From 0fea41d6b31b3bc6056e18675c4d08715f1a5357 Mon Sep 17 00:00:00 2001 From: Arie Date: Tue, 17 Feb 2015 09:26:49 -0800 Subject: [PATCH 0001/1979] Create LICENSE --- java-spanner-jdbc/LICENSE | 201 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 java-spanner-jdbc/LICENSE diff --git a/java-spanner-jdbc/LICENSE b/java-spanner-jdbc/LICENSE new file mode 100644 index 000000000000..4eedc0116add --- /dev/null +++ b/java-spanner-jdbc/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. From 19d7059973687e2f67093fa477c0d440d04e751c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 5 Aug 2019 18:54:15 +0200 Subject: [PATCH 0002/1979] Spanner JDBC: Add Spanner JDBC driver to google-cloud-contrib (#6007) add Spanner JDBC driver to google-cloud-contrib --- java-spanner-jdbc/README.md | 124 + java-spanner-jdbc/pom.xml | 193 + .../spanner/jdbc/AbstractBaseUnitOfWork.java | 162 + .../spanner/jdbc/AbstractJdbcConnection.java | 240 + .../jdbc/AbstractJdbcPreparedStatement.java | 394 + .../spanner/jdbc/AbstractJdbcResultSet.java | 626 + .../spanner/jdbc/AbstractJdbcStatement.java | 377 + .../spanner/jdbc/AbstractJdbcWrapper.java | 184 + .../jdbc/AbstractMultiUseTransaction.java | 96 + .../cloud/spanner/jdbc/AnalyzeMode.java | 52 + .../cloud/spanner/jdbc/AutocommitDmlMode.java | 42 + .../cloud/spanner/jdbc/ChecksumResultSet.java | 355 + .../spanner/jdbc/ClientSideStatement.java | 63 + .../jdbc/ClientSideStatementExecutor.java | 54 + .../spanner/jdbc/ClientSideStatementImpl.java | 217 + .../ClientSideStatementNoParamExecutor.java | 45 + .../jdbc/ClientSideStatementSetExecutor.java | 101 + .../ClientSideStatementValueConverter.java | 35 + .../ClientSideStatementValueConverters.java | 243 + .../spanner/jdbc/ClientSideStatements.java | 51 + .../jdbc/CloudSpannerJdbcConnection.java | 172 + .../google/cloud/spanner/jdbc/Connection.java | 704 + .../cloud/spanner/jdbc/ConnectionImpl.java | 989 ++ .../cloud/spanner/jdbc/ConnectionOptions.java | 592 + .../spanner/jdbc/ConnectionPreconditions.java | 45 + .../jdbc/ConnectionStatementExecutor.java | 78 + .../jdbc/ConnectionStatementExecutorImpl.java | 233 + .../spanner/jdbc/CredentialsService.java | 144 + .../google/cloud/spanner/jdbc/DdlBatch.java | 266 + .../google/cloud/spanner/jdbc/DdlClient.java | 91 + .../spanner/jdbc/DirectExecuteResultSet.java | 365 + .../google/cloud/spanner/jdbc/DmlBatch.java | 193 + .../cloud/spanner/jdbc/FailedBatchUpdate.java | 83 + .../cloud/spanner/jdbc/FailedQuery.java | 82 + .../cloud/spanner/jdbc/FailedUpdate.java | 67 + .../google/cloud/spanner/jdbc/JdbcArray.java | 204 + .../google/cloud/spanner/jdbc/JdbcBlob.java | 271 + .../google/cloud/spanner/jdbc/JdbcClob.java | 219 + .../cloud/spanner/jdbc/JdbcConnection.java | 401 + .../cloud/spanner/jdbc/JdbcConstants.java | 41 + .../cloud/spanner/jdbc/JdbcDataSource.java | 197 + .../cloud/spanner/jdbc/JdbcDataType.java | 267 + .../spanner/jdbc/JdbcDatabaseMetaData.java | 1538 +++ .../google/cloud/spanner/jdbc/JdbcDriver.java | 239 + .../spanner/jdbc/JdbcParameterMetaData.java | 160 + .../spanner/jdbc/JdbcParameterStore.java | 854 ++ .../cloud/spanner/jdbc/JdbcPreconditions.java | 70 + .../spanner/jdbc/JdbcPreparedStatement.java | 82 + .../cloud/spanner/jdbc/JdbcResultSet.java | 682 + .../spanner/jdbc/JdbcResultSetMetaData.java | 211 + .../cloud/spanner/jdbc/JdbcSqlException.java | 42 + .../spanner/jdbc/JdbcSqlExceptionFactory.java | 314 + .../cloud/spanner/jdbc/JdbcStatement.java | 364 + .../cloud/spanner/jdbc/JdbcTypeConverter.java | 274 + .../spanner/jdbc/ReadOnlyStalenessUtil.java | 261 + .../spanner/jdbc/ReadOnlyTransaction.java | 178 + .../spanner/jdbc/ReadWriteTransaction.java | 762 ++ .../jdbc/ReplaceableForwardingResultSet.java | 352 + .../spanner/jdbc/RetriableBatchUpdate.java | 69 + .../cloud/spanner/jdbc/RetriableUpdate.java | 64 + .../spanner/jdbc/SingleUseTransaction.java | 546 + .../cloud/spanner/jdbc/SpannerPool.java | 428 + .../jdbc/StatementExecutionInterceptor.java | 40 + .../cloud/spanner/jdbc/StatementExecutor.java | 189 + .../cloud/spanner/jdbc/StatementParser.java | 381 + .../cloud/spanner/jdbc/StatementResult.java | 101 + .../spanner/jdbc/StatementResultImpl.java | 187 + .../cloud/spanner/jdbc/TransactionMode.java | 46 + .../jdbc/TransactionRetryListener.java | 86 + .../google/cloud/spanner/jdbc/UnitOfWork.java | 182 + .../META-INF/services/java.sql.Driver | 1 + .../spanner/jdbc/ClientSideStatements.json | 246 + .../jdbc/DatabaseMetaData_GetColumns.sql | 78 + .../DatabaseMetaData_GetCrossReferences.sql | 34 + .../jdbc/DatabaseMetaData_GetExportedKeys.sql | 34 + .../jdbc/DatabaseMetaData_GetImportedKeys.sql | 34 + .../jdbc/DatabaseMetaData_GetIndexInfo.sql | 36 + .../jdbc/DatabaseMetaData_GetPrimaryKeys.sql | 29 + .../jdbc/DatabaseMetaData_GetSchemas.sql | 21 + .../jdbc/DatabaseMetaData_GetTables.sql | 30 + .../jdbc/AbstractConnectionImplTest.java | 918 ++ .../spanner/jdbc/AbstractJdbcWrapperTest.java | 179 + .../jdbc/AbstractSqlScriptVerifier.java | 456 + .../jdbc/AutocommitDmlModeConverterTest.java | 58 + .../spanner/jdbc/AutocommitDmlModeTest.java | 115 + .../spanner/jdbc/BooleanConverterTest.java | 51 + .../jdbc/ClientSideStatementsTest.java | 241 + .../ConnectionImplAutocommitReadOnlyTest.java | 914 ++ ...ConnectionImplAutocommitReadWriteTest.java | 1325 ++ .../ConnectionImplGeneratedSqlScriptTest.java | 120 + .../spanner/jdbc/ConnectionImplTest.java | 1117 ++ ...nnectionImplTransactionalReadOnlyTest.java | 1204 ++ ...nectionImplTransactionalReadWriteTest.java | 1945 +++ .../spanner/jdbc/ConnectionOptionsTest.java | 334 + .../jdbc/ConnectionStatementExecutorTest.java | 183 + ...nnectionStatementWithNoParametersTest.java | 155 + ...nnectionStatementWithOneParameterTest.java | 165 + .../spanner/jdbc/CredentialsServiceTest.java | 126 + .../cloud/spanner/jdbc/DdlBatchTest.java | 514 + .../cloud/spanner/jdbc/DdlClientTest.java | 69 + .../jdbc/DirectExecuteResultSetTest.java | 255 + .../cloud/spanner/jdbc/DmlBatchTest.java | 163 + .../spanner/jdbc/DurationConverterTest.java | 86 + .../spanner/jdbc/ITAbstractJdbcTest.java | 182 + .../spanner/jdbc/ITAbstractSpannerTest.java | 301 + .../cloud/spanner/jdbc/ITConnectionImpl.java | 25 + .../jdbc/JdbcAbortedTransactionTest.java | 380 + .../cloud/spanner/jdbc/JdbcArrayTest.java | 68 + .../cloud/spanner/jdbc/JdbcBlobTest.java | 349 + .../cloud/spanner/jdbc/JdbcClobTest.java | 329 + .../JdbcConnectionGeneratedSqlScriptTest.java | 62 + .../spanner/jdbc/JdbcConnectionTest.java | 416 + .../jdbc/JdbcDatabaseMetaDataTest.java | 434 + .../cloud/spanner/jdbc/JdbcDriverTest.java | 67 + .../spanner/jdbc/JdbcExceptionMatcher.java | 64 + .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 351 + .../spanner/jdbc/JdbcParameterStoreTest.java | 637 + .../jdbc/JdbcPreparedStatementTest.java | 325 + .../jdbc/JdbcResultSetMetaDataTest.java | 483 + .../cloud/spanner/jdbc/JdbcResultSetTest.java | 1141 ++ .../spanner/jdbc/JdbcSqlScriptVerifier.java | 185 + .../cloud/spanner/jdbc/JdbcStatementTest.java | 322 + .../spanner/jdbc/JdbcTimeoutSqlTest.java | 40 + .../jdbc/RandomResultSetGenerator.java | 166 + .../jdbc/ReadOnlyStalenessConverterTest.java | 166 + .../spanner/jdbc/ReadOnlyStalenessTest.java | 199 + .../jdbc/ReadOnlyStalenessUtilTest.java | 170 + .../spanner/jdbc/ReadOnlyTransactionTest.java | 403 + .../jdbc/ReadWriteTransactionTest.java | 581 + .../ReplaceableForwardingResultSetTest.java | 310 + .../SetReadOnlyStalenessSqlScriptTest.java | 47 + .../SetStatementTimeoutSqlScriptTest.java | 43 + .../jdbc/SingleUseTransactionTest.java | 740 + .../spanner/jdbc/SpannerExceptionMatcher.java | 65 + .../jdbc/SpannerJdbcExceptionMatcher.java | 70 + .../cloud/spanner/jdbc/SpannerPoolTest.java | 400 + .../cloud/spanner/jdbc/SqlScriptVerifier.java | 185 + .../spanner/jdbc/SqlTestScriptsGenerator.java | 27 + .../spanner/jdbc/StatementParserTest.java | 666 + .../spanner/jdbc/StatementResultImplTest.java | 177 + .../spanner/jdbc/StatementTimeoutTest.java | 1173 ++ .../jdbc/TransactionModeConverterTest.java | 71 + .../spanner/jdbc/it/ITBulkConnectionTest.java | 88 + .../cloud/spanner/jdbc/it/ITDdlTest.java | 37 + .../spanner/jdbc/it/ITJdbcConnectTest.java | 197 + .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 38 + .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 131 + .../it/ITJdbcReadWriteAutocommitTest.java | 75 + .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 238 + .../jdbc/it/ITReadOnlySpannerTest.java | 225 + .../it/ITReadWriteAutocommitSpannerTest.java | 179 + .../spanner/jdbc/it/ITSqlScriptTest.java | 203 + .../jdbc/it/ITTransactionModeTest.java | 187 + .../jdbc/it/ITTransactionRetryTest.java | 1586 +++ .../spanner/jdbc/ClientSideStatementsTest.sql | 11078 +++++++++++++++ .../cloud/spanner/jdbc/CommentsTest.sql | 302 + .../ConnectionImplGeneratedSqlScriptTest.sql | 11201 ++++++++++++++++ .../google/cloud/spanner/jdbc/ITDdlTest.sql | 189 + .../spanner/jdbc/ITReadOnlySpannerTest.sql | 261 + .../ITReadOnlySpannerTest_CreateTables.sql | 24 + .../jdbc/ITReadWriteAutocommitSpannerTest.sql | 216 + .../jdbc/ITSqlScriptTest_CreateTables.sql | 98 + .../jdbc/ITSqlScriptTest_InsertTestData.sql | 79 + .../ITSqlScriptTest_TestAutocommitDmlMode.sql | 87 + ...ITSqlScriptTest_TestAutocommitReadOnly.sql | 64 + ...ITSqlScriptTest_TestGetCommitTimestamp.sql | 138 + .../ITSqlScriptTest_TestGetReadTimestamp.sql | 112 + .../ITSqlScriptTest_TestInvalidStatements.sql | 32 + .../ITSqlScriptTest_TestReadOnlyStaleness.sql | 262 + .../ITSqlScriptTest_TestSetStatements.sql | 58 + .../ITSqlScriptTest_TestStatementTimeout.sql | 255 + ...qlScriptTest_TestTemporaryTransactions.sql | 67 + .../ITSqlScriptTest_TestTransactionMode.sql | 152 + ...criptTest_TestTransactionMode_ReadOnly.sql | 80 + .../spanner/jdbc/ITTransactionModeTest.sql | 114 + .../spanner/jdbc/SetReadOnlyStalenessTest.sql | 575 + .../spanner/jdbc/SetStatementTimeoutTest.sql | 158 + .../spanner/jdbc/TimeoutSqlScriptTest.sql | 54 + .../spanner/jdbc/test-key-app-default.json | 12 + .../spanner/jdbc/test-key-cloud-storage.json | 12 + .../google/cloud/spanner/jdbc/test-key.json | 12 + 181 files changed, 69992 insertions(+) create mode 100644 java-spanner-jdbc/README.md create mode 100644 java-spanner-jdbc/pom.xml create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java create mode 100644 java-spanner-jdbc/src/main/resources/META-INF/services/java.sql.Driver create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql create mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key.json diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md new file mode 100644 index 000000000000..26c755f9d03a --- /dev/null +++ b/java-spanner-jdbc/README.md @@ -0,0 +1,124 @@ +# JDBC Driver for Google Cloud Spanner + +JDBC Driver for +[Google Cloud Spanner](https://cloud.google.com/spanner/). + +## Quickstart + +[//]: # ({x-version-update-start:google-cloud-spanner-jdbc:released}) +If you are using Maven, add this to your pom.xml file +```xml + + com.google.cloud + google-cloud-spanner-jdbc + 0.1.0 + +``` +If you are using Gradle, add this to your dependencies +```Groovy +compile 'com.google.cloud:google-cloud-spanner-jdbc:0.1.0' +``` +If you are using SBT, add this to your dependencies +```Scala +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.1.0" +``` +[//]: # ({x-version-update-end}) + +## Getting Started +You can access Google Cloud Spanner through JDBC like this: + +```java +String url = "jdbc:cloudspanner:/projects/my_project_id/" + + "instances/my_instance_id/" + + "databases/my_database_name" + + "?credentials=/home/cloudspanner-keys/my-key.json" + + ";autocommit=false"; +try (Connection connection = DriverManager.getConnection(url)) { + try(ResultSet rs = connection.createStatement() + .executeQuery("SELECT SingerId, AlbumId, MarketingBudget FROM Albums")) { + while(rs.next()) { + Long singerId = rs.getLong(1); + } + } +} +``` + +### Connection URL +The JDBC connection URL must be specified in the following format: + +``` +jdbc:cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\?property-name=property-value[;property-name=property-value]*]? +``` + +The property-value strings should be url-encoded. + +The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This +placeholder will be replaced by the default project id of the environment that is requesting a +connection. +The supported connection properties are: + +* credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials, the default credentials of the environment as returned by {@link GoogleCredentials#getApplicationDefault()} will be used. +* autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. +* readonly (boolean): Sets the initial readonly mode for the connection. Default is false. +* retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the connection. Default is true. See +CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean) for more information. + +### Authentication +The JDBC Driver will either use the credentials that are specified in the connection URL, or if none specified, the default credentials of the environment. + +See the +[Authentication](https://github.com/googleapis/google-cloud-java#authentication) +section in the base directory's README for more information. + +## Examples + +The google-cloud-spanner-jdbc-examples project contains a number of examples on how to use the JDBC Driver. These include: + +* JdbcConnectExamples: Contains examples on how to obtain a JDBC connection for Cloud Spanner. +* JdbcAutocommitExamples: Contains examples on how to use a JDBC connection in autocommit mode. +* JdbcTransactionExamples: Contains examples on how to use the JDBC connection with read/write and read-only transactions. +* JdbcBatchExamples: Shows the batching capabilities of the Cloud Spanner JDBC Driver. +* JdbcVariablesExamples: Shows how to use custom SQL statements to read and write variables from a JDBC connection. +* JdbcCustomMethodsExample: Shows how to use the custom methods that are exposed by the `com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection` interface. + + +## Shaded JAR + +You can build a shaded JAR of the JDBC Driver to use with third-party tools using the following command: + +``` +mvn package -Pbuild-jdbc-driver +``` + +## Java Versions + +Java 7 or above is required for using this JDBC Driver. + +## Versioning + +This library follows [Semantic Versioning](http://semver.org/). + +## Contributing + +Contributions to this library are always welcome and highly encouraged. + +See `google-cloud`'s [CONTRIBUTING] documentation and the +[shared documentation](https://github.com/googleapis/google-cloud-common/blob/master/contributing/readme.md#how-to-contribute-to-gcloud) +for more information on how to get started. + +Please note that this project is released with a Contributor Code of Conduct. +By participating in this project you agree to abide by its terms. See +[Code of Conduct][code-of-conduct] for more information. + +## License + +Apache 2.0 - See [LICENSE] for more information. + + +[CONTRIBUTING]:https://github.com/googleapis/google-cloud-java/blob/master/CONTRIBUTING.md +[code-of-conduct]:https://github.com/googleapis/google-cloud-java/blob/master/CODE_OF_CONDUCT.md#contributor-code-of-conduct +[LICENSE]: https://github.com/googleapis/google-cloud-java/blob/master/LICENSE +[cloud-platform]: https://cloud.google.com/ + +[cloud-spanner]: https://cloud.google.com/spanner/ +[cloud-spanner-docs]: https://cloud.google.com/spanner/docs/overview diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml new file mode 100644 index 000000000000..b32661ac5142 --- /dev/null +++ b/java-spanner-jdbc/pom.xml @@ -0,0 +1,193 @@ + + + 4.0.0 + google-cloud-spanner-jdbc + 0.1.0 + jar + Google Cloud Spanner JDBC + https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc + + JDBC driver for Google Cloud Spanner. + + + com.google.cloud + google-cloud-contrib + 0.103.1-alpha-SNAPSHOT + + + google-cloud-spanner-jdbc + + + + ${project.groupId} + google-cloud-spanner + + + com.google.cloud + google-cloud-storage + + + ${project.groupId} + google-cloud-spanner + 1.30.1-SNAPSHOT + test-jar + test + + + com.google.api + gax-grpc + testlib + test + + + com.google.truth + truth + test + + + org.mockito + mockito-core + 1.9.5 + test + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.5 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + com.google.cloud.spanner.IntegrationTest + sponge_log + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M3 + + + com.google.cloud.spanner.GceTestEnvConfig + projects/gcloud-devel/instances/spanner-testing + + com.google.cloud.spanner.IntegrationTest + com.google.cloud.spanner.FlakyTest + 2400 + + + + + integration-test + + + + + + + + + + generate-test-sql-scripts + + + + org.codehaus.mojo + exec-maven-plugin + + + generateTestScripts + compile + + java + + + com.google.cloud.spanner.jdbc.SqlTestScriptsGenerator + + + do_log_statements + true + + + test + false + + + + + + + + + + build-jdbc-driver + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + + shade + + + true + true + false + false + + + *:* + + + java:* + junit:* + + + + + + META-INF/services + java.sql.Driver + + + com.google.cloud.spanner.jdbc + ClientSideStatements.json + + + com.google.cloud.spanner.jdbc + *.sql + + + + + + + + + + + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java new file mode 100644 index 000000000000..099fd36e3579 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java @@ -0,0 +1,162 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.StatementExecutor.StatementTimeout; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.concurrent.GuardedBy; + +/** Base for all {@link Connection}-based transactions and batches. */ +abstract class AbstractBaseUnitOfWork implements UnitOfWork { + private final StatementExecutor statementExecutor; + private final StatementTimeout statementTimeout; + + /** + * The {@link Future} that monitors the result of the statement currently being executed for this + * unit of work. + */ + @GuardedBy("this") + private Future currentlyRunningStatementFuture = null; + + enum InterceptorsUsage { + INVOKE_INTERCEPTORS, + IGNORE_INTERCEPTORS; + } + + abstract static class Builder, T extends AbstractBaseUnitOfWork> { + private StatementExecutor statementExecutor; + private StatementTimeout statementTimeout = new StatementTimeout(); + + Builder() {} + + @SuppressWarnings("unchecked") + B self() { + return (B) this; + } + + B withStatementExecutor(StatementExecutor executor) { + Preconditions.checkNotNull(executor); + this.statementExecutor = executor; + return self(); + } + + B setStatementTimeout(StatementTimeout timeout) { + Preconditions.checkNotNull(timeout); + this.statementTimeout = timeout; + return self(); + } + + abstract T build(); + } + + AbstractBaseUnitOfWork(Builder builder) { + Preconditions.checkState(builder.statementExecutor != null, "No statement executor specified"); + this.statementExecutor = builder.statementExecutor; + this.statementTimeout = builder.statementTimeout; + } + + StatementExecutor getStatementExecutor() { + return statementExecutor; + } + + StatementTimeout getStatementTimeout() { + return statementTimeout; + } + + @Override + public void cancel() { + synchronized (this) { + if (currentlyRunningStatementFuture != null + && !currentlyRunningStatementFuture.isDone() + && !currentlyRunningStatementFuture.isCancelled()) { + currentlyRunningStatementFuture.cancel(true); + } + } + } + + T asyncExecuteStatement(ParsedStatement statement, Callable callable) { + return asyncExecuteStatement(statement, callable, InterceptorsUsage.INVOKE_INTERCEPTORS); + } + + T asyncExecuteStatement( + ParsedStatement statement, Callable callable, InterceptorsUsage interceptorUsage) { + Preconditions.checkNotNull(statement); + Preconditions.checkNotNull(callable); + + if (interceptorUsage == InterceptorsUsage.INVOKE_INTERCEPTORS) { + statementExecutor.invokeInterceptors( + statement, StatementExecutionStep.EXECUTE_STATEMENT, this); + } + Future future = statementExecutor.submit(callable); + synchronized (this) { + this.currentlyRunningStatementFuture = future; + } + T res; + try { + if (statementTimeout.hasTimeout()) { + TimeUnit unit = statementTimeout.getAppropriateTimeUnit(); + res = future.get(statementTimeout.getTimeoutValue(unit), unit); + } else { + res = future.get(); + } + } catch (TimeoutException e) { + // statement timed out, cancel the execution + future.cancel(true); + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.DEADLINE_EXCEEDED, + "Statement execution timeout occurred for " + statement.getSqlWithoutComments(), + e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + Set causes = new HashSet<>(); + while (cause != null && !causes.contains(cause)) { + if (cause instanceof SpannerException) { + throw (SpannerException) cause; + } + causes.add(cause); + cause = cause.getCause(); + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.UNKNOWN, + "Statement execution failed for " + statement.getSqlWithoutComments(), + e); + } catch (InterruptedException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "Statement execution was interrupted", e); + } catch (CancellationException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "Statement execution was cancelled", e); + } finally { + synchronized (this) { + this.currentlyRunningStatementFuture = null; + } + } + return res; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java new file mode 100644 index 000000000000..71a1c20a62e2 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -0,0 +1,240 @@ +/* + * Copyright 2019 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.common.annotations.VisibleForTesting; +import com.google.rpc.Code; +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Struct; +import java.util.Properties; +import java.util.concurrent.Executor; + +/** Base class for Cloud Spanner JDBC connections. */ +abstract class AbstractJdbcConnection extends AbstractJdbcWrapper + implements CloudSpannerJdbcConnection { + private static final String CALLABLE_STATEMENTS_UNSUPPORTED = + "Callable statements are not supported"; + private static final String ONLY_SERIALIZABLE = + "Only isolation level TRANSACTION_SERIALIZABLE is supported"; + private static final String ONLY_CLOSE_ALLOWED = + "Only holdability CLOSE_CURSORS_AT_COMMIT is supported"; + private static final String SAVEPOINTS_UNSUPPORTED = "Savepoints are not supported"; + private static final String SQLXML_UNSUPPORTED = "SQLXML is not supported"; + private static final String STRUCTS_UNSUPPORTED = "Structs are not supported"; + private static final String ABORT_UNSUPPORTED = "Abort is not supported"; + private static final String NETWORK_TIMEOUT_UNSUPPORTED = "Network timeout is not supported"; + static final String CLIENT_INFO_NOT_SUPPORTED = + "Cloud Spanner does not support any ClientInfo properties"; + + private final String connectionUrl; + private final ConnectionOptions options; + private final com.google.cloud.spanner.jdbc.Connection spanner; + + private SQLWarning firstWarning = null; + private SQLWarning lastWarning = null; + + AbstractJdbcConnection(String connectionUrl, ConnectionOptions options) { + this.connectionUrl = connectionUrl; + this.options = options; + this.spanner = options.getConnection(); + } + + /** Return the corresponding {@link com.google.cloud.spanner.jdbc.Connection} */ + com.google.cloud.spanner.jdbc.Connection getSpannerConnection() { + return spanner; + } + + @Override + public String getConnectionUrl() { + return connectionUrl; + } + + ConnectionOptions getConnectionOptions() { + return options; + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return checkClosedAndThrowUnsupported(CALLABLE_STATEMENTS_UNSUPPORTED); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return checkClosedAndThrowUnsupported(CALLABLE_STATEMENTS_UNSUPPORTED); + } + + @Override + public CallableStatement prepareCall( + String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return checkClosedAndThrowUnsupported(CALLABLE_STATEMENTS_UNSUPPORTED); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + checkClosed(); + JdbcPreconditions.checkArgument( + level == TRANSACTION_SERIALIZABLE + || level == TRANSACTION_REPEATABLE_READ + || level == TRANSACTION_READ_UNCOMMITTED + || level == TRANSACTION_READ_COMMITTED, + "Not a transaction isolation level"); + JdbcPreconditions.checkSqlFeatureSupported( + level == TRANSACTION_SERIALIZABLE, ONLY_SERIALIZABLE); + } + + @Override + public int getTransactionIsolation() throws SQLException { + checkClosed(); + return TRANSACTION_SERIALIZABLE; + } + + @Override + public void setHoldability(int holdability) throws SQLException { + checkClosed(); + JdbcPreconditions.checkArgument( + holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT + || holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT, + "Not a holdability value"); + JdbcPreconditions.checkSqlFeatureSupported( + holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT, ONLY_CLOSE_ALLOWED); + } + + @Override + public int getHoldability() throws SQLException { + checkClosed(); + return ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + checkClosed(); + return firstWarning; + } + + @Override + public void clearWarnings() throws SQLException { + checkClosed(); + firstWarning = null; + lastWarning = null; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return checkClosedAndThrowUnsupported(SQLXML_UNSUPPORTED); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + try { + checkClosed(); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + throw JdbcSqlExceptionFactory.clientInfoException( + e.getMessage(), ((JdbcSqlException) e).getCode()); + } else { + throw JdbcSqlExceptionFactory.clientInfoException(e.getMessage(), Code.UNKNOWN); + } + } + pushWarning(new SQLWarning(CLIENT_INFO_NOT_SUPPORTED)); + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + try { + checkClosed(); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + throw JdbcSqlExceptionFactory.clientInfoException( + e.getMessage(), ((JdbcSqlException) e).getCode()); + } else { + throw JdbcSqlExceptionFactory.clientInfoException(e.getMessage(), Code.UNKNOWN); + } + } + pushWarning(new SQLWarning(CLIENT_INFO_NOT_SUPPORTED)); + } + + @Override + public String getClientInfo(String name) throws SQLException { + checkClosed(); + return null; + } + + @Override + public Properties getClientInfo() throws SQLException { + checkClosed(); + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return checkClosedAndThrowUnsupported(STRUCTS_UNSUPPORTED); + } + + @Override + public void abort(Executor executor) throws SQLException { + checkClosedAndThrowUnsupported(ABORT_UNSUPPORTED); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + checkClosedAndThrowUnsupported(NETWORK_TIMEOUT_UNSUPPORTED); + } + + @Override + public int getNetworkTimeout() throws SQLException { + return checkClosedAndThrowUnsupported(NETWORK_TIMEOUT_UNSUPPORTED); + } + + @VisibleForTesting + void pushWarning(SQLWarning warning) { + if (lastWarning == null) { + firstWarning = warning; + lastWarning = warning; + } else { + lastWarning.setNextWarning(warning); + lastWarning = warning; + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java new file mode 100644 index 000000000000..ef0c5af4b907 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -0,0 +1,394 @@ +/* + * Copyright 2019 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.rpc.Code; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; + +/** Base class for Cloud Spanner {@link PreparedStatement}s. */ +abstract class AbstractJdbcPreparedStatement extends JdbcStatement implements PreparedStatement { + private static final String METHOD_NOT_ON_PREPARED_STATEMENT = + "This method may not be called on a PreparedStatement"; + private final JdbcParameterStore parameters = new JdbcParameterStore(); + + AbstractJdbcPreparedStatement(JdbcConnection connection) { + super(connection); + } + + JdbcParameterStore getParameters() { + return parameters; + } + + private T checkClosedAndThrowNotOnPreparedStatement() throws SQLException { + checkClosed(); + throw JdbcSqlExceptionFactory.of(METHOD_NOT_ON_PREPARED_STATEMENT, Code.INVALID_ARGUMENT); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + return checkClosedAndThrowNotOnPreparedStatement(); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return checkClosedAndThrowNotOnPreparedStatement(); + } + + @Override + public boolean execute(String sql) throws SQLException { + return checkClosedAndThrowNotOnPreparedStatement(); + } + + @Override + public void addBatch(String sql) throws SQLException { + checkClosedAndThrowNotOnPreparedStatement(); + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, null, sqlType, null); + } + + @Override + public void setBoolean(int parameterIndex, boolean value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BOOLEAN); + } + + @Override + public void setByte(int parameterIndex, byte value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.TINYINT); + } + + @Override + public void setShort(int parameterIndex, short value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.SMALLINT); + } + + @Override + public void setInt(int parameterIndex, int value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.INTEGER); + } + + @Override + public void setLong(int parameterIndex, long value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BIGINT); + } + + @Override + public void setFloat(int parameterIndex, float value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.FLOAT); + } + + @Override + public void setDouble(int parameterIndex, double value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.DOUBLE); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.DECIMAL); + } + + @Override + public void setString(int parameterIndex, String value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR); + } + + @Override + public void setBytes(int parameterIndex, byte[] value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BINARY); + } + + @Override + public void setDate(int parameterIndex, Date value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.DATE); + } + + @Override + public void setTime(int parameterIndex, Time value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.TIME); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.TIMESTAMP); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream value, int length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.VARCHAR, length); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream value, int length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream value, int length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BINARY, length); + } + + @Override + public void clearParameters() throws SQLException { + checkClosed(); + parameters.clearParameters(); + } + + @Override + public void setObject(int parameterIndex, Object value, int targetSqlType) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, targetSqlType, null); + } + + @Override + public void setObject(int parameterIndex, Object value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, null); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.NVARCHAR, length); + } + + @Override + public void setRef(int parameterIndex, Ref value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.REF); + } + + @Override + public void setBlob(int parameterIndex, Blob value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BLOB); + } + + @Override + public void setClob(int parameterIndex, Clob value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.CLOB); + } + + @Override + public void setArray(int parameterIndex, Array value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.ARRAY); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + checkClosed(); + try (ResultSet rs = executeQuery()) { + return rs.getMetaData(); + } + } + + @Override + public void setDate(int parameterIndex, Date value, Calendar cal) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.DATE); + } + + @Override + public void setTime(int parameterIndex, Time value, Calendar cal) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.TIME); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp value, Calendar cal) throws SQLException { + checkClosed(); + parameters.setParameter( + parameterIndex, + cal == null ? value : JdbcTypeConverter.setTimestampInCalendar(value, cal), + Types.TIMESTAMP); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, null, sqlType, null); + } + + @Override + public void setURL(int parameterIndex, URL value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR); + } + + @Override + public void setRowId(int parameterIndex, RowId value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.ROWID); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NCLOB); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.CLOB); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, inputStream, Types.BLOB); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.NCLOB); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, xmlObject, Types.SQLXML); + } + + @Override + public void setObject(int parameterIndex, Object value, int targetSqlType, int scaleOrLength) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, targetSqlType, scaleOrLength); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream value, long length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.VARCHAR); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream value, long length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BINARY); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.NVARCHAR); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.VARCHAR); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.BINARY); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.NVARCHAR); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, Types.NVARCHAR); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.CLOB); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, inputStream, Types.BLOB); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, reader, Types.NVARCHAR); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java new file mode 100644 index 000000000000..a85a3d3de244 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java @@ -0,0 +1,626 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; + +/** Base class for Cloud Spanner {@link ResultSet}s. */ +abstract class AbstractJdbcResultSet extends AbstractJdbcWrapper implements ResultSet { + /** The underlying Cloud Spanner {@link com.google.cloud.spanner.ResultSet}. */ + final com.google.cloud.spanner.ResultSet spanner; + + AbstractJdbcResultSet(com.google.cloud.spanner.ResultSet spanner) { + this.spanner = spanner; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException {} + + @Override + public String getCursorName() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean isLast() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void beforeFirst() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void afterLast() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean first() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean last() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean absolute(int row) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean relative(int rows) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public boolean previous() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + JdbcPreconditions.checkArgument(direction == FETCH_FORWARD, direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return FETCH_FORWARD; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + // no-op + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getType() throws SQLException { + return TYPE_FORWARD_ONLY; + } + + @Override + public int getConcurrency() throws SQLException { + return CONCUR_READ_ONLY; + } + + @Override + public boolean rowUpdated() throws SQLException { + return false; + } + + @Override + public boolean rowInserted() throws SQLException { + return false; + } + + @Override + public boolean rowDeleted() throws SQLException { + return false; + } + + @Override + public void updateNull(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateByte(int columnIndex, byte x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateShort(int columnIndex, short x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateInt(int columnIndex, int x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateLong(int columnIndex, long x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateFloat(int columnIndex, float x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDouble(int columnIndex, double x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateString(int columnIndex, String x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDate(int columnIndex, Date x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTime(int columnIndex, Time x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNull(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBoolean(String columnLabel, boolean x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateByte(String columnLabel, byte x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateShort(String columnLabel, short x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateInt(String columnLabel, int x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateLong(String columnLabel, long x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateFloat(String columnLabel, float x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDouble(String columnLabel, double x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateString(String columnLabel, String x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBytes(String columnLabel, byte[] x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateDate(String columnLabel, Date x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTime(String columnLabel, Time x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(String columnLabel, Object x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void insertRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void deleteRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void refreshRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void cancelRowUpdates() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void moveToInsertRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void moveToCurrentRow() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Ref getRef(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Ref getRef(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRef(int columnIndex, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRef(String columnLabel, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateArray(int columnIndex, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateArray(String columnLabel, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public RowId getRowId(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public RowId getRowId(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRowId(int columnIndex, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateRowId(String columnLabel, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNString(int columnIndex, String nString) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNString(String columnLabel, String nString) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public SQLXML getSQLXML(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public SQLXML getSQLXML(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(int columnIndex, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateClob(String columnLabel, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java new file mode 100644 index 000000000000..ef52e5be1f56 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -0,0 +1,377 @@ +/* + * Copyright 2019 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; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.jdbc.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.concurrent.TimeUnit; + +/** Base class for Cloud Spanner JDBC {@link Statement}s */ +abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Statement { + private static final String CURSORS_NOT_SUPPORTED = "Cursors are not supported"; + private static final String ONLY_FETCH_FORWARD_SUPPORTED = "Only fetch_forward is supported"; + private boolean closed; + private boolean closeOnCompletion; + private boolean poolable; + private final JdbcConnection connection; + private int queryTimeout; + + AbstractJdbcStatement(JdbcConnection connection) { + this.connection = connection; + } + + @Override + public JdbcConnection getConnection() { + return connection; + } + + private Options.QueryOption[] getQueryOptions() throws SQLException { + if (getFetchSize() > 0) { + return new Options.ReadAndQueryOption[] {Options.prefetchChunks(getFetchSize())}; + } + return new QueryOption[0]; + } + + /** The {@link TimeUnit}s that are supported for timeout and staleness durations */ + private static final TimeUnit[] SUPPORTED_UNITS = + new TimeUnit[] { + TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS + }; + + /** + * Get the {@link TimeUnit} with the least precision that is able to represent the timeout of this + * statement. + */ + private TimeUnit getAppropriateTimeUnit() { + int index = 0; + if (connection.getSpannerConnection().hasStatementTimeout()) { + for (TimeUnit unit : SUPPORTED_UNITS) { + long duration = connection.getSpannerConnection().getStatementTimeout(unit); + if (index + 1 < SUPPORTED_UNITS.length) { + if (duration > 0L + && duration * 1000 + == connection + .getSpannerConnection() + .getStatementTimeout(SUPPORTED_UNITS[index + 1])) { + return unit; + } + } else { + // last unit, we have to use this one + return unit; + } + index++; + } + throw new IllegalStateException("Unsupported duration"); + } + return null; + } + + /** + * Local class to temporarily hold the statement timeout of the Spanner {@link Connection}. The + * Spanner connection API sets the timeout on the connection and applies it to all statements that + * are executed on the {@link Connection}. JDBC specifies a timeout per statement, so we need to + * temporarily hold on to the timeout specified for the connection while using the timeout + * specified for a JDBC statement, and then after executing the JDBC statement setting the timeout + * on the Spanner {@link Connection} again. + */ + private static class StatementTimeout { + private final long timeout; + private final TimeUnit unit; + + private static StatementTimeout of(long timeout, TimeUnit unit) { + return new StatementTimeout(timeout, unit); + } + + private StatementTimeout(long timeout, TimeUnit unit) { + this.timeout = timeout; + this.unit = unit; + } + } + + /** + * 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 + * be reset after the execution of a statement + */ + private StatementTimeout setTemporaryStatementTimeout() throws SQLException { + StatementTimeout originalTimeout = null; + if (getQueryTimeout() > 0) { + if (connection.getSpannerConnection().hasStatementTimeout()) { + TimeUnit unit = getAppropriateTimeUnit(); + originalTimeout = + StatementTimeout.of(connection.getSpannerConnection().getStatementTimeout(unit), unit); + } + connection.getSpannerConnection().setStatementTimeout(getQueryTimeout(), TimeUnit.SECONDS); + } + return originalTimeout; + } + + /** + * Resets the statement timeout of the Spanner {@link Connection} after a JDBC {@link Statement} + * has been executed. + */ + private void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLException { + if (getQueryTimeout() > 0) { + if (originalTimeout == null) { + connection.getSpannerConnection().clearStatementTimeout(); + } else { + connection + .getSpannerConnection() + .setStatementTimeout(originalTimeout.timeout, originalTimeout.unit); + } + } + } + + /** + * Executes a SQL statement on the connection of this {@link Statement} as a query. + * + * @param statement The SQL statement to executed. + * @return the result of the SQL statement as a {@link ResultSet}. + * @throws SQLException if a database error occurs. + */ + ResultSet executeQuery(com.google.cloud.spanner.Statement statement) throws SQLException { + StatementTimeout originalTimeout = setTemporaryStatementTimeout(); + try { + return JdbcResultSet.of( + this, connection.getSpannerConnection().executeQuery(statement, getQueryOptions())); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } finally { + 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 { + StatementTimeout originalTimeout = setTemporaryStatementTimeout(); + try { + long count = connection.getSpannerConnection().executeUpdate(statement); + if (count > Integer.MAX_VALUE) { + throw JdbcSqlExceptionFactory.of( + "update count too large for executeUpdate: " + count, Code.OUT_OF_RANGE); + } + return (int) count; + } 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. + * + * @param statement The SQL statement to execute. + * @return a {@link StatementResult} containing either a {@link ResultSet}, an update count or + * nothing depending on the type of SQL statement. + * @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, result, originalTimeout); + } + return result; + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } finally { + if (mustResetTimeout) { + resetStatementTimeout(originalTimeout); + } + } + } + + /** + * The Spanner Connection API sets the statement timeout on a {@link Connection}. JDBC on the + * other hand sets this on the {@link Statement} object. This means that when a JDBC statement has + * a query timeout set, we need to temporarily set the statement timeout on the underlying Spanner + * {@link Connection}, then execute the actual statement, and then reset the timeout on the + * Spanner connection. But if the executed statement was a SHOW STATEMENT_TIMEOUT or SET + * STATEMENT_TIMEOUT, then we need to handle it differently: + * + *
    + *
  • SHOW STATEMENT_TIMEOUT: Reset the statement timeout on the {@link Connection} to the + * original value and re-run the statement + *
  • SET STATEMENT_TIMEOUT: Do not reset the statement timeout on the {@link Connection} after + * the execution + *
+ * + * @param result The result of a statement that was executed. + * @return true if the {@link StatementResult} indicates that the statement that was + * executed was a SET STATEMENT_TIMEOUT statement. + */ + private boolean resultIsSetStatementTimeout(StatementResult result) { + return result.getClientSideStatementType() == ClientSideStatementType.SET_STATEMENT_TIMEOUT; + } + + private boolean resultIsShowStatementTimeout(StatementResult result) { + return result.getClientSideStatementType() == ClientSideStatementType.SHOW_STATEMENT_TIMEOUT; + } + + private StatementResult rerunShowStatementTimeout( + com.google.cloud.spanner.Statement statement, + StatementResult result, + StatementTimeout originalTimeout) + throws SQLException { + resetStatementTimeout(originalTimeout); + return connection.getSpannerConnection().execute(statement); + } + + @Override + public int getQueryTimeout() throws SQLException { + checkClosed(); + return queryTimeout; + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + checkClosed(); + this.queryTimeout = seconds; + } + + @Override + public void cancel() throws SQLException { + checkClosed(); + connection.getSpannerConnection().cancel(); + } + + @Override + public void close() throws SQLException { + this.closed = true; + } + + @Override + public boolean isClosed() throws SQLException { + return closed; + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + checkClosed(); + this.poolable = poolable; + } + + @Override + public boolean isPoolable() throws SQLException { + checkClosed(); + return poolable; + } + + @Override + public void closeOnCompletion() throws SQLException { + checkClosed(); + this.closeOnCompletion = true; + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + checkClosed(); + return closeOnCompletion; + } + + @Override + public int getMaxFieldSize() throws SQLException { + checkClosed(); + return 0; + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + checkClosed(); + } + + @Override + public int getMaxRows() throws SQLException { + checkClosed(); + return 0; + } + + @Override + public void setMaxRows(int max) throws SQLException { + checkClosed(); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + checkClosed(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + checkClosed(); + return null; + } + + @Override + public void clearWarnings() throws SQLException { + checkClosed(); + } + + @Override + public void setCursorName(String name) throws SQLException { + throw JdbcSqlExceptionFactory.unsupported(CURSORS_NOT_SUPPORTED); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + if (direction != ResultSet.FETCH_FORWARD) { + throw JdbcSqlExceptionFactory.unsupported(ONLY_FETCH_FORWARD_SUPPORTED); + } + } + + @Override + public int getFetchDirection() throws SQLException { + return ResultSet.FETCH_FORWARD; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return ResultSet.CONCUR_READ_ONLY; + } + + @Override + public int getResultSetType() throws SQLException { + return ResultSet.TYPE_FORWARD_ONLY; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return ResultSet.CLOSE_CURSORS_AT_COMMIT; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java new file mode 100644 index 000000000000..abfa0f58d8ad --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -0,0 +1,184 @@ +/* + * Copyright 2019 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.Type; +import com.google.cloud.spanner.Type.Code; +import com.google.common.base.Preconditions; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.Timestamp; +import java.sql.Types; +import java.sql.Wrapper; + +/** Base class for all Cloud Spanner JDBC classes that implement the {@link Wrapper} interface. */ +abstract class AbstractJdbcWrapper implements Wrapper { + static final String OTHER_NAME = "OTHER"; + + /** + * Extract {@link java.sql.Types} code from Spanner {@link Type}. + * + * @param type The Cloud Spanner type to convert. May not be null. + */ + static int extractColumnType(Type type) { + Preconditions.checkNotNull(type); + if (type.equals(Type.bool())) return Types.BOOLEAN; + if (type.equals(Type.bytes())) return Types.BINARY; + if (type.equals(Type.date())) return Types.DATE; + if (type.equals(Type.float64())) return Types.DOUBLE; + if (type.equals(Type.int64())) return Types.BIGINT; + if (type.equals(Type.string())) return Types.NVARCHAR; + if (type.equals(Type.timestamp())) return Types.TIMESTAMP; + if (type.getCode() == Code.ARRAY) return Types.ARRAY; + return Types.OTHER; + } + + /** Extract Spanner type name from {@link java.sql.Types} code. */ + static String getSpannerTypeName(int sqlType) { + if (sqlType == Types.BOOLEAN) return Type.bool().getCode().name(); + if (sqlType == Types.BINARY) return Type.bytes().getCode().name(); + if (sqlType == Types.DATE) return Type.date().getCode().name(); + if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Type.float64().getCode().name(); + if (sqlType == Types.BIGINT + || sqlType == Types.INTEGER + || sqlType == Types.SMALLINT + || sqlType == Types.TINYINT) return Type.int64().getCode().name(); + if (sqlType == Types.NVARCHAR) return Type.string().getCode().name(); + if (sqlType == Types.TIMESTAMP) return Type.timestamp().getCode().name(); + if (sqlType == Types.ARRAY) return Code.ARRAY.name(); + + return OTHER_NAME; + } + + /** Get corresponding Java class name from {@link java.sql.Types} code. */ + static String getClassName(int sqlType) { + if (sqlType == Types.BOOLEAN) return Boolean.class.getName(); + if (sqlType == Types.BINARY) return Byte[].class.getName(); + if (sqlType == Types.DATE) return Date.class.getName(); + if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Double.class.getName(); + if (sqlType == Types.BIGINT + || sqlType == Types.INTEGER + || sqlType == Types.SMALLINT + || sqlType == Types.TINYINT) return Long.class.getName(); + if (sqlType == Types.NVARCHAR) return String.class.getName(); + if (sqlType == Types.TIMESTAMP) return Timestamp.class.getName(); + if (sqlType == Types.ARRAY) return Object.class.getName(); + + return null; + } + + /** + * Get corresponding Java class name from Spanner {@link Type}. + * + * @param type The Cloud Spanner type to convert. May not be null. + */ + static String getClassName(Type type) { + Preconditions.checkNotNull(type); + if (type == Type.bool()) return Boolean.class.getName(); + if (type == Type.bytes()) return byte[].class.getName(); + if (type == Type.date()) return Date.class.getName(); + if (type == Type.float64()) return Double.class.getName(); + if (type == Type.int64()) return Long.class.getName(); + if (type == Type.string()) return String.class.getName(); + if (type == Type.timestamp()) return Timestamp.class.getName(); + if (type.getCode() == Code.ARRAY) { + if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); + if (type.getArrayElementType() == Type.bytes()) return byte[][].class.getName(); + if (type.getArrayElementType() == Type.date()) return Date[].class.getName(); + if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); + if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); + if (type.getArrayElementType() == Type.string()) return String[].class.getName(); + if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); + } + return null; + } + + /** Standard error message for out-of-range values. */ + private static final String OUT_OF_RANGE_MSG = "Value out of range for %s: %s"; + + /** Cast value and throw {@link SQLException} if out-of-range. */ + static byte checkedCastToByte(long val) throws SQLException { + if (val > Byte.MAX_VALUE || val < Byte.MIN_VALUE) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "byte", val), com.google.rpc.Code.OUT_OF_RANGE); + } + return (byte) val; + } + + /** Cast value and throw {@link SQLException} if out-of-range. */ + static short checkedCastToShort(long val) throws SQLException { + if (val > Short.MAX_VALUE || val < Short.MIN_VALUE) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "short", val), com.google.rpc.Code.OUT_OF_RANGE); + } + return (short) val; + } + + /** Cast value and throw {@link SQLException} if out-of-range. */ + static int checkedCastToInt(long val) throws SQLException { + if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "int", val), com.google.rpc.Code.OUT_OF_RANGE); + } + return (int) val; + } + + /** Cast value and throw {@link SQLException} if out-of-range. */ + static float checkedCastToFloat(double val) throws SQLException { + if (val > Float.MAX_VALUE || val < -Float.MAX_VALUE) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "float", val), com.google.rpc.Code.OUT_OF_RANGE); + } + return (float) val; + } + + /** Should return true if this object has been closed */ + public abstract boolean isClosed() throws SQLException; + + /** Throws a {@link SQLException} if this object is closed */ + void checkClosed() throws SQLException { + if (isClosed()) { + throw JdbcSqlExceptionFactory.of( + "This " + getClass().getName() + " has been closed", + com.google.rpc.Code.FAILED_PRECONDITION); + } + } + + /** + * Throws a {@link SQLException} if this object is closed and otherwise a {@link + * SQLFeatureNotSupportedException} with the given message + */ + T checkClosedAndThrowUnsupported(String message) throws SQLException { + checkClosed(); + throw JdbcSqlExceptionFactory.unsupported(message); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return iface != null && iface.isAssignableFrom(getClass()); + } + + @Override + public T unwrap(Class iface) throws SQLException { + if (isWrapperFor(iface)) { + return iface.cast(this); + } + throw JdbcSqlExceptionFactory.of( + "Cannot unwrap to " + iface.getName(), com.google.rpc.Code.INVALID_ARGUMENT); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java new file mode 100644 index 000000000000..6468c0042da3 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java @@ -0,0 +1,96 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; +import java.util.concurrent.Callable; + +/** + * Base class for {@link Connection}-based transactions that can be used for multiple read and + * read/write statements. + */ +abstract class AbstractMultiUseTransaction extends AbstractBaseUnitOfWork { + + AbstractMultiUseTransaction(Builder builder) { + super(builder); + } + + @Override + public Type getType() { + return Type.TRANSACTION; + } + + @Override + public boolean isActive() { + return getState().isActive(); + } + + /** + * Check that the current transaction actually has a valid underlying transaction. If not, the + * method will throw a {@link SpannerException}. + */ + abstract void checkValidTransaction(); + + /** Returns the {@link ReadContext} that can be used for queries on this transaction. */ + abstract ReadContext getReadContext(); + + @Override + public ResultSet executeQuery( + final ParsedStatement statement, + final AnalyzeMode analyzeMode, + final QueryOption... options) { + Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); + checkValidTransaction(); + return asyncExecuteStatement( + statement, + new Callable() { + @Override + public ResultSet call() throws Exception { + return DirectExecuteResultSet.ofResultSet( + internalExecuteQuery(statement, analyzeMode, options)); + } + }); + } + + ResultSet internalExecuteQuery( + final ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { + if (analyzeMode == AnalyzeMode.NONE) { + return getReadContext().executeQuery(statement.getStatement(), options); + } + return getReadContext() + .analyzeQuery(statement.getStatement(), analyzeMode.getQueryAnalyzeMode()); + } + + @Override + public long[] runBatch() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for transactions"); + } + + @Override + public void abortBatch() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for transactions"); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java new file mode 100644 index 000000000000..457ceec2a128 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java @@ -0,0 +1,52 @@ +/* + * Copyright 2019 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.ReadContext.QueryAnalyzeMode; + +/** + * {@link AnalyzeMode} indicates whether a query should be executed as a normal query (NONE), + * whether only a query plan should be returned, or whether the query should be profiled while + * executed. + */ +enum AnalyzeMode { + NONE(null), + PLAN(QueryAnalyzeMode.PLAN), + PROFILE(QueryAnalyzeMode.PROFILE); + + private final QueryAnalyzeMode mode; + + private AnalyzeMode(QueryAnalyzeMode mode) { + this.mode = mode; + } + + QueryAnalyzeMode getQueryAnalyzeMode() { + return mode; + } + + /** Translates from the Spanner client library QueryAnalyzeMode to {@link AnalyzeMode}. */ + static AnalyzeMode of(QueryAnalyzeMode mode) { + switch (mode) { + case PLAN: + return AnalyzeMode.PLAN; + case PROFILE: + return AnalyzeMode.PROFILE; + default: + throw new IllegalArgumentException(mode + " is unknown"); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java new file mode 100644 index 000000000000..c390edd1b459 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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; + +/** Enum used to define the behavior of DML statements in autocommit mode */ +enum AutocommitDmlMode { + TRANSACTIONAL, + PARTITIONED_NON_ATOMIC; + + private final String statementString; + + private AutocommitDmlMode() { + this.statementString = name(); + } + + /** + * Use this method to get the correct format for use in a SQL statement. Autocommit dml mode must + * be wrapped between single quotes in SQL statements: + * SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL' This method returns the value + * without the single quotes. + * + * @return a string representation of this {@link AutocommitDmlMode} that can be used in a SQL + * statement. + */ + public String getStatementString() { + return statementString; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java new file mode 100644 index 000000000000..0e0d7b433c34 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java @@ -0,0 +1,355 @@ +/* + * Copyright 2019 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.ByteArray; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type.Code; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.hash.Funnel; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; +import com.google.common.hash.PrimitiveSink; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; + +/** + * {@link ResultSet} implementation that keeps a running checksum that can be used to determine + * whether a transaction retry is possible or not. The checksum is based on all the rows that have + * actually been consumed by the user. If the user has not yet consumed any part of the result set + * (i.e. never called next()), the checksum will be null and retry will always be + * allowed. + * + *

If all the rows in the result set have been consumed, the checksum will be based on the values + * of all those rows, and a retry will only be possible if the query returns the exact same results + * during the retry as during the original transaction. + * + *

If some of the rows in the result set have been consumed, the checksum will be based on the + * values of the rows that have been consumed. A retry will succeed if the query returns the same + * results for the already consumed rows. + * + *

The checksum of a {@link ResultSet} is the SHA256 checksum of the current row together with + * the previous checksum value of the result set. The calculation of the checksum is executed in a + * separate {@link Thread} to allow the checksum calculation to lag behind the actual consumption of + * rows, and catch up again if the client slows down the consumption of rows, for example while + * waiting for more data from Cloud Spanner. If the checksum calculation queue contains more than + * {@link ChecksumExecutor#MAX_IN_CHECKSUM_QUEUE} items that have not yet been calculated, calls to + * {@link ResultSet#next()} will slow down in order to allow the calculation to catch up. + */ +@VisibleForTesting +class ChecksumResultSet extends ReplaceableForwardingResultSet implements RetriableStatement { + private final ReadWriteTransaction transaction; + private long numberOfNextCalls; + private final ParsedStatement statement; + private final AnalyzeMode analyzeMode; + private final QueryOption[] options; + private final ChecksumResultSet.ChecksumCalculator checksumCalculator = new ChecksumCalculator(); + + ChecksumResultSet( + ReadWriteTransaction transaction, + ResultSet delegate, + ParsedStatement statement, + AnalyzeMode analyzeMode, + QueryOption... options) { + super(delegate); + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(delegate); + Preconditions.checkNotNull(statement); + Preconditions.checkNotNull(statement.getStatement()); + Preconditions.checkNotNull(statement.getStatement().getSql()); + this.transaction = transaction; + this.statement = statement; + this.analyzeMode = analyzeMode; + this.options = options; + } + + /** Simple {@link Callable} for calling {@link ResultSet#next()} */ + private final class NextCallable implements Callable { + @Override + public Boolean call() throws Exception { + transaction + .getStatementExecutor() + .invokeInterceptors( + statement, StatementExecutionStep.CALL_NEXT_ON_RESULT_SET, transaction); + return ChecksumResultSet.super.next(); + } + } + + private final NextCallable nextCallable = new NextCallable(); + + @Override + public boolean next() { + // Call next() with retry. + boolean res = transaction.runWithRetry(nextCallable); + // Only update the checksum if there was another row to be consumed. + if (res) { + checksumCalculator.calculateNextChecksum(getCurrentRowAsStruct()); + } + numberOfNextCalls++; + return res; + } + + @VisibleForTesting + HashCode getChecksum() throws InterruptedException, ExecutionException { + // HashCode is immutable and can be safely returned. + return checksumCalculator.getChecksum(); + } + + /** + * Execute the same query as in the original transaction and consume the {@link ResultSet} to the + * same point as the original {@link ResultSet}. The {@link HashCode} of the new {@link ResultSet} + * is compared with the {@link HashCode} of the original {@link ResultSet} at the point where the + * consumption of the {@link ResultSet} stopped. + */ + @Override + public void retry(AbortedException aborted) throws AbortedException { + // Execute the same query and consume the result set to the same point as the original. + ChecksumResultSet.ChecksumCalculator newChecksumCalculator = new ChecksumCalculator(); + ResultSet resultSet = null; + long counter = 0L; + try { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + resultSet = + DirectExecuteResultSet.ofResultSet( + transaction.internalExecuteQuery(statement, analyzeMode, options)); + boolean next = true; + while (counter < numberOfNextCalls && next) { + transaction + .getStatementExecutor() + .invokeInterceptors( + statement, StatementExecutionStep.RETRY_NEXT_ON_RESULT_SET, transaction); + next = resultSet.next(); + if (next) { + newChecksumCalculator.calculateNextChecksum(resultSet.getCurrentRowAsStruct()); + } + counter++; + } + } catch (Throwable e) { + if (resultSet != null) { + resultSet.close(); + } + // If it was a SpannerException other than an AbortedException, the retry should fail + // because of different results from the database. + if (e instanceof SpannerException && !(e instanceof AbortedException)) { + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException( + aborted, (SpannerException) e); + } + // For other types of exceptions we should just re-throw the exception. + throw e; + } + // Check that we have the same number of rows and the same checksum. + HashCode newChecksum = newChecksumCalculator.getChecksum(); + HashCode currentChecksum = checksumCalculator.getChecksum(); + if (counter == numberOfNextCalls && Objects.equals(newChecksum, currentChecksum)) { + // Checksum is ok, we only need to replace the delegate result set if it's still open. + if (isClosed()) { + resultSet.close(); + } else { + replaceDelegate(resultSet); + } + } else { + // The results are not equal, there is an actual concurrent modification, so we cannot + // continue the transaction. + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } + } + + /** Calculates and keeps the current checksum of a {@link ChecksumResultSet} */ + private static final class ChecksumCalculator { + private static final HashFunction SHA256_FUNCTION = Hashing.sha256(); + private HashCode currentChecksum; + + private void calculateNextChecksum(Struct row) { + Hasher hasher = SHA256_FUNCTION.newHasher(); + if (currentChecksum != null) { + hasher.putBytes(currentChecksum.asBytes()); + } + hasher.putObject(row, StructFunnel.INSTANCE); + currentChecksum = hasher.hash(); + } + + private HashCode getChecksum() { + return currentChecksum; + } + } + + /** + * A {@link Funnel} implementation for calculating a {@link HashCode} for each row in a {@link + * ResultSet}. + */ + private enum StructFunnel implements Funnel { + INSTANCE; + private static final String NULL = "null"; + + @Override + public void funnel(Struct row, PrimitiveSink into) { + for (int i = 0; i < row.getColumnCount(); i++) { + if (row.isNull(i)) { + funnelValue(Code.STRING, null, into); + } else { + Code type = row.getColumnType(i).getCode(); + switch (type) { + case ARRAY: + funnelArray(row.getColumnType(i).getArrayElementType().getCode(), row, i, into); + break; + case BOOL: + funnelValue(type, row.getBoolean(i), into); + break; + case BYTES: + funnelValue(type, row.getBytes(i), into); + break; + case DATE: + funnelValue(type, row.getDate(i), into); + break; + case FLOAT64: + funnelValue(type, row.getDouble(i), into); + break; + case INT64: + funnelValue(type, row.getLong(i), into); + break; + case STRING: + funnelValue(type, row.getString(i), into); + break; + case TIMESTAMP: + funnelValue(type, row.getTimestamp(i), into); + break; + + case STRUCT: + default: + throw new IllegalArgumentException("unsupported row type"); + } + } + } + } + + private void funnelArray( + Code arrayElementType, Struct row, int columnIndex, PrimitiveSink into) { + funnelValue(Code.STRING, "BeginArray", into); + switch (arrayElementType) { + case BOOL: + into.putInt(row.getBooleanList(columnIndex).size()); + for (Boolean value : row.getBooleanList(columnIndex)) { + funnelValue(Code.BOOL, value, into); + } + break; + case BYTES: + into.putInt(row.getBytesList(columnIndex).size()); + for (ByteArray value : row.getBytesList(columnIndex)) { + funnelValue(Code.BYTES, value, into); + } + break; + case DATE: + into.putInt(row.getDateList(columnIndex).size()); + for (Date value : row.getDateList(columnIndex)) { + funnelValue(Code.DATE, value, into); + } + break; + case FLOAT64: + into.putInt(row.getDoubleList(columnIndex).size()); + for (Double value : row.getDoubleList(columnIndex)) { + funnelValue(Code.FLOAT64, value, into); + } + break; + case INT64: + into.putInt(row.getLongList(columnIndex).size()); + for (Long value : row.getLongList(columnIndex)) { + funnelValue(Code.INT64, value, into); + } + break; + case STRING: + into.putInt(row.getStringList(columnIndex).size()); + for (String value : row.getStringList(columnIndex)) { + funnelValue(Code.STRING, value, into); + } + break; + case TIMESTAMP: + into.putInt(row.getTimestampList(columnIndex).size()); + for (Timestamp value : row.getTimestampList(columnIndex)) { + funnelValue(Code.TIMESTAMP, value, into); + } + break; + + case ARRAY: + case STRUCT: + default: + throw new IllegalArgumentException("unsupported array element type"); + } + funnelValue(Code.STRING, "EndArray", into); + } + + private void funnelValue(Code type, T value, PrimitiveSink into) { + // Include the type name in case the type of a column has changed. + into.putUnencodedChars(type.name()); + if (value == null) { + if (type == Code.BYTES || type == Code.STRING) { + // Put length -1 to distinguish from the string value 'null'. + into.putInt(-1); + } + into.putUnencodedChars(NULL); + } else { + switch (type) { + case BOOL: + into.putBoolean((Boolean) value); + break; + case BYTES: + ByteArray byteArray = (ByteArray) value; + into.putInt(byteArray.length()); + into.putBytes(byteArray.toByteArray()); + break; + case DATE: + Date date = (Date) value; + into.putInt(date.getYear()).putInt(date.getMonth()).putInt(date.getDayOfMonth()); + break; + case FLOAT64: + into.putDouble((Double) value); + break; + case INT64: + into.putLong((Long) value); + break; + case STRING: + String stringValue = (String) value; + into.putInt(stringValue.length()); + into.putUnencodedChars(stringValue); + break; + case TIMESTAMP: + Timestamp timestamp = (Timestamp) value; + into.putLong(timestamp.getSeconds()).putInt(timestamp.getNanos()); + break; + case ARRAY: + case STRUCT: + default: + throw new IllegalArgumentException("invalid type for single value"); + } + } + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java new file mode 100644 index 000000000000..7bd31407a348 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 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.ResultSet; +import java.util.List; + +/** + * A {@link ClientSideStatement} is a statement that is not sent to Google Cloud Spanner, but that + * is executed locally to for example set a certain state of a {@link Connection} or get a property + * of a {@link Connection}. + */ +interface ClientSideStatement { + + /** + * @return a list of example statements for this {@link ClientSideStatement}. If these statements + * are parsed, they will all result this in this {@link ClientSideStatement}. + */ + List getExampleStatements(); + + /** + * @return a list of statements that need to be executed on a new connection before the example + * statements may be executed on a connection. For GET READ_TIMESTAMP this would for example + * be a couple of statements that generate a read-only transaction. + */ + List getExamplePrerequisiteStatements(); + + /** + * @return true if this {@link ClientSideStatement} will return a {@link ResultSet}. + */ + boolean isQuery(); + + /** @return true if this {@link ClientSideStatement} will return an update count. */ + boolean isUpdate(); + + /** + * Execute this {@link ClientSideStatement} on the given {@link ConnectionStatementExecutor}. The + * executor calls the appropriate method(s) on the {@link Connection}. The statement argument is + * used to parse any additional properties that might be needed for the execution. + * + * @param executor The {@link ConnectionStatementExecutor} that will be used to call a method on + * the {@link Connection}. + * @param statement The original sql statement that has been parsed to this {@link + * ClientSideStatement}. This statement is used to get any additional arguments that are + * needed for the execution of the {@link ClientSideStatement}. + * @return the result of the execution of the statement. + */ + StatementResult execute(ConnectionStatementExecutor executor, String statement); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java new file mode 100644 index 000000000000..d758286d16c5 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; + +/** + * A {@link ClientSideStatementExecutor} is used to compile {@link ClientSideStatement}s from the + * json source file, and to execute these against a {@link Connection} (through a {@link + * ConnectionStatementExecutor}). + */ +interface ClientSideStatementExecutor { + + /** + * Compiles the given {@link ClientSideStatementImpl} and registers this statement with this + * executor. A statement must be compiled before it can be executed. The parser automatically + * compiles all available statements during initialization. + * + * @param statement The statement to compile. + * @throws CompileException If the statement could not be compiled. This should never happen, as + * it would indicate that an invalid statement has been defined in the source file. + */ + void compile(ClientSideStatementImpl statement) throws CompileException; + + /** + * Executes the {@link ClientSideStatementImpl} that has been compiled and registered with this + * executor on the specified connection. + * + * @param connectionExecutor The {@link ConnectionStatementExecutor} to use to execute the + * statement on a {@link Connection}. + * @param sql The sql statement that is executed. This can be used to parse any additional + * arguments that might be needed for the execution of the {@link ClientSideStatementImpl}. + * @return the result of the execution. + * @throws Exception If an error occurs while executing the statement, for example if an invalid + * argument has been specified in the sql statement, or if the statement is invalid for the + * current state of the {@link Connection}. + */ + StatementResult execute(ConnectionStatementExecutor connectionExecutor, String sql) + throws Exception; +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java new file mode 100644 index 000000000000..551ab5aa3a87 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java @@ -0,0 +1,217 @@ +/* + * Copyright 2019 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.SpannerException; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import com.google.common.base.Preconditions; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Implementation of the {@link ClientSideStatement} interface. The instances of this class are + * imported from the file 'ClientSideStatements.json' in the resources folder. + */ +class ClientSideStatementImpl implements ClientSideStatement { + + /** + * Statements that set a value, such as SET AUTOCOMMIT ON|OFF, must specify a {@link + * ClientSideSetStatementImpl} that defines how the value is set. + */ + static class ClientSideSetStatementImpl { + /** The property name that is to be set, e.g. AUTOCOMMIT. */ + private String propertyName; + /** The separator between the property and the value (i.e. '=' or '\s+'). */ + private String separator; + /** Regex specifying the range of allowed values for the property. */ + private String allowedValues; + /** The class name of the {@link ClientSideStatementValueConverter} to use. */ + private String converterName; + + String getPropertyName() { + return propertyName; + } + + String getSeparator() { + return separator; + } + + String getAllowedValues() { + return allowedValues; + } + + String getConverterName() { + return converterName; + } + } + + static class CompileException extends Exception { + private static final long serialVersionUID = 1L; + private final ClientSideStatementImpl statement; + + CompileException(Throwable cause, ClientSideStatementImpl statement) { + super(cause); + this.statement = statement; + } + + @Override + public String getMessage() { + return "Could not compile statement " + this.statement.name; + } + } + + static class ExecuteException extends RuntimeException { + private static final long serialVersionUID = 1L; + private final ClientSideStatementImpl statement; + private final String sql; + + private ExecuteException(Throwable cause, ClientSideStatementImpl statement, String sql) { + super(cause); + this.statement = statement; + this.sql = sql; + } + + @Override + public String getMessage() { + return "Could not execute statement " + this.statement.name + " (" + sql + ")"; + } + } + + /** The name of this statement. Used in error and info messages. */ + private String name; + + /** + * The class name of the {@link ClientSideStatementExecutor} that should be used for this + * statement. + */ + private String executorName; + + /** The result type of this statement. */ + private ResultType resultType; + + /** The regular expression that should be used to recognize this class of statements. */ + private String regex; + + /** + * The method name of the {@link ConnectionStatementExecutor} that should be called when this + * statement is executed, for example 'statementSetAutocommit'. + */ + private String method; + + /** A list of example statements that is used for testing. */ + private List exampleStatements; + + /** + * A list of statements that need to be executed before the example statements may be executed. + */ + private List examplePrerequisiteStatements; + + /** + * If this statement sets a value, the statement definition should also contain a {@link + * ClientSideSetStatementImpl} definition that defines how the value that is to be set should be + * parsed. + */ + private ClientSideSetStatementImpl setStatement; + + /** The compiled regex pattern for recognizing this statement. */ + private Pattern pattern; + + /** A reference to the executor that should be used. */ + private ClientSideStatementExecutor executor; + + /** + * Compiles this {@link ClientSideStatementImpl}. Throws a {@link CompileException} if the + * compilation fails. This should never happen, and if it does, it is a sign of a invalid + * statement definition in the ClientSideStatements.json file. + */ + ClientSideStatementImpl compile() throws CompileException { + try { + this.pattern = Pattern.compile(regex); + this.executor = + (ClientSideStatementExecutor) + Class.forName(getClass().getPackage().getName() + "." + executorName).newInstance(); + this.executor.compile(this); + return this; + } catch (Exception e) { + throw new CompileException(e, this); + } + } + + @Override + public StatementResult execute(ConnectionStatementExecutor connection, String statement) { + Preconditions.checkState(executor != null, "This statement has not been compiled"); + try { + return executor.execute(connection, statement); + } catch (SpannerException e) { + throw e; + } catch (InvocationTargetException e) { + if (e.getCause() instanceof SpannerException) { + throw (SpannerException) e.getCause(); + } + throw new ExecuteException(e.getCause(), this, statement); + } catch (Exception e) { + throw new ExecuteException(e, this, statement); + } + } + + @Override + public boolean isQuery() { + return resultType == ResultType.RESULT_SET; + } + + @Override + public boolean isUpdate() { + return resultType == ResultType.UPDATE_COUNT; + } + + boolean matches(String statement) { + Preconditions.checkState(pattern != null, "This statement has not been compiled"); + return pattern.matcher(statement).matches(); + } + + @Override + public String toString() { + return name; + } + + Pattern getPattern() { + return pattern; + } + + String getMethodName() { + return method; + } + + @Override + public List getExampleStatements() { + return Collections.unmodifiableList(exampleStatements); + } + + @Override + public List getExamplePrerequisiteStatements() { + if (examplePrerequisiteStatements == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(examplePrerequisiteStatements); + } + + ClientSideSetStatementImpl getSetStatement() { + return setStatement; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java new file mode 100644 index 000000000000..d2ca7fde9d0f --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; +import java.lang.reflect.Method; + +/** + * Executor to use for statements that do not set a value and do not have any parameters, such as + * SHOW AUTOCOMMIT. The executor just calls a method with no parameters. + */ +class ClientSideStatementNoParamExecutor implements ClientSideStatementExecutor { + private Method method; + + ClientSideStatementNoParamExecutor() {} + + @Override + public void compile(ClientSideStatementImpl statement) throws CompileException { + try { + this.method = ConnectionStatementExecutor.class.getDeclaredMethod(statement.getMethodName()); + } catch (NoSuchMethodException | SecurityException e) { + throw new CompileException(e, statement); + } + } + + @Override + public StatementResult execute(ConnectionStatementExecutor connection, String statement) + throws Exception { + return (StatementResult) method.invoke(connection); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java new file mode 100644 index 000000000000..aaf01eaaa859 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.common.base.Preconditions; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Executor for {@link ClientSideStatement}s that sets a value for a property, such as SET + * AUTOCOMMIT=TRUE. + */ +class ClientSideStatementSetExecutor implements ClientSideStatementExecutor { + private ClientSideStatementImpl statement; + private Method method; + private ClientSideStatementValueConverter converter; + private Pattern allowedValuesPattern; + + @SuppressWarnings("unchecked") + @Override + public void compile(ClientSideStatementImpl statement) throws CompileException { + Preconditions.checkNotNull(statement.getSetStatement()); + try { + this.statement = statement; + this.allowedValuesPattern = + Pattern.compile( + String.format( + "(?is)\\A\\s*set\\s+%s\\s*%s\\s*%s\\s*\\z", + statement.getSetStatement().getPropertyName(), + statement.getSetStatement().getSeparator(), + statement.getSetStatement().getAllowedValues())); + Class> converterClass = + (Class>) + Class.forName( + getClass().getPackage().getName() + + "." + + statement.getSetStatement().getConverterName()); + Constructor> constructor = + converterClass.getConstructor(String.class); + this.converter = constructor.newInstance(statement.getSetStatement().getAllowedValues()); + this.method = + ConnectionStatementExecutor.class.getDeclaredMethod( + statement.getMethodName(), converter.getParameterClass()); + } catch (Exception e) { + throw new CompileException(e, statement); + } + } + + @Override + public StatementResult execute(ConnectionStatementExecutor connection, String sql) + throws Exception { + return (StatementResult) method.invoke(connection, getParameterValue(sql)); + } + + T getParameterValue(String sql) { + Matcher matcher = allowedValuesPattern.matcher(sql); + if (matcher.find() && matcher.groupCount() >= 1) { + String value = matcher.group(1); + T res = converter.convert(value); + if (res != null) { + return res; + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + String.format( + "Unknown value for %s: %s", + this.statement.getSetStatement().getPropertyName(), value)); + } else { + Matcher invalidMatcher = this.statement.getPattern().matcher(sql); + if (invalidMatcher.find() && invalidMatcher.groupCount() == 1) { + String invalidValue = invalidMatcher.group(1); + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + String.format( + "Unknown value for %s: %s", + this.statement.getSetStatement().getPropertyName(), invalidValue)); + } + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, String.format("Unknown statement: %s", sql)); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java new file mode 100644 index 000000000000..13b404cfe598 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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; + +/** + * Interface for converters that are used by {@link ClientSideStatement} that sets a value that need + * to be converted from a string to a specific type. Implementing classes must have a public + * constructor that takes a String parameter. The String parameter will contain a regular expression + * for the allowed values for the property. + */ +interface ClientSideStatementValueConverter { + + /** The type to convert to. */ + Class getParameterClass(); + + /** + * The actual convert method. Should return null for values that could not be + * converted. + */ + T convert(String value); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java new file mode 100644 index 000000000000..ddeb394268f7 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java @@ -0,0 +1,243 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.protobuf.Duration; +import com.google.protobuf.util.Durations; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Contains all {@link ClientSideStatementValueConverter} implementations. */ +class ClientSideStatementValueConverters { + /** Map for mapping case-insensitive strings to enums. */ + private static final class CaseInsensitiveEnumMap> { + private final Map map = new HashMap<>(); + + /** Create an map using the name of the enum elements as keys. */ + private CaseInsensitiveEnumMap(Class elementType) { + this( + elementType, + new Function() { + @Override + public String apply(E input) { + return input.name(); + } + }); + } + + /** Create a map using the specific function to get the key per enum value. */ + private CaseInsensitiveEnumMap(Class elementType, Function keyFunction) { + Preconditions.checkNotNull(elementType); + Preconditions.checkNotNull(keyFunction); + EnumSet set = EnumSet.allOf(elementType); + for (E e : set) { + if (map.put(keyFunction.apply(e).toUpperCase(), e) != null) { + throw new IllegalArgumentException( + "Enum contains multiple elements with the same case-insensitive key"); + } + } + } + + private E get(String value) { + Preconditions.checkNotNull(value); + return map.get(value.toUpperCase()); + } + } + + /** Converter from string to {@link Boolean} */ + static class BooleanConverter implements ClientSideStatementValueConverter { + + public BooleanConverter(String allowedValues) {} + + @Override + public Class getParameterClass() { + return Boolean.class; + } + + @Override + public Boolean convert(String value) { + if ("true".equalsIgnoreCase(value)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(value)) { + return Boolean.FALSE; + } + return null; + } + } + + /** Converter from string to {@link Duration}. */ + static class DurationConverter implements ClientSideStatementValueConverter { + private final Pattern allowedValues; + + public DurationConverter(String allowedValues) { + // Remove the parentheses from the beginning and end. + this.allowedValues = + Pattern.compile( + "(?is)\\A" + allowedValues.substring(1, allowedValues.length() - 1) + "\\z"); + } + + @Override + public Class getParameterClass() { + return Duration.class; + } + + @Override + public Duration convert(String value) { + Matcher matcher = allowedValues.matcher(value); + if (matcher.find()) { + if (matcher.group(0).equalsIgnoreCase("null")) { + return Durations.fromNanos(0L); + } else { + Duration duration = + ReadOnlyStalenessUtil.createDuration( + Long.valueOf(matcher.group(1)), + ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(2))); + if (duration.getSeconds() == 0L && duration.getNanos() == 0) { + return null; + } + return duration; + } + } + return null; + } + } + + /** Converter from string to possible values for read only staleness ({@link TimestampBound}). */ + static class ReadOnlyStalenessConverter + implements ClientSideStatementValueConverter { + private final Pattern allowedValues; + private final CaseInsensitiveEnumMap values = new CaseInsensitiveEnumMap<>(Mode.class); + + public ReadOnlyStalenessConverter(String allowedValues) { + // Remove the single quotes at the beginning and end. + this.allowedValues = + Pattern.compile( + "(?is)\\A" + allowedValues.substring(1, allowedValues.length() - 1) + "\\z"); + } + + @Override + public Class getParameterClass() { + return TimestampBound.class; + } + + @Override + public TimestampBound convert(String value) { + Matcher matcher = allowedValues.matcher(value); + if (matcher.find() && matcher.groupCount() >= 1) { + Mode mode = null; + int groupIndex = 0; + for (int group = 1; group <= matcher.groupCount(); group++) { + if (matcher.group(group) != null) { + mode = values.get(matcher.group(group)); + if (mode != null) { + groupIndex = group; + break; + } + } + } + switch (mode) { + case STRONG: + return TimestampBound.strong(); + case READ_TIMESTAMP: + return TimestampBound.ofReadTimestamp( + ReadOnlyStalenessUtil.parseRfc3339(matcher.group(groupIndex + 1))); + case MIN_READ_TIMESTAMP: + return TimestampBound.ofMinReadTimestamp( + ReadOnlyStalenessUtil.parseRfc3339(matcher.group(groupIndex + 1))); + case EXACT_STALENESS: + try { + return TimestampBound.ofExactStaleness( + Long.valueOf(matcher.group(groupIndex + 2)), + ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3))); + } catch (IllegalArgumentException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, e.getMessage()); + } + case MAX_STALENESS: + try { + return TimestampBound.ofMaxStaleness( + Long.valueOf(matcher.group(groupIndex + 2)), + ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3))); + } catch (IllegalArgumentException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, e.getMessage()); + } + default: + // fall through to allow the calling method to handle this + } + } + return null; + } + } + + /** Converter for converting strings to {@link AutocommitDmlMode} values. */ + static class AutocommitDmlModeConverter + implements ClientSideStatementValueConverter { + private final CaseInsensitiveEnumMap values = + new CaseInsensitiveEnumMap<>(AutocommitDmlMode.class); + + public AutocommitDmlModeConverter(String allowedValues) {} + + @Override + public Class getParameterClass() { + return AutocommitDmlMode.class; + } + + @Override + public AutocommitDmlMode convert(String value) { + return values.get(value); + } + } + + /** Converter for converting string values to {@link TransactionMode} values. */ + static class TransactionModeConverter + implements ClientSideStatementValueConverter { + private final CaseInsensitiveEnumMap values = + new CaseInsensitiveEnumMap<>( + TransactionMode.class, + new Function() { + @Override + public String apply(TransactionMode input) { + return input.getStatementString(); + } + }); + + public TransactionModeConverter(String allowedValues) {} + + @Override + public Class getParameterClass() { + return TransactionMode.class; + } + + @Override + public TransactionMode convert(String value) { + // Transaction mode may contain multiple spaces. + String valueWithSingleSpaces = value.replaceAll("\\s+", " "); + return values.get(valueWithSingleSpaces); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java new file mode 100644 index 000000000000..3f3d872fc669 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java @@ -0,0 +1,51 @@ +/* + * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; +import com.google.gson.Gson; +import java.io.InputStreamReader; +import java.util.Set; + +/** This class reads and parses the {@link ClientSideStatement}s from the json file. */ +class ClientSideStatements { + private static final String STATEMENTS_DEFINITION_FILE = "ClientSideStatements.json"; + static final ClientSideStatements INSTANCE = importStatements(); + + /** + * Reads statement definitions from ClientSideStatements.json and parses these as Java objects. + */ + private static ClientSideStatements importStatements() { + Gson gson = new Gson(); + return gson.fromJson( + new InputStreamReader( + ClientSideStatements.class.getResourceAsStream(STATEMENTS_DEFINITION_FILE)), + ClientSideStatements.class); + } + + private Set statements; + + private ClientSideStatements() {} + + /** Compiles and returns all statements from the resource file. */ + Set getCompiledStatements() throws CompileException { + for (ClientSideStatementImpl statement : statements) { + statement.compile(); + } + return statements; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java new file mode 100644 index 000000000000..d4c6629b7e82 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -0,0 +1,172 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Iterator; + +/** + * 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 + * input on a {@link Connection} returned by the Cloud Spanner JDBC Driver will return a {@link + * CloudSpannerJdbcConnection} instance. + */ +public interface CloudSpannerJdbcConnection extends Connection { + + /** + * @return the commit {@link Timestamp} of the last read/write transaction. If the last + * transaction was not a read/write transaction, or a read/write transaction that did not + * return a commit timestamp because the transaction was not committed, the method will throw + * a {@link SQLException}. + */ + Timestamp getCommitTimestamp() throws SQLException; + + /** + * @return the read {@link Timestamp} of the last read-only transaction. If the last transaction + * was not a read-only transaction, or a read-only transaction that did not return a read + * timestamp because no data was read, the method will throw a {@link SQLException}. + */ + Timestamp getReadTimestamp() throws SQLException; + + /** + * @return true if this connection will automatically retry read/write transactions + * that abort. This method may only be called when the connection is in read/write + * transactional mode and no transaction has been started yet. + */ + boolean isRetryAbortsInternally() throws SQLException; + + /** + * Sets whether this connection will internally retry read/write transactions that abort. The + * default is true. When internal retry is enabled, the {@link Connection} will keep + * track of a running SHA256 checksum of all {@link ResultSet}s that have been returned from Cloud + * Spanner. If the checksum that is calculated during an internal retry differs from the original + * checksum, the transaction will abort with an {@link + * AbortedDueToConcurrentModificationException}. + * + *

Note that retries of a read/write transaction that calls a non-deterministic function on + * Cloud Spanner, such as CURRENT_TIMESTAMP(), will never be successful, as the data returned + * during the retry will always be different from the original transaction. + * + *

It is also highly recommended that all queries in a read/write transaction have an ORDER BY + * clause that guarantees that the data is returned in the same order as in the original + * transaction if the transaction is internally retried. The most efficient way to achieve this is + * to always include the primary key columns at the end of the ORDER BY clause. + * + *

This method may only be called when the connection is in read/write transactional mode and + * no transaction has been started yet. + * + * @param retryAbortsInternally Set to true to internally retry transactions that are + * aborted by Spanner. When set to false, any database call on a transaction that + * has been aborted by Cloud Spanner will throw an {@link AbortedException} instead of being + * retried. Set this to false if your application already uses retry loops to handle {@link + * AbortedException}s. + */ + void setRetryAbortsInternally(boolean retryAbortsInternally) throws SQLException; + + /** + * Writes the specified mutation directly to the database and commits the change. The value is + * readable after the successful completion of this method. Writing multiple mutations to a + * database by calling this method multiple times mode is inefficient, as each call will need a + * round trip to the database. Instead, you should consider writing the mutations together by + * calling {@link CloudSpannerJdbcConnection#write(Iterable)}. + * + *

Calling this method is only allowed in autocommit mode. See {@link + * CloudSpannerJdbcConnection#bufferedWrite(Iterable)} for writing mutations in transactions. + * + * @param mutation The {@link Mutation} to write to the database. + * @throws SQLException if the {@link Connection} is not in autocommit mode or if the {@link + * Connection} is closed. + */ + void write(Mutation mutation) throws SQLException; + + /** + * Writes the specified mutations directly to the database and commits the changes. The values are + * readable after the successful completion of this method. + * + *

Calling this method is only allowed in autocommit mode. See {@link + * CloudSpannerJdbcConnection#bufferedWrite(Iterable)} for writing mutations in transactions. + * + * @param mutations The {@link Mutation}s to write to the database. + * @throws SQLException if the {@link Connection} is not in autocommit mode or if the {@link + * Connection} is closed. + */ + void write(Iterable mutations) throws SQLException; + + /** + * Buffers the given mutation locally on the current transaction of this {@link Connection}. The + * mutation will be written to the database at the next call to {@link Connection#commit()}. The + * value will not be readable on this {@link Connection} before the transaction is committed. + * + *

Calling this method is only allowed when not in autocommit mode. See {@link + * CloudSpannerJdbcConnection#write(Mutation)} for writing mutations in autocommit mode. + * + * @param mutation the {@link Mutation} to buffer for writing to the database on the next commit. + * @throws SQLException if the {@link Connection} is in autocommit mode or the {@link Connection} + * is closed. + */ + void bufferedWrite(Mutation mutation) throws SQLException; + + /** + * Buffers the given mutations locally on the current transaction of this {@link Connection}. The + * mutations will be written to the database at the next call to {@link Connection#commit()}. The + * values will not be readable on this {@link Connection} before the transaction is committed. + * + *

Calling this method is only allowed when not in autocommit mode. See {@link + * CloudSpannerJdbcConnection#write(Iterable)} for writing mutations in autocommit mode. + * + * @param mutations the {@link Mutation}s to buffer for writing to the database on the next + * commit. + * @throws SQLException if the {@link Connection} is in autocommit mode or the {@link Connection} + * is closed. + */ + void bufferedWrite(Iterable mutations) throws SQLException; + + /** + * @return a connection URL that can be used to create a new {@link Connection} that is equal to + * the initial state of this connection. If this connection was initially opened in read-only + * mode, and later changed to read-write, this will not be reflected in the connection URL + * that is returned. + */ + String getConnectionUrl(); + + /** + * @see + * com.google.cloud.spanner.jdbc.Connection#addTransactionRetryListener(TransactionRetryListener) + * @throws SQLException if the {@link Connection} is closed. + */ + void addTransactionRetryListener(TransactionRetryListener listener) throws SQLException; + + /** + * @see + * com.google.cloud.spanner.jdbc.Connection#removeTransactionRetryListener(TransactionRetryListener) + * @throws SQLException if the {@link Connection} is closed. + */ + boolean removeTransactionRetryListener(TransactionRetryListener listener) throws SQLException; + + /** + * @see com.google.cloud.spanner.jdbc.Connection#getTransactionRetryListeners() + * @throws SQLException if the {@link Connection} is closed. + */ + Iterator getTransactionRetryListeners() throws SQLException; +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java new file mode 100644 index 000000000000..0ae8ed5cd864 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java @@ -0,0 +1,704 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import java.util.Iterator; +import java.util.concurrent.TimeUnit; + +/** + * A connection to a Cloud Spanner database. Connections are not designed to be thread-safe. The + * only exception is the {@link Connection#cancel()} method that may be called by any other thread + * to stop the execution of the current statement on the connection. + * + *

Connections accept a number of additional SQL statements for setting or changing the state of + * a {@link Connection}. These statements can only be executed using the {@link + * Connection#execute(Statement)} method: + * + *

    + *
  • SHOW AUTOCOMMIT: Returns the current value of AUTOCOMMIT of this + * connection as a {@link ResultSet} + *
  • SET AUTOCOMMIT=TRUE|FALSE: Sets the value of AUTOCOMMIT for this + * connection + *
  • SHOW READONLY: Returns the current value of READONLY of this + * connection as a {@link ResultSet} + *
  • SET READONLY=TRUE|FALSE: Sets the value of READONLY for this + * connection + *
  • SHOW RETRY_ABORTS_INTERNALLY: Returns the current value of + * RETRY_ABORTS_INTERNALLY of this connection as a {@link ResultSet} + *
  • SET RETRY_ABORTS_INTERNALLY=TRUE|FALSE: Sets the value of + * RETRY_ABORTS_INTERNALLY for this connection + *
  • SHOW AUTOCOMMIT_DML_MODE: Returns the current value of + * AUTOCOMMIT_DML_MODE of this connection as a {@link ResultSet} + *
  • SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL' | 'PARTITIONED_NON_ATOMIC': Sets the + * value of AUTOCOMMIT_DML_MODE for this connection + *
  • SHOW STATEMENT_TIMEOUT: Returns the current value of STATEMENT_TIMEOUT + * of this connection as a {@link ResultSet} + *
  • SET STATEMENT_TIMEOUT='<int64>s|ms|us|ns' | NULL: Sets the value of + * STATEMENT_TIMEOUT for this connection. The supported {@link TimeUnit}s are: + *
      + *
    • s - Seconds + *
    • ms - Milliseconds + *
    • us - Microseconds + *
    • ns - Nanoseconds + *
    + * Setting the STATEMENT_TIMEOUT to NULL will clear the value for the STATEMENT_TIMEOUT on the + * connection. + *
  • SHOW READ_TIMESTAMP: Returns the last READ_TIMESTAMP of this + * connection as a {@link ResultSet} + *
  • SHOW COMMIT_TIMESTAMP: Returns the last COMMIT_TIMESTAMP of this + * connection as a {@link ResultSet} + *
  • SHOW READ_ONLY_STALENESS: Returns the current value of + * READ_ONLY_STALENESS of this connection as a {@link ResultSet} + *
  • + * SET READ_ONLY_STALENESS='STRONG' | 'MIN_READ_TIMESTAMP <timestamp>' | 'READ_TIMESTAMP <timestamp>' | 'MAX_STALENESS <int64>s|ms|mus|ns' | 'EXACT_STALENESS (<int64>s|ms|mus|ns)' + * : Sets the value of READ_ONLY_STALENESS for this connection. + *
  • BEGIN [TRANSACTION]: Begins a new transaction. This statement is optional when + * the connection is not in autocommit mode, as a new transaction will automatically be + * started when a query or update statement is issued. In autocommit mode, this statement will + * temporarily put the connection in transactional mode, and return the connection to + * autocommit mode when COMMIT [TRANSACTION] or ROLLBACK [TRANSACTION] + * is executed + *
  • COMMIT [TRANSACTION]: Commits the current transaction + *
  • ROLLBACK [TRANSACTION]: Rollbacks the current transaction + *
  • SET TRANSACTION READ ONLY|READ WRITE: Sets the type for the current + * transaction. May only be executed before a transaction is actually running (i.e. before any + * statements have been executed in the transaction) + *
  • START BATCH DDL: Starts a batch of DDL statements. May only be executed when + * no transaction has been started and the connection is in read/write mode. The connection + * will only accept DDL statements while a DDL batch is active. + *
  • START BATCH DML: Starts a batch of DML statements. May only be executed when + * the connection is in read/write mode. The connection will only accept DML statements while + * a DML batch is active. + *
  • RUN BATCH: Ends the current batch, sends the batched DML or DDL statements to + * Spanner and blocks until all statements have been executed or an error occurs. May only be + * executed when a (possibly empty) batch is active. The statement will return the update + * counts of the batched statements as {@link ResultSet} with an ARRAY<INT64> column. In + * case of a DDL batch, this array will always be empty. + *
  • ABORT BATCH: Ends the current batch and removes any DML or DDL statements from + * the buffer without sending any statements to Spanner. May only be executed when a (possibly + * empty) batch is active. + *
+ * + * Note that Cloud Spanner could abort read/write transactions in the background, and that + * any database call during a read/write transaction could fail with an {@link + * AbortedException}. This also includes calls to {@link ResultSet#next()}. + * + *

If {@link Connection#isRetryAbortsInternally()} is true, then the connection will + * silently handle any {@link AbortedException}s by internally re-acquiring all transactional locks + * and verifying (via the use of cryptographic checksums) that no underlying data has changed. If a + * change to the underlying data is detected, then an {@link + * AbortedDueToConcurrentModificationException} error will be thrown. If your application already + * uses retry loops to handle these Aborted errors, then it will be most efficient to set {@link + * Connection#isRetryAbortsInternally()} to false. + * + *

Use {@link ConnectionOptions} to create a {@link Connection}. + */ +interface Connection extends AutoCloseable { + + /** Closes this connection. This is a no-op if the {@link Connection} has alread been closed. */ + @Override + void close(); + + /** @return true if this connection has been closed. */ + boolean isClosed(); + + /** + * Sets autocommit on/off for this {@link Connection}. Connections in autocommit mode will apply + * any changes to the database directly without waiting for an explicit commit. DDL- and DML + * statements as well as {@link Mutation}s are sent directly to Spanner, and committed + * automatically unless the statement caused an error. The statement is retried in case of an + * {@link AbortedException}. All other errors will cause the underlying transaction to be rolled + * back. + * + *

A {@link Connection} that is in autocommit and read/write mode will allow all types of + * statements: Queries, DML, DDL, and Mutations (writes). If the connection is in read-only mode, + * only queries will be allowed. + * + *

{@link Connection}s in autocommit mode may also accept partitioned DML statements. See + * {@link Connection#setAutocommitDmlMode(AutocommitDmlMode)} for more information. + * + * @param autocommit true/false to turn autocommit on/off + */ + void setAutocommit(boolean autocommit); + + /** @return true if this connection is in autocommit mode */ + boolean isAutocommit(); + + /** + * Sets this connection to read-only or read-write. This method may only be called when no + * transaction is active. A connection that is in read-only mode, will never allow any kind of + * changes to the database to be submitted. + * + * @param readOnly true/false to turn read-only mode on/off + */ + void setReadOnly(boolean readOnly); + + /** @return true if this connection is in read-only mode */ + boolean isReadOnly(); + + /** + * Sets the duration the connection should wait before automatically aborting the execution of a + * statement. The default is no timeout. Statement timeouts are applied all types of statements, + * both in autocommit and transactional mode. They also apply to {@link Connection#commit()} and + * {@link Connection#rollback()} statements. + * + *

A DML statement in autocommit mode may or may not have actually been applied to the + * database, depending on when the timeout occurred. + * + *

A DML statement in a transaction that times out may still have been applied to the + * transaction. If you still decide to commit the transaction after such a timeout, the DML + * statement may or may not have been part of the transaction, depending on whether the timeout + * occurred before or after the statement was (successfully) sent to Spanner. You should therefore + * either always rollback a transaction that had a DML statement that timed out, or you should + * accept that the timed out statement still might have been applied to the database. + * + *

DDL statements and DML statements in {@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} mode + * cannot be rolled back. If such a statement times out, it may or may not have been applied to + * the database. The same applies to commit and rollback statements. + * + *

Statements that time out will throw a {@link SpannerException} with error code {@link + * ErrorCode#DEADLINE_EXCEEDED}. + * + * @param timeout The number of {@link TimeUnit}s before a statement is automatically aborted by + * the connection. Zero or negative values are not allowed. The maximum allowed value is + * 315,576,000,000 seconds. Use {@link Connection#clearStatementTimeout()} to remove a timeout + * value that has been set. + * @param unit The {@link TimeUnit} to specify the timeout value in. Must be one of {@link + * TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link TimeUnit#MILLISECONDS}, {@link + * TimeUnit#SECONDS}. + */ + void setStatementTimeout(long timeout, TimeUnit unit); + + /** + * Clears the statement timeout value for this connection. This is a no-op if there is currently + * no statement timeout set on this connection. + */ + void clearStatementTimeout(); + + /** + * @param unit The {@link TimeUnit} to get the timeout value in. Must be one of {@link + * TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link TimeUnit#MILLISECONDS}, {@link + * TimeUnit#SECONDS} + * @return the current statement timeout value or 0 if no timeout value has been set. + */ + long getStatementTimeout(TimeUnit unit); + + /** @return true if this {@link Connection} has a statement timeout value. */ + boolean hasStatementTimeout(); + + /** + * Cancels the currently running statement on this {@link Connection} (if any). If canceling the + * statement execution succeeds, the statement will be terminated and a {@link SpannerException} + * with code {@link ErrorCode#CANCELLED} will be thrown. The result of the statement will be the + * same as when a statement times out (see {@link Connection#setStatementTimeout(long, TimeUnit)} + * for more information). + * + *

Canceling a DDL statement in autocommit mode or a RUN BATCH statement of a DDL batch will + * cause the connection to try to cancel the execution of the DDL statement(s). This is not + * guaranteed to cancel the execution of the statement(s) on Cloud Spanner. See + * https://cloud.google.com/spanner/docs/reference/rpc/google.longrunning#google.longrunning.Operations.CancelOperation + * for more information. + * + *

Canceling a DML statement that is running in {@link + * AutocommitDmlMode#PARTITIONED_NON_ATOMIC} mode will not cancel a statement on Cloud Spanner + * that is already being executed, and its effects will still be applied to the database. + */ + void cancel(); + + /** + * Begins a new transaction for this connection. + * + *

    + *
  • Calling this method on a connection that has no transaction and that is + * not in autocommit mode, will register a new transaction that has not yet + * started on this connection + *
  • Calling this method on a connection that has no transaction and that is + * in autocommit mode, will register a new transaction that has not yet started on this + * connection, and temporarily turn off autocommit mode until the next commit/rollback + *
  • Calling this method on a connection that already has a transaction that has not yet + * started, will cause a {@link SpannerException} + *
  • Calling this method on a connection that already has a transaction that has started, will + * cause a {@link SpannerException} (no nested transactions) + *
+ */ + void beginTransaction(); + + /** + * Sets the transaction mode to use for current transaction. This method may only be called when + * in a transaction, and before the transaction is actually started, i.e. before any statements + * have been executed in the transaction. + * + * @param transactionMode The transaction mode to use for the current transaction. + *
    + *
  • {@link TransactionMode#READ_ONLY_TRANSACTION} will create a read-only transaction and + * prevent any changes to written to the database through this transaction. The read + * timestamp to be used will be determined based on the current readOnlyStaleness + * setting of this connection. It is recommended to use {@link + * TransactionMode#READ_ONLY_TRANSACTION} instead of {@link + * TransactionMode#READ_WRITE_TRANSACTION} when possible, as read-only transactions do + * not acquire locks on Cloud Spanner, and read-only transactions never abort. + *
  • {@link TransactionMode#READ_WRITE_TRANSACTION} this value is only allowed when the + * connection is not in read-only mode and will create a read-write transaction. If + * {@link Connection#isRetryAbortsInternally()} is true, each read/write + * transaction will keep track of a running SHA256 checksum for each {@link ResultSet} + * that is returned in order to be able to retry the transaction in case the transaction + * is aborted by Spanner. + *
+ */ + void setTransactionMode(TransactionMode transactionMode); + + /** + * @return the transaction mode of the current transaction. This method may only be called when + * the connection is in a transaction. + */ + TransactionMode getTransactionMode(); + + /** + * @return true if this connection will automatically retry read/write transactions + * that abort. This method may only be called when the connection is in read/write + * transactional mode and no transaction has been started yet. + */ + boolean isRetryAbortsInternally(); + + /** + * Sets whether this connection will internally retry read/write transactions that abort. The + * default is true. When internal retry is enabled, the {@link Connection} will keep + * track of a running SHA256 checksum of all {@link ResultSet}s that have been returned from Cloud + * Spanner. If the checksum that is calculated during an internal retry differs from the original + * checksum, the transaction will abort with an {@link + * AbortedDueToConcurrentModificationException}. + * + *

Note that retries of a read/write transaction that calls a non-deterministic function on + * Cloud Spanner, such as CURRENT_TIMESTAMP(), will never be successful, as the data returned + * during the retry will always be different from the original transaction. + * + *

It is also highly recommended that all queries in a read/write transaction have an ORDER BY + * clause that guarantees that the data is returned in the same order as in the original + * transaction if the transaction is internally retried. The most efficient way to achieve this is + * to always include the primary key columns at the end of the ORDER BY clause. + * + *

This method may only be called when the connection is in read/write transactional mode and + * no transaction has been started yet. + * + * @param retryAbortsInternally Set to true to internally retry transactions that are + * aborted by Spanner. When set to false, any database call on a transaction that + * has been aborted by Cloud Spanner will throw an {@link AbortedException} instead of being + * retried. Set this to false if your application already uses retry loops to handle {@link + * AbortedException}s. + */ + void setRetryAbortsInternally(boolean retryAbortsInternally); + + /** + * Add a {@link TransactionRetryListener} to this {@link Connection} for testing and logging + * purposes. The method {@link TransactionRetryListener#retryStarting(Timestamp, long, int)} will + * be called before an automatic retry is started for a read/write transaction on this connection. + * The method {@link TransactionRetryListener#retryFinished(Timestamp, long, int, + * TransactionRetryListener.RetryResult)} will be called after the retry has finished. + * + * @param listener The listener to add to this connection. + */ + void addTransactionRetryListener(TransactionRetryListener listener); + + /** + * Removes one existing {@link TransactionRetryListener} from this {@link Connection}, if it is + * present (optional operation). + * + * @param listener The listener to remove from the connection. + * @return true if a listener was removed from the connection. + */ + boolean removeTransactionRetryListener(TransactionRetryListener listener); + + /** + * @return an unmodifiable iterator of the {@link TransactionRetryListener}s registered for this + * connection. + */ + Iterator getTransactionRetryListeners(); + + /** + * Sets the mode for executing DML statements in autocommit mode for this connection. This setting + * is only used when the connection is in autocommit mode, and may only be set while the + * transaction is in autocommit mode and not in a temporary transaction. The autocommit + * transaction mode is reset to its default value of {@link AutocommitDmlMode#TRANSACTIONAL} when + * autocommit mode is changed on the connection. + * + * @param mode The DML autocommit mode to use + *

    + *
  • {@link AutocommitDmlMode#TRANSACTIONAL} DML statements are executed as single + * read-write transaction. After successful execution, the DML statement is guaranteed + * to have been applied exactly once to the database + *
  • {@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} DML statements are executed as + * partitioned DML transactions. If an error occurs during the execution of the DML + * statement, it is possible that the statement has been applied to some but not all of + * the rows specified in the statement. + *
+ */ + void setAutocommitDmlMode(AutocommitDmlMode mode); + + /** + * @return the current {@link AutocommitDmlMode} setting for this connection. This method may only + * be called on a connection that is in autocommit mode and not while in a temporary + * transaction. + */ + AutocommitDmlMode getAutocommitDmlMode(); + + /** + * Sets the staleness to use for the current read-only transaction. This method may only be called + * when the transaction mode of the current transaction is {@link + * TransactionMode#READ_ONLY_TRANSACTION} and there is no transaction that has started, or when + * the connection is in read-only and autocommit mode. + * + * @param staleness The staleness to use for the current but not yet started read-only transaction + */ + void setReadOnlyStaleness(TimestampBound staleness); + + /** + * @return the read-only staleness setting for the current read-only transaction. This method may + * only be called when the current transaction is a read-only transaction, or when the + * connection is in read-only and autocommit mode. + */ + TimestampBound getReadOnlyStaleness(); + + /** + * Commits the current transaction of this connection. All mutations that have been buffered + * during the current transaction will be written to the database. + * + *

If the connection is in autocommit mode, and there is a temporary transaction active on this + * connection, calling this method will cause the connection to go back to autocommit mode after + * calling this method. + * + *

This method will throw a {@link SpannerException} with code {@link + * ErrorCode#DEADLINE_EXCEEDED} if a statement timeout has been set on this connection, and the + * commit operation takes longer than this timeout. + * + *

    + *
  • Calling this method on a connection in autocommit mode and with no temporary transaction, + * will cause an exception + *
  • Calling this method while a DDL batch is active will cause an exception + *
  • Calling this method on a connection with a transaction that has not yet started, will end + * that transaction and any properties that might have been set on that transaction, and + * return the connection to its previous state. This means that if a transaction is created + * and set to read-only, and then committed before any statements have been executed, the + * read-only transaction is ended and any subsequent statements will be executed in a new + * transaction. If the connection is in read-write mode, the default for new transactions + * will be {@link TransactionMode#READ_WRITE_TRANSACTION}. Committing an empty transaction + * also does not generate a read timestamp or a commit timestamp, and calling one of the + * methods {@link Connection#getReadTimestamp()} or {@link Connection#getCommitTimestamp()} + * will cause an exception. + *
  • Calling this method on a connection with a {@link TransactionMode#READ_ONLY_TRANSACTION} + * transaction will end that transaction. If the connection is in read-write mode, any + * subsequent transaction will by default be a {@link + * TransactionMode#READ_WRITE_TRANSACTION} transaction, unless any following transaction is + * explicitly set to {@link TransactionMode#READ_ONLY_TRANSACTION} + *
  • Calling this method on a connection with a {@link TransactionMode#READ_WRITE_TRANSACTION} + * transaction will send all buffered mutations to the database, commit any DML statements + * that have been executed during this transaction and end the transaction. + *
+ */ + void commit(); + + /** + * Rollbacks the current transaction of this connection. All mutations or DDL statements that have + * been buffered during the current transaction will be removed from the buffer. + * + *

If the connection is in autocommit mode, and there is a temporary transaction active on this + * connection, calling this method will cause the connection to go back to autocommit mode after + * calling this method. + * + *

    + *
  • Calling this method on a connection in autocommit mode and with no temporary transaction + * will cause an exception + *
  • Calling this method while a DDL batch is active will cause an exception + *
  • Calling this method on a connection with a transaction that has not yet started, will end + * that transaction and any properties that might have been set on that transaction, and + * return the connection to its previous state. This means that if a transaction is created + * and set to read-only, and then rolled back before any statements have been executed, the + * read-only transaction is ended and any subsequent statements will be executed in a new + * transaction. If the connection is in read-write mode, the default for new transactions + * will be {@link TransactionMode#READ_WRITE_TRANSACTION}. + *
  • Calling this method on a connection with a {@link TransactionMode#READ_ONLY_TRANSACTION} + * transaction will end that transaction. If the connection is in read-write mode, any + * subsequent transaction will by default be a {@link + * TransactionMode#READ_WRITE_TRANSACTION} transaction, unless any following transaction is + * explicitly set to {@link TransactionMode#READ_ONLY_TRANSACTION} + *
  • Calling this method on a connection with a {@link TransactionMode#READ_WRITE_TRANSACTION} + * transaction will clear all buffered mutations, rollback any DML statements that have been + * executed during this transaction and end the transaction. + *
+ */ + void rollback(); + + /** + * @return true if this connection has a transaction (that has not necessarily + * started). This method will only return false when the {@link Connection} is in autocommit + * mode and no explicit transaction has been started by calling {@link + * Connection#beginTransaction()}. If the {@link Connection} is not in autocommit mode, there + * will always be a transaction. + */ + boolean isInTransaction(); + + /** + * @return true if this connection has a transaction that has started. A transaction + * is automatically started by the first statement that is executed in the transaction. + */ + boolean isTransactionStarted(); + + /** + * Returns the read timestamp of the current/last {@link TransactionMode#READ_ONLY_TRANSACTION} + * transaction, or the read timestamp of the last query in autocommit mode. + * + *
    + *
  • When in autocommit mode: The method will return the read timestamp of the last statement + * if the last statement was a query. + *
  • When in a {@link TransactionMode#READ_ONLY_TRANSACTION} transaction that has started (a + * query has been executed), or that has just committed: The read timestamp of the + * transaction. If the read-only transaction was committed without ever executing a query, + * calling this method after the commit will also throw a {@link SpannerException} + *
  • In all other cases the method will throw a {@link SpannerException}. + *
+ * + * @return the read timestamp of the current/last read-only transaction. + */ + Timestamp getReadTimestamp(); + + /** + * @return the commit timestamp of the last {@link TransactionMode#READ_WRITE_TRANSACTION} + * transaction. This method will throw a {@link SpannerException} if there is no last {@link + * TransactionMode#READ_WRITE_TRANSACTION} transaction (i.e. the last transaction was a {@link + * TransactionMode#READ_ONLY_TRANSACTION}), or if the last {@link + * TransactionMode#READ_WRITE_TRANSACTION} transaction rolled back. It will also throw a + * {@link SpannerException} if the last {@link TransactionMode#READ_WRITE_TRANSACTION} + * transaction was empty when committed. + */ + Timestamp getCommitTimestamp(); + + /** + * Starts a new DDL batch on this connection. A DDL batch allows several DDL statements to be + * grouped into a batch that can be executed as a group. DDL statements that are issued during the + * batch are buffered locally and will return immediately with an OK. It is not guaranteed that a + * DDL statement that has been issued during a batch will eventually succeed when running the + * batch. Aborting a DDL batch will clear the DDL buffer and will have made no changes to the + * database. Running a DDL batch will send all buffered DDL statements to Spanner, and Spanner + * will try to execute these. The result will be OK if all the statements executed successfully. + * If a statement cannot be executed, Spanner will stop execution at that point and return an + * error message for the statement that could not be executed. Preceding statements of the batch + * may have been executed. + * + *

This method may only be called when the connection is in read/write mode, autocommit mode is + * enabled or no read/write transaction has been started, and there is not already another batch + * active. The connection will only accept DDL statements while a DDL batch is active. + */ + void startBatchDdl(); + + /** + * Starts a new DML batch on this connection. A DML batch allows several DML statements to be + * grouped into a batch that can be executed as a group. DML statements that are issued during the + * batch are buffered locally and will return immediately with an OK. It is not guaranteed that a + * DML statement that has been issued during a batch will eventually succeed when running the + * batch. Aborting a DML batch will clear the DML buffer and will have made no changes to the + * database. Running a DML batch will send all buffered DML statements to Spanner, and Spanner + * will try to execute these. The result will be OK if all the statements executed successfully. + * If a statement cannot be executed, Spanner will stop execution at that point and return {@link + * SpannerBatchUpdateException} for the statement that could not be executed. Preceding statements + * of the batch will have been executed, and the update counts of those statements can be + * retrieved through {@link SpannerBatchUpdateException#getUpdateCounts()}. + * + *

This method may only be called when the connection is in read/write mode, autocommit mode is + * enabled or no read/write transaction has been started, and there is not already another batch + * active. The connection will only accept DML statements while a DML batch is active. + */ + void startBatchDml(); + + /** + * Sends all buffered DML or DDL statements of the current batch to the database, waits for these + * to be executed and ends the current batch. The method will throw an exception for the first + * statement that cannot be executed, or return successfully if all statements could be executed. + * If an exception is thrown for a statement in the batch, the preceding statements in the same + * batch may still have been applied to the database. + * + *

This method may only be called when a (possibly empty) batch is active. + * + * @return the update counts in case of a DML batch. Returns an array containing 1 for each + * successful statement and 0 for each failed statement or statement that was not executed DDL + * in case of a DDL batch. + */ + long[] runBatch(); + + /** + * Clears all buffered statements in the current batch and ends the batch. + * + *

This method may only be called when a (possibly empty) batch is active. + */ + void abortBatch(); + + /** @return true if a DDL batch is active on this connection. */ + boolean isDdlBatchActive(); + + /** @return true if a DML batch is active on this connection. */ + boolean isDmlBatchActive(); + + /** + * Executes the given statement if allowed in the current {@link TransactionMode} and connection + * state. The returned value depends on the type of statement: + * + *

    + *
  • Queries will return a {@link ResultSet} + *
  • DML statements will return an update count + *
  • DDL statements will return a {@link ResultType#NO_RESULT} + *
  • Connection and transaction statements (SET AUTOCOMMIT=TRUE|FALSE, SHOW AUTOCOMMIT, SET + * TRANSACTION READ ONLY, etc) will return either a {@link ResultSet} or {@link + * ResultType#NO_RESULT}, depending on the type of statement (SHOW or SET) + *
+ * + * @param statement The statement to execute + * @return the result of the statement + */ + StatementResult execute(Statement statement); + + /** + * Executes the given statement as a query and returns the result as a {@link ResultSet}. This + * method blocks and waits for a response from Spanner. If the statement does not contain a valid + * query, the method will throw a {@link SpannerException}. + * + * @param query The query statement to execute + * @param options the options to configure the query + * @return a {@link ResultSet} with the results of the query + */ + ResultSet executeQuery(Statement query, QueryOption... options); + + /** + * Analyzes a query and returns query plan and/or query execution statistics information. + * + *

The query plan and query statistics information is contained in {@link + * com.google.spanner.v1.ResultSetStats} that can be accessed by calling {@link + * ResultSet#getStats()} on the returned {@code ResultSet}. + * + *

+   * 
+   * {@code
+   * ResultSet resultSet =
+   *     connection.analyzeQuery(
+   *         Statement.of("SELECT SingerId, AlbumId, MarketingBudget FROM Albums"),
+   *         ReadContext.QueryAnalyzeMode.PROFILE);
+   * while (resultSet.next()) {
+   *   // Discard the results. We're only processing because getStats() below requires it.
+   * }
+   * ResultSetStats stats = resultSet.getStats();
+   * }
+   * 
+   * 
+ * + * @param query the query statement to execute + * @param queryMode the mode in which to execute the query + */ + ResultSet analyzeQuery(Statement query, QueryAnalyzeMode queryMode); + + /** + * Executes the given statement as a DML statement. If the statement does not contain a valid DML + * statement, the method will throw a {@link SpannerException}. + * + * @param update The update statement to execute + * @return the number of records that were inserted/updated/deleted by this statement + */ + long executeUpdate(Statement update); + + /** + * Executes a list of DML statements in a single request. The statements will be executed in order + * and the semantics is the same as if each statement is executed by {@link + * Connection#executeUpdate(Statement)} in a loop. This method returns an array of long integers, + * each representing the number of rows modified by each statement. + * + *

If an individual statement fails, execution stops and a {@code SpannerBatchUpdateException} + * is returned, which includes the error and the number of rows affected by the statements that + * are run prior to the error. + * + *

For example, if statements contains 3 statements, and the 2nd one is not a valid DML. This + * method throws a {@code SpannerBatchUpdateException} that contains the error message from the + * 2nd statement, and an array of length 1 that contains the number of rows modified by the 1st + * statement. The 3rd statement will not run. Executes the given statements as DML statements in + * one batch. If one of the statements does not contain a valid DML statement, the method will + * throw a {@link SpannerException}. + * + * @param updates The update statements that will be executed as one batch. + * @return an array containing the update counts per statement. + */ + long[] executeBatchUpdate(Iterable updates); + + /** + * Writes the specified mutation directly to the database and commits the change. The value is + * readable after the successful completion of this method. Writing multiple mutations to a + * database by calling this method multiple times mode is inefficient, as each call will need a + * round trip to the database. Instead, you should consider writing the mutations together by + * calling {@link Connection#write(Iterable)}. + * + *

Calling this method is only allowed in autocommit mode. See {@link + * Connection#bufferedWrite(Iterable)} for writing mutations in transactions. + * + * @param mutation The {@link Mutation} to write to the database + * @throws SpannerException if the {@link Connection} is not in autocommit mode + */ + void write(Mutation mutation); + + /** + * Writes the specified mutations directly to the database and commits the changes. The values are + * readable after the successful completion of this method. + * + *

Calling this method is only allowed in autocommit mode. See {@link + * Connection#bufferedWrite(Iterable)} for writing mutations in transactions. + * + * @param mutations The {@link Mutation}s to write to the database + * @throws SpannerException if the {@link Connection} is not in autocommit mode + */ + void write(Iterable mutations); + + /** + * Buffers the given mutation locally on the current transaction of this {@link Connection}. The + * mutation will be written to the database at the next call to {@link Connection#commit()}. The + * value will not be readable on this {@link Connection} before the transaction is committed. + * + *

Calling this method is only allowed when not in autocommit mode. See {@link + * Connection#write(Mutation)} for writing mutations in autocommit mode. + * + * @param mutation the {@link Mutation} to buffer for writing to the database on the next commit + * @throws SpannerException if the {@link Connection} is in autocommit mode + */ + void bufferedWrite(Mutation mutation); + + /** + * Buffers the given mutations locally on the current transaction of this {@link Connection}. The + * mutations will be written to the database at the next call to {@link Connection#commit()}. The + * values will not be readable on this {@link Connection} before the transaction is committed. + * + *

Calling this method is only allowed when not in autocommit mode. See {@link + * Connection#write(Iterable)} for writing mutations in autocommit mode. + * + * @param mutations the {@link Mutation}s to buffer for writing to the database on the next commit + * @throws SpannerException if the {@link Connection} is in autocommit mode + */ + void bufferedWrite(Iterable mutations); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java new file mode 100644 index 000000000000..b0fd4e426384 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java @@ -0,0 +1,989 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.jdbc.StatementExecutor.StatementTimeout; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import org.threeten.bp.Instant; + +/** Implementation for {@link Connection}, the generic Spanner connection API (not JDBC). */ +class ConnectionImpl implements Connection { + private static final String CLOSED_ERROR_MSG = "This connection is closed"; + private static final String ONLY_ALLOWED_IN_AUTOCOMMIT = + "This method may only be called while in autocommit mode"; + private static final String NOT_ALLOWED_IN_AUTOCOMMIT = + "This method may not be called while in autocommit mode"; + + /** + * Exception that is used to register the stacktrace of the code that opened a {@link Connection}. + * This exception is logged if the application closes without first closing the connection. + */ + static class LeakedConnectionException extends RuntimeException { + private static final long serialVersionUID = 7119433786832158700L; + + private LeakedConnectionException() { + super("Connection was opened at " + Instant.now()); + } + } + + private volatile LeakedConnectionException leakedException = new LeakedConnectionException(); + private final SpannerPool spannerPool; + private final StatementParser parser = StatementParser.INSTANCE; + /** + * The {@link ConnectionStatementExecutor} is responsible for translating parsed {@link + * ClientSideStatement}s into actual method calls on this {@link ConnectionImpl}. I.e. the {@link + * ClientSideStatement} 'SET AUTOCOMMIT ON' will be translated into the method call {@link + * ConnectionImpl#setAutocommit(boolean)} with value true. + */ + private final ConnectionStatementExecutor connectionStatementExecutor = + new ConnectionStatementExecutorImpl(this); + + /** Simple thread factory that is used for fire-and-forget rollbacks. */ + static final class DaemonThreadFactory implements ThreadFactory { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setName("connection-rollback-executor"); + t.setDaemon(true); + return t; + } + } + + /** + * Statements are executed using a separate thread in order to be able to cancel these. Statements + * are automatically cancelled if the configured {@link ConnectionImpl#statementTimeout} is + * exceeded. In autocommit mode, the connection will try to rollback the effects of an update + * statement, but this is not guaranteed to actually succeed. + */ + private final StatementExecutor statementExecutor; + + /** + * The {@link ConnectionOptions} that were used to create this {@link ConnectionImpl}. This is + * retained as it is used for getting a {@link Spanner} object and removing this connection from + * the {@link SpannerPool}. + */ + private final ConnectionOptions options; + + /** The supported batch modes. */ + enum BatchMode { + NONE, + DDL, + DML; + } + + /** The combination of all transaction modes and batch modes. */ + enum UnitOfWorkType { + READ_ONLY_TRANSACTION { + @Override + TransactionMode getTransactionMode() { + return TransactionMode.READ_ONLY_TRANSACTION; + } + }, + READ_WRITE_TRANSACTION { + @Override + TransactionMode getTransactionMode() { + return TransactionMode.READ_WRITE_TRANSACTION; + } + }, + DML_BATCH { + @Override + TransactionMode getTransactionMode() { + return TransactionMode.READ_WRITE_TRANSACTION; + } + }, + DDL_BATCH { + @Override + TransactionMode getTransactionMode() { + return null; + } + }; + + abstract TransactionMode getTransactionMode(); + + static UnitOfWorkType of(TransactionMode transactionMode) { + switch (transactionMode) { + case READ_ONLY_TRANSACTION: + return UnitOfWorkType.READ_ONLY_TRANSACTION; + case READ_WRITE_TRANSACTION: + return UnitOfWorkType.READ_WRITE_TRANSACTION; + default: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "Unknown transaction mode: " + transactionMode); + } + } + } + + private StatementExecutor.StatementTimeout statementTimeout = + new StatementExecutor.StatementTimeout(); + private boolean closed = false; + + private final Spanner spanner; + private DdlClient ddlClient; + private DatabaseClient dbClient; + private boolean autocommit; + private boolean readOnly; + + private UnitOfWork currentUnitOfWork = null; + /** + * The {@link ConnectionImpl#inTransaction} field is only used in autocommit mode to indicate that + * the user has explicitly started a transaction. + */ + private boolean inTransaction = false; + /** + * This field is used to indicate that a transaction begin has been indicated. This is done by + * calling beginTransaction or by setting a transaction property while not in autocommit mode. + */ + private boolean transactionBeginMarked = false; + + private BatchMode batchMode; + private UnitOfWorkType unitOfWorkType; + private final Stack transactionStack = new Stack<>(); + private boolean retryAbortsInternally; + private final List transactionRetryListeners = new ArrayList<>(); + private AutocommitDmlMode autocommitDmlMode = AutocommitDmlMode.TRANSACTIONAL; + private TimestampBound readOnlyStaleness = TimestampBound.strong(); + + /** Create a connection and register it in the SpannerPool. */ + ConnectionImpl(ConnectionOptions options) { + Preconditions.checkNotNull(options); + this.statementExecutor = new StatementExecutor(options.getStatementExecutionInterceptors()); + this.spannerPool = SpannerPool.INSTANCE; + this.options = options; + this.spanner = spannerPool.getSpanner(options, this); + this.dbClient = spanner.getDatabaseClient(options.getDatabaseId()); + this.retryAbortsInternally = options.isRetryAbortsInternally(); + this.readOnly = options.isReadOnly(); + this.autocommit = options.isAutocommit(); + this.ddlClient = createDdlClient(); + setDefaultTransactionOptions(); + } + + /** Constructor only for test purposes. */ + @VisibleForTesting + ConnectionImpl( + ConnectionOptions options, + SpannerPool spannerPool, + DdlClient ddlClient, + DatabaseClient dbClient) { + Preconditions.checkNotNull(options); + Preconditions.checkNotNull(spannerPool); + Preconditions.checkNotNull(ddlClient); + Preconditions.checkNotNull(dbClient); + this.statementExecutor = + new StatementExecutor(Collections.emptyList()); + this.spannerPool = spannerPool; + this.options = options; + this.spanner = spannerPool.getSpanner(options, this); + this.ddlClient = ddlClient; + this.dbClient = dbClient; + setReadOnly(options.isReadOnly()); + setAutocommit(options.isAutocommit()); + setDefaultTransactionOptions(); + } + + private DdlClient createDdlClient() { + return DdlClient.newBuilder() + .setDatabaseAdminClient(spanner.getDatabaseAdminClient()) + .setInstanceId(options.getInstanceId()) + .setDatabaseName(options.getDatabaseName()) + .build(); + } + + @Override + public void close() { + if (!isClosed()) { + try { + if (isTransactionStarted()) { + try { + rollback(); + } catch (Exception e) { + // Ignore as we are closing the connection. + } + } + statementExecutor.shutdownNow(); + spannerPool.removeConnection(options, this); + leakedException = null; + } finally { + this.closed = true; + } + } + } + + /** Get the current unit-of-work type of this connection. */ + UnitOfWorkType getUnitOfWorkType() { + return unitOfWorkType; + } + + /** Get the current batch mode of this connection. */ + BatchMode getBatchMode() { + return batchMode; + } + + /** @return true if this connection is in a batch. */ + boolean isInBatch() { + return batchMode != BatchMode.NONE; + } + + /** Get the call stack from when the {@link Connection} was opened. */ + LeakedConnectionException getLeakedException() { + return leakedException; + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public void setAutocommit(boolean autocommit) { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set autocommit while in a batch"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), "Cannot set autocommit while a transaction is active"); + ConnectionPreconditions.checkState( + !(isAutocommit() && isInTransaction()), + "Cannot set autocommit while in a temporary transaction"); + ConnectionPreconditions.checkState( + !transactionBeginMarked, "Cannot set autocommit when a transaction has begun"); + this.autocommit = autocommit; + clearLastTransactionAndSetDefaultTransactionOptions(); + // Reset the readOnlyStaleness value if it is no longer compatible with the new autocommit + // value. + if (!autocommit + && (readOnlyStaleness.getMode() == Mode.MAX_STALENESS + || readOnlyStaleness.getMode() == Mode.MIN_READ_TIMESTAMP)) { + readOnlyStaleness = TimestampBound.strong(); + } + } + + @Override + public boolean isAutocommit() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return internalIsAutocommit(); + } + + private boolean internalIsAutocommit() { + return this.autocommit; + } + + @Override + public void setReadOnly(boolean readOnly) { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set read-only while in a batch"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), "Cannot set read-only while a transaction is active"); + ConnectionPreconditions.checkState( + !(isAutocommit() && isInTransaction()), + "Cannot set read-only while in a temporary transaction"); + ConnectionPreconditions.checkState( + !transactionBeginMarked, "Cannot set read-only when a transaction has begun"); + this.readOnly = readOnly; + clearLastTransactionAndSetDefaultTransactionOptions(); + } + + @Override + public boolean isReadOnly() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.readOnly; + } + + private void clearLastTransactionAndSetDefaultTransactionOptions() { + setDefaultTransactionOptions(); + this.currentUnitOfWork = null; + } + + @Override + public void setAutocommitDmlMode(AutocommitDmlMode mode) { + Preconditions.checkNotNull(mode); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot set autocommit DML mode while in a batch"); + ConnectionPreconditions.checkState( + !isInTransaction() && isAutocommit(), + "Cannot set autocommit DML mode while not in autocommit mode or while a transaction is active"); + ConnectionPreconditions.checkState( + !isReadOnly(), "Cannot set autocommit DML mode for a read-only connection"); + this.autocommitDmlMode = mode; + } + + @Override + public AutocommitDmlMode getAutocommitDmlMode() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot get autocommit DML mode while in a batch"); + return this.autocommitDmlMode; + } + + @Override + public void setReadOnlyStaleness(TimestampBound staleness) { + Preconditions.checkNotNull(staleness); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set read-only while in a batch"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), + "Cannot set read-only staleness when a transaction has been started"); + if (staleness.getMode() == Mode.MAX_STALENESS + || staleness.getMode() == Mode.MIN_READ_TIMESTAMP) { + // These values are only allowed in autocommit mode. + ConnectionPreconditions.checkState( + isAutocommit() && !inTransaction, + "MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode"); + } + this.readOnlyStaleness = staleness; + } + + @Override + public TimestampBound getReadOnlyStaleness() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isBatchActive(), "Cannot get read-only while in a batch"); + return this.readOnlyStaleness; + } + + @Override + public void setStatementTimeout(long timeout, TimeUnit unit) { + Preconditions.checkArgument(timeout > 0L, "Zero or negative timeout values are not allowed"); + Preconditions.checkArgument( + StatementTimeout.isValidTimeoutUnit(unit), + "Time unit must be one of NANOSECONDS, MICROSECONDS, MILLISECONDS or SECONDS"); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + this.statementTimeout.setTimeoutValue(timeout, unit); + } + + @Override + public void clearStatementTimeout() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + this.statementTimeout.clearTimeoutValue(); + } + + @Override + public long getStatementTimeout(TimeUnit unit) { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + Preconditions.checkArgument( + StatementTimeout.isValidTimeoutUnit(unit), + "Time unit must be one of NANOSECONDS, MICROSECONDS, MILLISECONDS or SECONDS"); + return this.statementTimeout.getTimeoutValue(unit); + } + + @Override + public boolean hasStatementTimeout() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.statementTimeout.hasTimeout(); + } + + @Override + public void cancel() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + if (this.currentUnitOfWork != null) { + currentUnitOfWork.cancel(); + } + } + + @Override + public TransactionMode getTransactionMode() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isDdlBatchActive(), "This connection is in a DDL batch"); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + return unitOfWorkType.getTransactionMode(); + } + + @Override + public void setTransactionMode(TransactionMode transactionMode) { + Preconditions.checkNotNull(transactionMode); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot set transaction mode while in a batch"); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), + "The transaction mode cannot be set after the transaction has started"); + ConnectionPreconditions.checkState( + !isReadOnly() || transactionMode == TransactionMode.READ_ONLY_TRANSACTION, + "The transaction mode can only be READ_ONLY when the connection is in read_only mode"); + + this.transactionBeginMarked = true; + this.unitOfWorkType = UnitOfWorkType.of(transactionMode); + } + + /** + * Throws an {@link SpannerException} with code {@link ErrorCode#FAILED_PRECONDITION} if the + * current state of this connection does not allow changing the setting for retryAbortsInternally. + */ + private void checkSetRetryAbortsInternallyAvailable() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + ConnectionPreconditions.checkState( + getTransactionMode() == TransactionMode.READ_WRITE_TRANSACTION, + "RetryAbortsInternally is only available for read-write transactions"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), + "RetryAbortsInternally cannot be set after the transaction has started"); + } + + @Override + public boolean isRetryAbortsInternally() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return retryAbortsInternally; + } + + @Override + public void setRetryAbortsInternally(boolean retryAbortsInternally) { + checkSetRetryAbortsInternallyAvailable(); + this.retryAbortsInternally = retryAbortsInternally; + } + + @Override + public void addTransactionRetryListener(TransactionRetryListener listener) { + Preconditions.checkNotNull(listener); + transactionRetryListeners.add(listener); + } + + @Override + public boolean removeTransactionRetryListener(TransactionRetryListener listener) { + Preconditions.checkNotNull(listener); + return transactionRetryListeners.remove(listener); + } + + @Override + public Iterator getTransactionRetryListeners() { + return Collections.unmodifiableList(transactionRetryListeners).iterator(); + } + + @Override + public boolean isInTransaction() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return internalIsInTransaction(); + } + + /** Returns true if this connection currently is in a transaction (and not a batch). */ + private boolean internalIsInTransaction() { + return !isDdlBatchActive() && (!internalIsAutocommit() || inTransaction); + } + + @Override + public boolean isTransactionStarted() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return internalIsTransactionStarted(); + } + + private boolean internalIsTransactionStarted() { + if (internalIsAutocommit() && !inTransaction) { + return false; + } + return internalIsInTransaction() + && this.currentUnitOfWork != null + && this.currentUnitOfWork.getState() == UnitOfWorkState.STARTED; + } + + @Override + public Timestamp getReadTimestamp() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + this.currentUnitOfWork != null, "There is no transaction on this connection"); + return this.currentUnitOfWork.getReadTimestamp(); + } + + Timestamp getReadTimestampOrNull() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.currentUnitOfWork == null ? null : this.currentUnitOfWork.getReadTimestampOrNull(); + } + + @Override + public Timestamp getCommitTimestamp() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + this.currentUnitOfWork != null, "There is no transaction on this connection"); + return this.currentUnitOfWork.getCommitTimestamp(); + } + + Timestamp getCommitTimestampOrNull() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.currentUnitOfWork == null + ? null + : this.currentUnitOfWork.getCommitTimestampOrNull(); + } + + /** Resets this connection to its default transaction options. */ + private void setDefaultTransactionOptions() { + if (transactionStack.isEmpty()) { + unitOfWorkType = + isReadOnly() + ? UnitOfWorkType.READ_ONLY_TRANSACTION + : UnitOfWorkType.READ_WRITE_TRANSACTION; + batchMode = BatchMode.NONE; + } else { + popUnitOfWorkFromTransactionStack(); + } + } + + @Override + public void beginTransaction() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "This connection has an active batch and cannot begin a transaction"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), + "Beginning a new transaction is not allowed when a transaction is already running"); + ConnectionPreconditions.checkState(!transactionBeginMarked, "A transaction has already begun"); + + transactionBeginMarked = true; + clearLastTransactionAndSetDefaultTransactionOptions(); + if (isAutocommit()) { + inTransaction = true; + } + } + + /** Internal interface for ending a transaction (commit/rollback). */ + private static interface EndTransactionMethod { + public void end(UnitOfWork t); + } + + private static final class Commit implements EndTransactionMethod { + @Override + public void end(UnitOfWork t) { + t.commit(); + } + } + + private final Commit commit = new Commit(); + + @Override + public void commit() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + endCurrentTransaction(commit); + } + + private static final class Rollback implements EndTransactionMethod { + @Override + public void end(UnitOfWork t) { + t.rollback(); + } + } + + private final Rollback rollback = new Rollback(); + + @Override + public void rollback() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + endCurrentTransaction(rollback); + } + + private void endCurrentTransaction(EndTransactionMethod endTransactionMethod) { + ConnectionPreconditions.checkState(!isBatchActive(), "This connection has an active batch"); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + try { + if (isTransactionStarted()) { + endTransactionMethod.end(getCurrentUnitOfWorkOrStartNewUnitOfWork()); + } else { + this.currentUnitOfWork = null; + } + } finally { + transactionBeginMarked = false; + if (isAutocommit()) { + inTransaction = false; + } + setDefaultTransactionOptions(); + } + } + + @Override + public StatementResult execute(Statement statement) { + Preconditions.checkNotNull(statement); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ParsedStatement parsedStatement = parser.parse(statement); + switch (parsedStatement.getType()) { + case CLIENT_SIDE: + return parsedStatement + .getClientSideStatement() + .execute(connectionStatementExecutor, parsedStatement.getSqlWithoutComments()); + case QUERY: + return StatementResultImpl.of(internalExecuteQuery(parsedStatement, AnalyzeMode.NONE)); + case UPDATE: + return StatementResultImpl.of(internalExecuteUpdate(parsedStatement)); + case DDL: + executeDdl(parsedStatement); + return StatementResultImpl.noResult(); + case UNKNOWN: + default: + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "Unknown statement: " + parsedStatement.getSqlWithoutComments()); + } + + @Override + public ResultSet executeQuery(Statement query, QueryOption... options) { + return parseAndExecuteQuery(query, AnalyzeMode.NONE, options); + } + + @Override + public ResultSet analyzeQuery(Statement query, QueryAnalyzeMode queryMode) { + Preconditions.checkNotNull(queryMode); + return parseAndExecuteQuery(query, AnalyzeMode.of(queryMode)); + } + + /** + * Parses the given statement as a query and executes it. Throws a {@link SpannerException} if the + * statement is not a query. + */ + private ResultSet parseAndExecuteQuery( + Statement query, AnalyzeMode analyzeMode, QueryOption... options) { + Preconditions.checkNotNull(query); + Preconditions.checkNotNull(analyzeMode); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ParsedStatement parsedStatement = parser.parse(query); + if (parsedStatement.isQuery()) { + switch (parsedStatement.getType()) { + case CLIENT_SIDE: + return parsedStatement + .getClientSideStatement() + .execute(connectionStatementExecutor, parsedStatement.getSqlWithoutComments()) + .getResultSet(); + case QUERY: + return internalExecuteQuery(parsedStatement, analyzeMode); + case UPDATE: + case DDL: + case UNKNOWN: + default: + } + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "Statement is not a query: " + parsedStatement.getSqlWithoutComments()); + } + + @Override + public long executeUpdate(Statement update) { + Preconditions.checkNotNull(update); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ParsedStatement parsedStatement = parser.parse(update); + if (parsedStatement.isUpdate()) { + switch (parsedStatement.getType()) { + case UPDATE: + return internalExecuteUpdate(parsedStatement); + case CLIENT_SIDE: + case QUERY: + case DDL: + case UNKNOWN: + default: + } + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); + } + + @Override + public long[] executeBatchUpdate(Iterable updates) { + Preconditions.checkNotNull(updates); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + // Check that there are only DML statements in the input. + List parsedStatements = new LinkedList<>(); + for (Statement update : updates) { + ParsedStatement parsedStatement = parser.parse(update); + if (parsedStatement.isUpdate()) { + switch (parsedStatement.getType()) { + case UPDATE: + parsedStatements.add(parsedStatement); + break; + case CLIENT_SIDE: + case QUERY: + case DDL: + case UNKNOWN: + default: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "The batch update list contains a statement that is not an update statement: " + + parsedStatement.getSqlWithoutComments()); + } + } + } + return internalExecuteBatchUpdate(parsedStatements); + } + + private ResultSet internalExecuteQuery( + final ParsedStatement statement, + final AnalyzeMode analyzeMode, + final QueryOption... options) { + Preconditions.checkArgument( + statement.getType() == StatementType.QUERY, "Statement must be a query"); + UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); + try { + return transaction.executeQuery(statement, analyzeMode, options); + } catch (SpannerException e) { + // In case of a timed out or cancelled query we need to replace the executor to ensure that we + // have an executor that is not busy executing a statement. Although we try to cancel the + // current statement, it is not guaranteed to actually stop the execution directly. + if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED + || e.getErrorCode() == ErrorCode.CANCELLED) { + this.statementExecutor.recreate(); + } + throw e; + } + } + + private long internalExecuteUpdate(final ParsedStatement update) { + Preconditions.checkArgument( + update.getType() == StatementType.UPDATE, "Statement must be an update"); + UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); + try { + return transaction.executeUpdate(update); + } catch (SpannerException e) { + // In case of a timed out or cancelled query we need to replace the executor to ensure that we + // have an executor that is not busy executing a statement. Although we try to cancel the + // current statement, it is not guaranteed to actually stop the execution directly. + if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED + || e.getErrorCode() == ErrorCode.CANCELLED) { + this.statementExecutor.recreate(); + } + throw e; + } + } + + private long[] internalExecuteBatchUpdate(final List updates) { + UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); + try { + return transaction.executeBatchUpdate(updates); + } catch (SpannerException e) { + // In case of a timed out or cancelled query we need to replace the executor to ensure that we + // have an executor that is not busy executing a statement. Although we try to cancel the + // current statement, it is not guaranteed to actually stop the execution directly. + if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED + || e.getErrorCode() == ErrorCode.CANCELLED) { + this.statementExecutor.recreate(); + } + throw e; + } + } + + /** + * Returns the current {@link UnitOfWork} of this connection, or creates a new one based on the + * current transaction settings of the connection and returns that. + */ + private UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { + if (this.currentUnitOfWork == null || !this.currentUnitOfWork.isActive()) { + this.currentUnitOfWork = createNewUnitOfWork(); + } + return this.currentUnitOfWork; + } + + private UnitOfWork createNewUnitOfWork() { + if (isAutocommit() && !isInTransaction() && !isInBatch()) { + return SingleUseTransaction.newBuilder() + .setDdlClient(ddlClient) + .setDatabaseClient(dbClient) + .setReadOnly(isReadOnly()) + .setReadOnlyStaleness(readOnlyStaleness) + .setAutocommitDmlMode(autocommitDmlMode) + .setStatementTimeout(statementTimeout) + .withStatementExecutor(statementExecutor) + .build(); + } else { + switch (getUnitOfWorkType()) { + case READ_ONLY_TRANSACTION: + return ReadOnlyTransaction.newBuilder() + .setDatabaseClient(dbClient) + .setReadOnlyStaleness(readOnlyStaleness) + .setStatementTimeout(statementTimeout) + .withStatementExecutor(statementExecutor) + .build(); + case READ_WRITE_TRANSACTION: + return ReadWriteTransaction.newBuilder() + .setDatabaseClient(dbClient) + .setRetryAbortsInternally(retryAbortsInternally) + .setTransactionRetryListeners(transactionRetryListeners) + .setStatementTimeout(statementTimeout) + .withStatementExecutor(statementExecutor) + .build(); + case DML_BATCH: + // A DML batch can run inside the current transaction. It should therefore only + // temporarily replace the current transaction. + pushCurrentUnitOfWorkToTransactionStack(); + return DmlBatch.newBuilder() + .setTransaction(currentUnitOfWork) + .setStatementTimeout(statementTimeout) + .withStatementExecutor(statementExecutor) + .build(); + case DDL_BATCH: + return DdlBatch.newBuilder() + .setDdlClient(ddlClient) + .setStatementTimeout(statementTimeout) + .withStatementExecutor(statementExecutor) + .build(); + default: + } + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "This connection does not have an active transaction and the state of this connection does not allow any new transactions to be started"); + } + + /** Pushes the current unit of work to the stack of nested transactions. */ + private void pushCurrentUnitOfWorkToTransactionStack() { + Preconditions.checkState(currentUnitOfWork != null, "There is no current transaction"); + transactionStack.push(currentUnitOfWork); + } + + /** Set the {@link UnitOfWork} of this connection back to the previous {@link UnitOfWork}. */ + private void popUnitOfWorkFromTransactionStack() { + Preconditions.checkState( + !transactionStack.isEmpty(), "There is no unit of work in the transaction stack"); + this.currentUnitOfWork = transactionStack.pop(); + } + + private void executeDdl(ParsedStatement ddl) { + getCurrentUnitOfWorkOrStartNewUnitOfWork().executeDdl(ddl); + } + + @Override + public void write(Mutation mutation) { + Preconditions.checkNotNull(mutation); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(isAutocommit(), ONLY_ALLOWED_IN_AUTOCOMMIT); + getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutation); + } + + @Override + public void write(Iterable mutations) { + Preconditions.checkNotNull(mutations); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(isAutocommit(), ONLY_ALLOWED_IN_AUTOCOMMIT); + getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutations); + } + + @Override + public void bufferedWrite(Mutation mutation) { + Preconditions.checkNotNull(mutation); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isAutocommit(), NOT_ALLOWED_IN_AUTOCOMMIT); + getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutation); + } + + @Override + public void bufferedWrite(Iterable mutations) { + Preconditions.checkNotNull(mutations); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isAutocommit(), NOT_ALLOWED_IN_AUTOCOMMIT); + getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutations); + } + + @Override + public void startBatchDdl() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot start a DDL batch when a batch is already active"); + ConnectionPreconditions.checkState( + !isReadOnly(), "Cannot start a DDL batch when the connection is in read-only mode"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), "Cannot start a DDL batch while a transaction is active"); + ConnectionPreconditions.checkState( + !(isAutocommit() && isInTransaction()), + "Cannot start a DDL batch while in a temporary transaction"); + ConnectionPreconditions.checkState( + !transactionBeginMarked, "Cannot start a DDL batch when a transaction has begun"); + this.batchMode = BatchMode.DDL; + this.unitOfWorkType = UnitOfWorkType.DDL_BATCH; + this.currentUnitOfWork = createNewUnitOfWork(); + } + + @Override + public void startBatchDml() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot start a DML batch when a batch is already active"); + ConnectionPreconditions.checkState( + !isReadOnly(), "Cannot start a DML batch when the connection is in read-only mode"); + ConnectionPreconditions.checkState( + !(isInTransaction() && getTransactionMode() == TransactionMode.READ_ONLY_TRANSACTION), + "Cannot start a DML batch when a read-only transaction is in progress"); + // Make sure that there is a current unit of work that the batch can use. + getCurrentUnitOfWorkOrStartNewUnitOfWork(); + // Then create the DML batch. + this.batchMode = BatchMode.DML; + this.unitOfWorkType = UnitOfWorkType.DML_BATCH; + this.currentUnitOfWork = createNewUnitOfWork(); + } + + @Override + public long[] runBatch() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(isBatchActive(), "This connection has no active batch"); + try { + if (this.currentUnitOfWork != null) { + return this.currentUnitOfWork.runBatch(); + } + return new long[0]; + } finally { + this.batchMode = BatchMode.NONE; + setDefaultTransactionOptions(); + } + } + + @Override + public void abortBatch() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(isBatchActive(), "This connection has no active batch"); + try { + if (this.currentUnitOfWork != null) { + this.currentUnitOfWork.abortBatch(); + } + } finally { + this.batchMode = BatchMode.NONE; + setDefaultTransactionOptions(); + } + } + + private boolean isBatchActive() { + return isDdlBatchActive() || isDmlBatchActive(); + } + + @Override + public boolean isDdlBatchActive() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.batchMode == BatchMode.DDL; + } + + @Override + public boolean isDmlBatchActive() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.batchMode == BatchMode.DML; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java new file mode 100644 index 000000000000..f483d1250c44 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -0,0 +1,592 @@ +/* + * Copyright 2019 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.auth.Credentials; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.ServiceOptions; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Options for creating a {@link Connection} to a Google Cloud Spanner database. + * + *

Usage: + * + *

+ * 
+ * {@code
+ * ConnectionOptions options = ConnectionOptions.newBuilder()
+ *       .setUri("cloudspanner:/projects/my_project_id/instances/my_instance_id/databases/my_database_name?autocommit=false")
+ *       .setCredentialsUrl("/home/cloudspanner-keys/my-key.json")
+ *       .build();
+ * try(Connection connection = options.getConnection()) {
+ *   try(ResultSet rs = connection.executeQuery(Statement.of("SELECT SingerId, AlbumId, MarketingBudget FROM Albums"))) {
+ *     while(rs.next()) {
+ *       // do something
+ *     }
+ *   }
+ * }
+ * }
+ * 
+ * 
+ */ +class ConnectionOptions { + /** Supported connection properties that can be included in the connection URI. */ + public static class ConnectionProperty { + private static final String[] BOOLEAN_VALUES = new String[] {"true", "false"}; + private final String name; + private final String description; + private final String defaultValue; + private final String[] validValues; + private final int hashCode; + + private static ConnectionProperty createStringProperty(String name, String description) { + return new ConnectionProperty(name, description, "", null); + } + + private static ConnectionProperty createBooleanProperty( + String name, String description, boolean defaultValue) { + return new ConnectionProperty( + name, description, String.valueOf(defaultValue), BOOLEAN_VALUES); + } + + private static ConnectionProperty createEmptyProperty(String name) { + return new ConnectionProperty(name, "", "", null); + } + + private ConnectionProperty( + String name, String description, String defaultValue, String[] validValues) { + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(description); + Preconditions.checkNotNull(defaultValue); + this.name = name; + this.description = description; + this.defaultValue = defaultValue; + this.validValues = validValues; + this.hashCode = name.toLowerCase().hashCode(); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ConnectionProperty)) { + return false; + } + return ((ConnectionProperty) o).name.equalsIgnoreCase(this.name); + } + + /** @return the name of this connection property. */ + public String getName() { + return name; + } + + /** @return the description of this connection property. */ + public String getDescription() { + return description; + } + + /** @return the default value of this connection property. */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * @return the valid values for this connection property. null indicates no + * restriction. + */ + public String[] getValidValues() { + return validValues; + } + } + + private static final boolean DEFAULT_USE_PLAIN_TEXT = false; + static final boolean DEFAULT_AUTOCOMMIT = true; + static final boolean DEFAULT_READONLY = false; + static final boolean DEFAULT_RETRY_ABORTS_INTERNALLY = true; + private static final String DEFAULT_CREDENTIALS = null; + private static final String DEFAULT_NUM_CHANNELS = null; + private static final String DEFAULT_USER_AGENT = null; + + private static final String PLAIN_TEXT_PROTOCOL = "http:"; + private static final String HOST_PROTOCOL = "https:"; + private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; + /** Use plain text is only for local testing purposes. */ + private static final String USE_PLAIN_TEXT_PROPERTY_NAME = "usePlainText"; + /** Name of the 'autocommit' connection property. */ + public static final String AUTOCOMMIT_PROPERTY_NAME = "autocommit"; + /** Name of the 'readonly' connection property. */ + public static final String READONLY_PROPERTY_NAME = "readonly"; + /** Name of the 'retry aborts internally' connection property. */ + public static final String RETRY_ABORTS_INTERNALLY_PROPERTY_NAME = "retryAbortsInternally"; + /** Name of the 'credentials' connection property. */ + public static final String CREDENTIALS_PROPERTY_NAME = "credentials"; + /** Name of the 'numChannels' connection property. */ + public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels"; + /** Custom user agent string is only for other Google libraries. */ + private static final String USER_AGENT_PROPERTY_NAME = "userAgent"; + + /** All valid connection properties. */ + public static final Set VALID_PROPERTIES = + Collections.unmodifiableSet( + new HashSet<>( + Arrays.asList( + ConnectionProperty.createBooleanProperty( + AUTOCOMMIT_PROPERTY_NAME, "", DEFAULT_AUTOCOMMIT), + ConnectionProperty.createBooleanProperty( + READONLY_PROPERTY_NAME, "", DEFAULT_READONLY), + ConnectionProperty.createBooleanProperty( + RETRY_ABORTS_INTERNALLY_PROPERTY_NAME, "", DEFAULT_RETRY_ABORTS_INTERNALLY), + ConnectionProperty.createStringProperty(CREDENTIALS_PROPERTY_NAME, ""), + ConnectionProperty.createStringProperty(NUM_CHANNELS_PROPERTY_NAME, ""), + ConnectionProperty.createBooleanProperty( + USE_PLAIN_TEXT_PROPERTY_NAME, "", DEFAULT_USE_PLAIN_TEXT), + ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, "")))); + + private static final Set INTERNAL_PROPERTIES = + Collections.unmodifiableSet( + new HashSet<>( + Arrays.asList( + ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, "")))); + private static final Set INTERNAL_VALID_PROPERTIES = + Sets.union(VALID_PROPERTIES, INTERNAL_PROPERTIES); + + /** + * Gets the default project-id for the current environment as defined by {@link + * ServiceOptions#getDefaultProjectId()}, and if none could be found, the project-id of the given + * credentials if it contains any. + * + * @param credentials The credentials to use to get the default project-id if none could be found + * in the environment. + * @return the default project-id. + */ + public static String getDefaultProjectId(Credentials credentials) { + String projectId = SpannerOptions.getDefaultProjectId(); + if (projectId == null + && credentials != null + && credentials instanceof ServiceAccountCredentials) { + projectId = ((ServiceAccountCredentials) credentials).getProjectId(); + } + return projectId; + } + + /** + * Closes all {@link Spanner} instances that have been opened by connections + * during the lifetime of this JVM. Call this method at the end of your application to free up + * resources. You must close all {@link Connection}s that have been opened by your application + * before calling this method. Failing to do so, will cause this method to throw a {@link + * SpannerException}. + * + *

This method is also automatically called by a shutdown hook (see {@link + * Runtime#addShutdownHook(Thread)}) when the JVM is shutdown gracefully. + */ + public static void closeSpanner() { + SpannerPool.INSTANCE.checkAndCloseSpanners(); + } + + /** Builder for {@link ConnectionOptions} instances. */ + public static class Builder { + private String uri; + private String credentialsUrl; + private Credentials credentials; + private List statementExecutionInterceptors = + Collections.emptyList(); + + private Builder() {} + + /** Spanner {@link ConnectionOptions} URI format. */ + public static final String SPANNER_URI_FORMAT = + "(?:cloudspanner:)(?//[\\w.-]+(?:\\.[\\w\\.-]+)*[\\w\\-\\._~:/?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=.]+)?/projects/(?(([a-z]|[-]|[0-9])+|(DEFAULT_PROJECT_ID)))(/instances/(?([a-z]|[-]|[0-9])+)(/databases/(?([a-z]|[-]|[_]|[0-9])+))?)?(?:[?|;].*)?"; + + private static final String SPANNER_URI_REGEX = "(?is)^" + SPANNER_URI_FORMAT + "$"; + private static final Pattern SPANNER_URI_PATTERN = Pattern.compile(SPANNER_URI_REGEX); + private static final String HOST_GROUP = "HOSTGROUP"; + private static final String PROJECT_GROUP = "PROJECTGROUP"; + private static final String INSTANCE_GROUP = "INSTANCEGROUP"; + private static final String DATABASE_GROUP = "DATABASEGROUP"; + private static final String DEFAULT_PROJECT_ID_PLACEHOLDER = "DEFAULT_PROJECT_ID"; + + private boolean isValidUri(String uri) { + return SPANNER_URI_PATTERN.matcher(uri).matches(); + } + + /** + * Sets the URI of the Cloud Spanner database to connect to. A connection URI must be specified + * in this format: + * + *

+     * cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\?property-name=property-value[;property-name=property-value]*]?
+     * 
+ * + * The property-value strings should be url-encoded. + * + *

The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This + * placeholder will be replaced by the default project id of the environment that is requesting + * a connection. + * + *

The supported properties are: + * + *

    + *
  • credentials (String): URL for the credentials file to use for the connection. This + * property is only used if no credentials have been specified using the {@link + * ConnectionOptions.Builder#setCredentialsUrl(String)} method. If you do not specify any + * credentials at all, the default credentials of the environment as returned by {@link + * GoogleCredentials#getApplicationDefault()} will be used. + *
  • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is + * true. + *
  • readonly (boolean): Sets the initial readonly mode for the connection. Default is + * false. + *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the + * connection. Default is true. + *
+ * + * @param uri The URI of the Spanner database to connect to. + * @return this builder + */ + public Builder setUri(String uri) { + Preconditions.checkArgument( + isValidUri(uri), + "The specified URI is not a valid Cloud Spanner connection URI. Please specify a URI in the format \"cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\\?property-name=property-value[;property-name=property-value]*]?\""); + checkValidProperties(uri); + this.uri = uri; + return this; + } + + /** + * Sets the URL of the credentials file to use for this connection. The URL may be a reference + * to a file on the local file system, or to a file on Google Cloud Storage. References to + * Google Cloud Storage files are only allowed when the application is running on Google Cloud + * and the environment has access to the specified storage location. + * + *

If you do not specify a credentialsUrl (either by using this setter, or by specifying on + * the connection URI), the credentials returned by {@link + * GoogleCredentials#getApplicationDefault()} will be used for the connection. + * + * @param credentialsUrl A valid file or Google Cloud Storage URL for the credentials file to be + * used. + * @return this builder + */ + public Builder setCredentialsUrl(String credentialsUrl) { + this.credentialsUrl = credentialsUrl; + return this; + } + + @VisibleForTesting + Builder setStatementExecutionInterceptors(List interceptors) { + this.statementExecutionInterceptors = interceptors; + return this; + } + + @VisibleForTesting + Builder setCredentials(Credentials credentials) { + this.credentials = credentials; + return this; + } + + /** @return the {@link ConnectionOptions} */ + public ConnectionOptions build() { + Preconditions.checkState(this.uri != null, "Connection URI is required"); + return new ConnectionOptions(this); + } + } + + /** + * Create a {@link Builder} for {@link ConnectionOptions}. Use this method to create {@link + * ConnectionOptions} that can be used to obtain a {@link Connection}. + * + * @return a new {@link Builder} + */ + public static Builder newBuilder() { + return new Builder(); + } + + private final String uri; + private final String credentialsUrl; + + private final boolean usePlainText; + private final String host; + private final String projectId; + private final String instanceId; + private final String databaseName; + private final Credentials credentials; + private final Integer numChannels; + private final String userAgent; + + private final boolean autocommit; + private final boolean readOnly; + private final boolean retryAbortsInternally; + private final List statementExecutionInterceptors; + + private ConnectionOptions(Builder builder) { + Matcher matcher = Builder.SPANNER_URI_PATTERN.matcher(builder.uri); + Preconditions.checkArgument( + matcher.find(), String.format("Invalid connection URI specified: %s", builder.uri)); + checkValidProperties(builder.uri); + + this.uri = builder.uri; + this.credentialsUrl = + builder.credentialsUrl != null ? builder.credentialsUrl : parseCredentials(builder.uri); + this.usePlainText = parseUsePlainText(this.uri); + this.userAgent = parseUserAgent(this.uri); + + this.host = + matcher.group(Builder.HOST_GROUP) == null + ? DEFAULT_HOST + : (usePlainText ? PLAIN_TEXT_PROTOCOL : HOST_PROTOCOL) + + matcher.group(Builder.HOST_GROUP); + this.instanceId = matcher.group(Builder.INSTANCE_GROUP); + this.databaseName = matcher.group(Builder.DATABASE_GROUP); + this.credentials = + builder.credentials == null + ? getCredentialsService().createCredentials(this.credentialsUrl) + : builder.credentials; + String numChannelsValue = parseNumChannels(builder.uri); + if (numChannelsValue != null) { + try { + this.numChannels = Integer.valueOf(numChannelsValue); + } catch (NumberFormatException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "Invalid numChannels value specified: " + numChannelsValue, + e); + } + } else { + this.numChannels = null; + } + + String projectId = matcher.group(Builder.PROJECT_GROUP); + if (Builder.DEFAULT_PROJECT_ID_PLACEHOLDER.equalsIgnoreCase(projectId)) { + projectId = getDefaultProjectId(this.credentials); + } + this.projectId = projectId; + + this.autocommit = parseAutocommit(this.uri); + this.readOnly = parseReadOnly(this.uri); + this.retryAbortsInternally = parseRetryAbortsInternally(this.uri); + this.statementExecutionInterceptors = + Collections.unmodifiableList(builder.statementExecutionInterceptors); + } + + @VisibleForTesting + CredentialsService getCredentialsService() { + return CredentialsService.INSTANCE; + } + + @VisibleForTesting + static boolean parseUsePlainText(String uri) { + String value = parseUriProperty(uri, USE_PLAIN_TEXT_PROPERTY_NAME); + return value != null ? Boolean.valueOf(value) : DEFAULT_USE_PLAIN_TEXT; + } + + @VisibleForTesting + static boolean parseAutocommit(String uri) { + String value = parseUriProperty(uri, AUTOCOMMIT_PROPERTY_NAME); + return value != null ? Boolean.valueOf(value) : DEFAULT_AUTOCOMMIT; + } + + @VisibleForTesting + static boolean parseReadOnly(String uri) { + String value = parseUriProperty(uri, READONLY_PROPERTY_NAME); + return value != null ? Boolean.valueOf(value) : DEFAULT_READONLY; + } + + @VisibleForTesting + static boolean parseRetryAbortsInternally(String uri) { + String value = parseUriProperty(uri, RETRY_ABORTS_INTERNALLY_PROPERTY_NAME); + return value != null ? Boolean.valueOf(value) : DEFAULT_RETRY_ABORTS_INTERNALLY; + } + + @VisibleForTesting + static String parseCredentials(String uri) { + String value = parseUriProperty(uri, CREDENTIALS_PROPERTY_NAME); + return value != null ? value : DEFAULT_CREDENTIALS; + } + + @VisibleForTesting + static String parseNumChannels(String uri) { + String value = parseUriProperty(uri, NUM_CHANNELS_PROPERTY_NAME); + return value != null ? value : DEFAULT_NUM_CHANNELS; + } + + @VisibleForTesting + static String parseUserAgent(String uri) { + String value = parseUriProperty(uri, USER_AGENT_PROPERTY_NAME); + return value != null ? value : DEFAULT_USER_AGENT; + } + + @VisibleForTesting + static String parseUriProperty(String uri, String property) { + Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); + Matcher matcher = pattern.matcher(uri); + if (matcher.find() && matcher.groupCount() == 1) { + return matcher.group(1); + } + return null; + } + + /** Check that only valid properties have been specified. */ + @VisibleForTesting + static void checkValidProperties(String uri) { + String invalidProperties = ""; + List properties = parseProperties(uri); + for (String property : properties) { + if (!INTERNAL_VALID_PROPERTIES.contains(ConnectionProperty.createEmptyProperty(property))) { + if (invalidProperties.length() > 0) { + invalidProperties = invalidProperties + ", "; + } + invalidProperties = invalidProperties + property; + } + } + Preconditions.checkArgument( + invalidProperties.isEmpty(), + "Invalid properties found in connection URI: " + invalidProperties.toString()); + } + + @VisibleForTesting + static List parseProperties(String uri) { + Pattern pattern = Pattern.compile("(?is)(?:\\?|;)(?.*?)=(?:.*?)"); + Matcher matcher = pattern.matcher(uri); + List res = new ArrayList<>(); + while (matcher.find() && matcher.group("PROPERTY") != null) { + res.add(matcher.group("PROPERTY")); + } + return res; + } + + /** + * Create a new {@link Connection} from this {@link ConnectionOptions}. Calling this method + * multiple times for the same {@link ConnectionOptions} will return multiple instances of {@link + * Connection}s to the same database. + * + * @return a new {@link Connection} to the database referenced by this {@link ConnectionOptions} + */ + public Connection getConnection() { + return new ConnectionImpl(this); + } + + /** The URI of this {@link ConnectionOptions} */ + public String getUri() { + return uri; + } + + /** The credentials URL of this {@link ConnectionOptions} */ + public String getCredentialsUrl() { + return credentialsUrl; + } + + /** The number of channels to use for the connection. */ + public Integer getNumChannels() { + return numChannels; + } + + /** The host and port number that this {@link ConnectionOptions} will connect to */ + public String getHost() { + return host; + } + + /** The Google Project ID that this {@link ConnectionOptions} will connect to */ + public String getProjectId() { + return projectId; + } + + /** The Spanner Instance ID that this {@link ConnectionOptions} will connect to */ + public String getInstanceId() { + return instanceId; + } + + /** The Spanner database name that this {@link ConnectionOptions} will connect to */ + public String getDatabaseName() { + return databaseName; + } + + /** The Spanner {@link DatabaseId} that this {@link ConnectionOptions} will connect to */ + public DatabaseId getDatabaseId() { + Preconditions.checkState(projectId != null, "Project ID is not specified"); + Preconditions.checkState(instanceId != null, "Instance ID is not specified"); + Preconditions.checkState(databaseName != null, "Database name is not specified"); + return DatabaseId.of(projectId, instanceId, databaseName); + } + + /** + * The {@link Credentials} of this {@link ConnectionOptions}. This is either the credentials + * specified in the credentialsUrl or the default Google application credentials + */ + public Credentials getCredentials() { + return credentials; + } + + /** The initial autocommit value for connections created by this {@link ConnectionOptions} */ + public boolean isAutocommit() { + return autocommit; + } + + /** The initial readonly value for connections created by this {@link ConnectionOptions} */ + public boolean isReadOnly() { + return readOnly; + } + + /** + * The initial retryAbortsInternally value for connections created by this {@link + * ConnectionOptions} + */ + public boolean isRetryAbortsInternally() { + return retryAbortsInternally; + } + + /** Use http instead of https. Only valid for (local) test servers. */ + boolean isUsePlainText() { + return usePlainText; + } + + /** + * The (custom) user agent string to use for this connection. If null, then the + * default JDBC user agent string will be used. + */ + String getUserAgent() { + return userAgent; + } + + /** Interceptors that should be executed after each statement */ + List getStatementExecutionInterceptors() { + return statementExecutionInterceptors; + } + + @Override + public String toString() { + return getUri(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java new file mode 100644 index 000000000000..02f3953352e2 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import javax.annotation.Nullable; + +/** + * Static convenience methods that help a method or constructor in the Connection API to check + * whether it was invoked correctly. + */ +class ConnectionPreconditions { + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)}. + * @throws SpannerException with {@link ErrorCode#FAILED_PRECONDITION} if {@code expression} is + * false. + */ + static void checkState(boolean expression, @Nullable Object errorMessage) { + if (!expression) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, String.valueOf(errorMessage)); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java new file mode 100644 index 000000000000..4e79f25455a6 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019 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.TimestampBound; +import com.google.protobuf.Duration; + +/** + * The Cloud Spanner JDBC driver supports a number of client side statements that are interpreted by + * the driver and that can modify the current state of a connection, or report the current state of + * a connection. Each of the methods in this interface correspond with one such client side + * statement. + * + *

The methods in this interface are called by the different {@link ClientSideStatement}s. These + * method calls are then forwarded into the appropriate method of a {@link Connection} instance. + * + *

The client side statements are defined in the ClientSideStatements.json file. + */ +interface ConnectionStatementExecutor { + + StatementResult statementSetAutocommit(Boolean autocommit); + + StatementResult statementShowAutocommit(); + + StatementResult statementSetReadOnly(Boolean readOnly); + + StatementResult statementShowReadOnly(); + + StatementResult statementSetRetryAbortsInternally(Boolean retryAbortsInternally); + + StatementResult statementShowRetryAbortsInternally(); + + StatementResult statementSetAutocommitDmlMode(AutocommitDmlMode mode); + + StatementResult statementShowAutocommitDmlMode(); + + StatementResult statementSetStatementTimeout(Duration duration); + + StatementResult statementShowStatementTimeout(); + + StatementResult statementShowReadTimestamp(); + + StatementResult statementShowCommitTimestamp(); + + StatementResult statementSetReadOnlyStaleness(TimestampBound staleness); + + StatementResult statementShowReadOnlyStaleness(); + + StatementResult statementBeginTransaction(); + + StatementResult statementCommit(); + + StatementResult statementRollback(); + + StatementResult statementSetTransactionMode(TransactionMode mode); + + StatementResult statementStartBatchDdl(); + + StatementResult statementStartBatchDml(); + + StatementResult statementRunBatch(); + + StatementResult statementAbortBatch(); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java new file mode 100644 index 000000000000..7f7a5cf3ae74 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java @@ -0,0 +1,233 @@ +/* + * Copyright 2019 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 com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.ABORT_BATCH; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.BEGIN; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.COMMIT; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.ROLLBACK; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.RUN_BATCH; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READONLY; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READ_ONLY_STALENESS; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_RETRY_ABORTS_INTERNALLY; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_STATEMENT_TIMEOUT; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_TRANSACTION_MODE; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT_DML_MODE; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_COMMIT_TIMESTAMP; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READONLY; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_ONLY_STALENESS; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_TIMESTAMP; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_STATEMENT_TIMEOUT; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.START_BATCH_DDL; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.START_BATCH_DML; +import static com.google.cloud.spanner.jdbc.StatementResultImpl.noResult; +import static com.google.cloud.spanner.jdbc.StatementResultImpl.resultSet; + +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.DurationValueGetter; +import com.google.common.base.Preconditions; +import com.google.protobuf.Duration; +import java.util.concurrent.TimeUnit; + +/** + * The methods in this class are called by the different {@link ClientSideStatement}s. These method + * calls are then forwarded into a {@link Connection}. + */ +class ConnectionStatementExecutorImpl implements ConnectionStatementExecutor { + static final class StatementTimeoutGetter implements DurationValueGetter { + private final Connection connection; + + public StatementTimeoutGetter(Connection connection) { + this.connection = connection; + } + + @Override + public long getDuration(TimeUnit unit) { + return connection.getStatementTimeout(unit); + } + + @Override + public boolean hasDuration() { + return connection.hasStatementTimeout(); + } + } + + /** The connection to execute the statements on. */ + private final ConnectionImpl connection; + + ConnectionStatementExecutorImpl(ConnectionImpl connection) { + this.connection = connection; + } + + ConnectionImpl getConnection() { + return connection; + } + + @Override + public StatementResult statementSetAutocommit(Boolean autocommit) { + Preconditions.checkNotNull(autocommit); + getConnection().setAutocommit(autocommit); + return noResult(SET_AUTOCOMMIT); + } + + @Override + public StatementResult statementShowAutocommit() { + return resultSet("AUTOCOMMIT", getConnection().isAutocommit(), SHOW_AUTOCOMMIT); + } + + @Override + public StatementResult statementSetReadOnly(Boolean readOnly) { + Preconditions.checkNotNull(readOnly); + getConnection().setReadOnly(readOnly); + return noResult(SET_READONLY); + } + + @Override + public StatementResult statementShowReadOnly() { + return StatementResultImpl.resultSet("READONLY", getConnection().isReadOnly(), SHOW_READONLY); + } + + @Override + public StatementResult statementSetRetryAbortsInternally(Boolean retryAbortsInternally) { + Preconditions.checkNotNull(retryAbortsInternally); + getConnection().setRetryAbortsInternally(retryAbortsInternally); + return noResult(SET_RETRY_ABORTS_INTERNALLY); + } + + @Override + public StatementResult statementShowRetryAbortsInternally() { + return StatementResultImpl.resultSet( + "RETRY_ABORTS_INTERNALLY", + getConnection().isRetryAbortsInternally(), + SHOW_RETRY_ABORTS_INTERNALLY); + } + + @Override + public StatementResult statementSetAutocommitDmlMode(AutocommitDmlMode mode) { + getConnection().setAutocommitDmlMode(mode); + return noResult(SET_AUTOCOMMIT_DML_MODE); + } + + @Override + public StatementResult statementShowAutocommitDmlMode() { + return resultSet( + "AUTOCOMMIT_DML_MODE", getConnection().getAutocommitDmlMode(), SHOW_AUTOCOMMIT_DML_MODE); + } + + @Override + public StatementResult statementSetStatementTimeout(Duration duration) { + if (duration.getSeconds() == 0L && duration.getNanos() == 0) { + getConnection().clearStatementTimeout(); + } else { + TimeUnit unit = + ReadOnlyStalenessUtil.getAppropriateTimeUnit( + new ReadOnlyStalenessUtil.DurationGetter(duration)); + getConnection() + .setStatementTimeout(ReadOnlyStalenessUtil.durationToUnits(duration, unit), unit); + } + return noResult(SET_STATEMENT_TIMEOUT); + } + + @Override + public StatementResult statementShowStatementTimeout() { + return resultSet( + "STATEMENT_TIMEOUT", + getConnection().hasStatementTimeout() + ? ReadOnlyStalenessUtil.durationToString(new StatementTimeoutGetter(getConnection())) + : null, + SHOW_STATEMENT_TIMEOUT); + } + + @Override + public StatementResult statementShowReadTimestamp() { + return resultSet( + "READ_TIMESTAMP", getConnection().getReadTimestampOrNull(), SHOW_READ_TIMESTAMP); + } + + @Override + public StatementResult statementShowCommitTimestamp() { + return resultSet( + "COMMIT_TIMESTAMP", getConnection().getCommitTimestampOrNull(), SHOW_COMMIT_TIMESTAMP); + } + + @Override + public StatementResult statementSetReadOnlyStaleness(TimestampBound staleness) { + getConnection().setReadOnlyStaleness(staleness); + return noResult(SET_READ_ONLY_STALENESS); + } + + @Override + public StatementResult statementShowReadOnlyStaleness() { + TimestampBound staleness = getConnection().getReadOnlyStaleness(); + return resultSet( + "READ_ONLY_STALENESS", + ReadOnlyStalenessUtil.timestampBoundToString(staleness), + SHOW_READ_ONLY_STALENESS); + } + + @Override + public StatementResult statementBeginTransaction() { + getConnection().beginTransaction(); + return noResult(BEGIN); + } + + @Override + public StatementResult statementCommit() { + getConnection().commit(); + return noResult(COMMIT); + } + + @Override + public StatementResult statementRollback() { + getConnection().rollback(); + return noResult(ROLLBACK); + } + + @Override + public StatementResult statementSetTransactionMode(TransactionMode mode) { + getConnection().setTransactionMode(mode); + return noResult(SET_TRANSACTION_MODE); + } + + @Override + public StatementResult statementStartBatchDdl() { + getConnection().startBatchDdl(); + return noResult(START_BATCH_DDL); + } + + @Override + public StatementResult statementStartBatchDml() { + getConnection().startBatchDml(); + return noResult(START_BATCH_DML); + } + + @Override + public StatementResult statementRunBatch() { + long[] updateCounts = getConnection().runBatch(); + return resultSet("UPDATE_COUNTS", updateCounts, RUN_BATCH); + } + + @Override + public StatementResult statementAbortBatch() { + getConnection().abortBatch(); + return noResult(ABORT_BATCH); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java new file mode 100644 index 000000000000..b2f38a0d47d5 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java @@ -0,0 +1,144 @@ +/* + * Copyright 2019 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.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.storage.Blob; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageOptions; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; + +/** Service class for getting credentials from key files stored locally or on cloud storage. */ +class CredentialsService { + private static final String GOOGLE_CLOUD_STORAGE_PREFIX = "gs://"; + private static final String INVALID_GCS_PREFIX_MSG = + String.format("Storage URL must start with %s", GOOGLE_CLOUD_STORAGE_PREFIX); + + static final CredentialsService INSTANCE = new CredentialsService(); + + CredentialsService() {} + + /** + * Create credentials from the given URL pointing to a credentials json file. This may be a local + * file or a file on Google Cloud Storage. Credentials on Google Cloud Storage can only be used if + * the application is running in an environment where application default credentials have been + * set. + * + * @param credentialsUrl The URL of the credentials file to read. If null, then this + * method will return the application default credentials of the environment. + * @return the {@link GoogleCredentials} object pointed to by the URL. + * @throws SpannerException If the URL does not point to a valid credentials file, or if the file + * cannot be accessed. + */ + GoogleCredentials createCredentials(String credentialsUrl) { + try { + if (credentialsUrl == null) { + return internalGetApplicationDefault(); + } else { + return getCredentialsFromUrl(credentialsUrl); + } + } catch (IOException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "Invalid credentials path specified", e); + } + } + + @VisibleForTesting + GoogleCredentials internalGetApplicationDefault() throws IOException { + return GoogleCredentials.getApplicationDefault(); + } + + private GoogleCredentials getCredentialsFromUrl(String credentialsUrl) throws IOException { + Preconditions.checkNotNull(credentialsUrl); + Preconditions.checkArgument( + credentialsUrl.length() > 0, "credentialsUrl may not be an empty string"); + if (credentialsUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX)) { + return getCredentialsFromCloudStorage(credentialsUrl); + } else { + return getCredentialsFromLocalFile(credentialsUrl); + } + } + + private GoogleCredentials getCredentialsFromLocalFile(String filePath) throws IOException { + File credentialsFile = new File(filePath); + if (!credentialsFile.isFile()) { + throw new IOException( + String.format("Error reading credential file %s: File does not exist", filePath)); + } + try (InputStream credentialsStream = new FileInputStream(credentialsFile)) { + return GoogleCredentials.fromStream(credentialsStream); + } + } + + private GoogleCredentials getCredentialsFromCloudStorage(String credentialsUrl) + throws IOException { + Preconditions.checkArgument(credentialsUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX)); + try { + Storage storage = internalCreateStorage(); + String bucketName = internalGetBucket(credentialsUrl); + String blobName = internalGetBlob(credentialsUrl); + Blob blob = storage.get(bucketName, blobName); + return GoogleCredentials.fromStream(internalCreateInputStream(blob)); + } catch (Exception e) { + throw new IOException( + String.format( + "Could not retrieve credentials from %s. " + + "Credentials on Google Cloud Storage can only be used when the application is running " + + "in an environment that already has default credentials to access Google Cloud Storage", + credentialsUrl), + e); + } + } + + @VisibleForTesting + Storage internalCreateStorage() { + return StorageOptions.newBuilder().build().getService(); + } + + @VisibleForTesting + InputStream internalCreateInputStream(Blob blob) { + return Channels.newInputStream(blob.reader()); + } + + @VisibleForTesting + String internalGetBucket(String storageUrl) { + Preconditions.checkArgument( + storageUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX), INVALID_GCS_PREFIX_MSG); + Preconditions.checkArgument( + storageUrl.substring(5).contains("/"), "Storage URL must contain a blob name"); + return storageUrl.substring(5, storageUrl.indexOf('/', 5)); + } + + @VisibleForTesting + String internalGetBlob(String storageUrl) { + Preconditions.checkArgument( + storageUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX), + String.format("Storage URL must start with %s", GOOGLE_CLOUD_STORAGE_PREFIX)); + Preconditions.checkArgument( + storageUrl.substring(5).contains("/"), "Storage URL must contain a blob name"); + return storageUrl.substring(storageUrl.indexOf('/', 5) + 1); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java new file mode 100644 index 000000000000..d69271ffc3f0 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java @@ -0,0 +1,266 @@ +/* + * Copyright 2019 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.api.gax.longrunning.OperationFuture; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; + +/** + * {@link UnitOfWork} that is used when a DDL batch is started. These batches only accept DDL + * statements. All DDL statements are buffered locally and sent to Spanner when runBatch() is + * called. Running a {@link DdlBatch} is not an atomic operation. If the execution fails, then some + * (possibly empty) prefix of the statements in the batch have been successfully applied to the + * database, and the others have not. Note that the statements that succeed may not all happen at + * the same time, but they will always happen in order. + */ +class DdlBatch extends AbstractBaseUnitOfWork { + private final DdlClient ddlClient; + private final List statements = new ArrayList<>(); + private UnitOfWorkState state = UnitOfWorkState.STARTED; + + static class Builder extends AbstractBaseUnitOfWork.Builder { + private DdlClient ddlClient; + + private Builder() {} + + Builder setDdlClient(DdlClient client) { + Preconditions.checkNotNull(client); + this.ddlClient = client; + return this; + } + + @Override + DdlBatch build() { + Preconditions.checkState(ddlClient != null, "No DdlClient specified"); + return new DdlBatch(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private DdlBatch(Builder builder) { + super(builder); + this.ddlClient = builder.ddlClient; + } + + @Override + public Type getType() { + return Type.BATCH; + } + + @Override + public UnitOfWorkState getState() { + return this.state; + } + + @Override + public boolean isActive() { + return getState().isActive(); + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + public ResultSet executeQuery( + ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing queries is not allowed for DDL batches."); + } + + @Override + public Timestamp getReadTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "There is no read timestamp available for DDL batches."); + } + + @Override + public Timestamp getReadTimestampOrNull() { + return null; + } + + @Override + public Timestamp getCommitTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "There is no commit timestamp available for DDL batches."); + } + + @Override + public Timestamp getCommitTimestampOrNull() { + return null; + } + + @Override + public void executeDdl(ParsedStatement ddl) { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, + "The batch is no longer active and cannot be used for further statements"); + Preconditions.checkArgument( + ddl.getType() == StatementType.DDL, + "Only DDL statements are allowed. \"" + + ddl.getSqlWithoutComments() + + "\" is not a DDL-statement."); + statements.add(ddl.getSqlWithoutComments()); + } + + @Override + public long executeUpdate(ParsedStatement update) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing updates is not allowed for DDL batches."); + } + + @Override + public long[] executeBatchUpdate(Iterable updates) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing batch updates is not allowed for DDL batches."); + } + + @Override + public void write(Mutation mutation) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DDL batches."); + } + + @Override + public void write(Iterable mutations) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DDL batches."); + } + + /** + * Create a {@link ParsedStatement} that we can use as input for the generic execute method when + * the {@link #runBatch()} method is executed. This method uses the generic execute method that + * allows statements to be cancelled and to timeout, which requires the input to be a {@link + * ParsedStatement}. + */ + private static final ParsedStatement RUN_BATCH = + StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); + + @Override + public long[] runBatch() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be ran"); + try { + if (!statements.isEmpty()) { + // create a statement that can be passed in to the execute method + Callable callable = + new Callable() { + @Override + public UpdateDatabaseDdlMetadata call() throws Exception { + OperationFuture operation = + ddlClient.executeDdl(statements); + try { + // Wait until the operation has finished. + operation.get(); + // Return metadata. + return operation.getMetadata().get(); + } catch (ExecutionException e) { + SpannerException spannerException = extractSpannerCause(e); + long[] updateCounts = extractUpdateCounts(operation.getMetadata().get()); + throw SpannerExceptionFactory.newSpannerBatchUpdateException( + spannerException == null + ? ErrorCode.UNKNOWN + : spannerException.getErrorCode(), + e.getMessage(), + updateCounts); + } catch (InterruptedException e) { + long[] updateCounts = extractUpdateCounts(operation.getMetadata().get()); + throw SpannerExceptionFactory.newSpannerBatchUpdateException( + ErrorCode.CANCELLED, e.getMessage(), updateCounts); + } + } + }; + asyncExecuteStatement(RUN_BATCH, callable); + } + this.state = UnitOfWorkState.RAN; + long[] updateCounts = new long[statements.size()]; + Arrays.fill(updateCounts, 1L); + return updateCounts; + } catch (SpannerException e) { + this.state = UnitOfWorkState.RUN_FAILED; + throw e; + } + } + + private SpannerException extractSpannerCause(ExecutionException e) { + Throwable cause = e.getCause(); + Set causes = new HashSet<>(); + while (cause != null && !causes.contains(cause)) { + if (cause instanceof SpannerException) { + return (SpannerException) cause; + } + causes.add(cause); + cause = cause.getCause(); + } + return null; + } + + @VisibleForTesting + long[] extractUpdateCounts(UpdateDatabaseDdlMetadata metadata) { + long[] updateCounts = new long[metadata.getStatementsCount()]; + for (int i = 0; i < updateCounts.length; i++) { + if (metadata.getCommitTimestampsCount() > i && metadata.getCommitTimestamps(i) != null) { + updateCounts[i] = 1L; + } else { + updateCounts[i] = 0L; + } + } + return updateCounts; + } + + @Override + public void abortBatch() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be aborted."); + this.state = UnitOfWorkState.ABORTED; + } + + @Override + public void commit() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Commit is not allowed for DDL batches."); + } + + @Override + public void rollback() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Rollback is not allowed for DDL batches."); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java new file mode 100644 index 000000000000..5f921d7b43f7 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.List; + +/** + * Convenience class for executing Data Definition Language statements on transactions that support + * DDL statements, i.e. DdlBatchTransaction and SingleUseTransaction. + */ +class DdlClient { + private final DatabaseAdminClient dbAdminClient; + private final String instanceId; + private final String databaseName; + + static class Builder { + private DatabaseAdminClient dbAdminClient; + private String instanceId; + private String databaseName; + + private Builder() {} + + Builder setDatabaseAdminClient(DatabaseAdminClient client) { + Preconditions.checkNotNull(client); + this.dbAdminClient = client; + return this; + } + + Builder setInstanceId(String instanceId) { + Preconditions.checkArgument( + !Strings.isNullOrEmpty(instanceId), "Empty instanceId is not allowed"); + this.instanceId = instanceId; + return this; + } + + Builder setDatabaseName(String name) { + Preconditions.checkArgument( + !Strings.isNullOrEmpty(name), "Empty database name is not allowed"); + this.databaseName = name; + return this; + } + + DdlClient build() { + Preconditions.checkState(dbAdminClient != null, "No DatabaseAdminClient specified"); + Preconditions.checkState(!Strings.isNullOrEmpty(instanceId), "No InstanceId specified"); + Preconditions.checkArgument( + !Strings.isNullOrEmpty(databaseName), "No database name specified"); + return new DdlClient(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private DdlClient(Builder builder) { + this.dbAdminClient = builder.dbAdminClient; + this.instanceId = builder.instanceId; + this.databaseName = builder.databaseName; + } + + /** Execute a single DDL statement. */ + OperationFuture executeDdl(String ddl) { + return executeDdl(Arrays.asList(ddl)); + } + + /** Execute a list of DDL statements as one operation. */ + OperationFuture executeDdl(List statements) { + return dbAdminClient.updateDatabaseDdl(instanceId, databaseName, statements, null); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java new file mode 100644 index 000000000000..90ca044166e8 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java @@ -0,0 +1,365 @@ +/* + * Copyright 2019 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.ByteArray; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.common.base.Preconditions; +import com.google.spanner.v1.ResultSetStats; +import java.util.List; + +/** + * {@link ResultSet} implementation used by the Spanner connection API to ensure that the query for + * a {@link ResultSet} is executed directly when it is created. This is done by calling {@link + * ResultSet#next()} directly after creation. This ensures that a statement timeout can be applied + * to the actual query execution. It also ensures that any invalid query will throw an exception at + * execution instead of the first next() call by a client. + */ +class DirectExecuteResultSet implements ResultSet { + private static final String MISSING_NEXT_CALL = "Must be preceded by a next() call"; + private final ResultSet delegate; + private boolean nextCalledByClient = false; + private final boolean initialNextResult; + private boolean nextHasReturnedFalse = false; + + /** + * Creates a new {@link DirectExecuteResultSet} from the given delegate {@link ResultSet}. This + * automatically executes the query of the given delegate {@link ResultSet} by calling next() on + * the delegate. The delegate must not have been used (i.e. next() must not have been called on + * it). + * + * @param delegate The underlying {@link ResultSet} for this {@link DirectExecuteResultSet}. + * @return a {@link DirectExecuteResultSet} that has already executed the query associated with + * the delegate {@link ResultSet}. + */ + static DirectExecuteResultSet ofResultSet(ResultSet delegate) { + return new DirectExecuteResultSet(delegate); + } + + DirectExecuteResultSet(ResultSet delegate) { + Preconditions.checkNotNull(delegate); + this.delegate = delegate; + initialNextResult = delegate.next(); + } + + @Override + public boolean next() throws SpannerException { + if (nextCalledByClient) { + boolean res = delegate.next(); + nextHasReturnedFalse = !res; + return res; + } + nextCalledByClient = true; + nextHasReturnedFalse = !initialNextResult; + return initialNextResult; + } + + @Override + public Struct getCurrentRowAsStruct() { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getCurrentRowAsStruct(); + } + + @Override + public void close() { + delegate.close(); + } + + @Override + public ResultSetStats getStats() { + if (nextHasReturnedFalse) { + return delegate.getStats(); + } + return null; + } + + @Override + public Type getType() { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getType(); + } + + @Override + public int getColumnCount() { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getColumnCount(); + } + + @Override + public int getColumnIndex(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getColumnIndex(columnName); + } + + @Override + public Type getColumnType(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getColumnType(columnIndex); + } + + @Override + public Type getColumnType(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getColumnType(columnName); + } + + @Override + public boolean isNull(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.isNull(columnIndex); + } + + @Override + public boolean isNull(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.isNull(columnName); + } + + @Override + public boolean getBoolean(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBoolean(columnIndex); + } + + @Override + public boolean getBoolean(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBoolean(columnName); + } + + @Override + public long getLong(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLong(columnIndex); + } + + @Override + public long getLong(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLong(columnName); + } + + @Override + public double getDouble(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDouble(columnIndex); + } + + @Override + public double getDouble(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDouble(columnName); + } + + @Override + public String getString(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getString(columnIndex); + } + + @Override + public String getString(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getString(columnName); + } + + @Override + public ByteArray getBytes(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBytes(columnIndex); + } + + @Override + public ByteArray getBytes(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBytes(columnName); + } + + @Override + public Timestamp getTimestamp(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getTimestamp(columnIndex); + } + + @Override + public Timestamp getTimestamp(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getTimestamp(columnName); + } + + @Override + public Date getDate(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDate(columnIndex); + } + + @Override + public Date getDate(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDate(columnName); + } + + @Override + public boolean[] getBooleanArray(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBooleanArray(columnIndex); + } + + @Override + public boolean[] getBooleanArray(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBooleanArray(columnName); + } + + @Override + public List getBooleanList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBooleanList(columnIndex); + } + + @Override + public List getBooleanList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBooleanList(columnName); + } + + @Override + public long[] getLongArray(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLongArray(columnIndex); + } + + @Override + public long[] getLongArray(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLongArray(columnName); + } + + @Override + public List getLongList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLongList(columnIndex); + } + + @Override + public List getLongList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getLongList(columnName); + } + + @Override + public double[] getDoubleArray(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDoubleArray(columnIndex); + } + + @Override + public double[] getDoubleArray(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDoubleArray(columnName); + } + + @Override + public List getDoubleList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDoubleList(columnIndex); + } + + @Override + public List getDoubleList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDoubleList(columnName); + } + + @Override + public List getStringList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getStringList(columnIndex); + } + + @Override + public List getStringList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getStringList(columnName); + } + + @Override + public List getBytesList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBytesList(columnIndex); + } + + @Override + public List getBytesList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getBytesList(columnName); + } + + @Override + public List getTimestampList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getTimestampList(columnIndex); + } + + @Override + public List getTimestampList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getTimestampList(columnName); + } + + @Override + public List getDateList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDateList(columnIndex); + } + + @Override + public List getDateList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getDateList(columnName); + } + + @Override + public List getStructList(int columnIndex) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getStructList(columnIndex); + } + + @Override + public List getStructList(String columnName) { + Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); + return delegate.getStructList(columnName); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof DirectExecuteResultSet)) { + return false; + } + return ((DirectExecuteResultSet) o).delegate.equals(delegate); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java new file mode 100644 index 000000000000..55da9fb1bc67 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java @@ -0,0 +1,193 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.List; + +/** + * {@link UnitOfWork} that is used when a DML batch is started. These batches only accept DML + * statements. All DML statements are buffered locally and sent to Spanner when runBatch() is + * called. + */ +class DmlBatch extends AbstractBaseUnitOfWork { + private final UnitOfWork transaction; + private final List statements = new ArrayList<>(); + private UnitOfWorkState state = UnitOfWorkState.STARTED; + + static class Builder extends AbstractBaseUnitOfWork.Builder { + private UnitOfWork transaction; + + private Builder() {} + + Builder setTransaction(UnitOfWork transaction) { + Preconditions.checkNotNull(transaction); + this.transaction = transaction; + return this; + } + + @Override + DmlBatch build() { + Preconditions.checkState(transaction != null, "No transaction specified"); + return new DmlBatch(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private DmlBatch(Builder builder) { + super(builder); + this.transaction = builder.transaction; + } + + @Override + public Type getType() { + return Type.BATCH; + } + + @Override + public UnitOfWorkState getState() { + return this.state; + } + + @Override + public boolean isActive() { + return getState().isActive(); + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + public ResultSet executeQuery( + ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing queries is not allowed for DML batches."); + } + + @Override + public Timestamp getReadTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "There is no read timestamp available for DML batches."); + } + + @Override + public Timestamp getReadTimestampOrNull() { + return null; + } + + @Override + public Timestamp getCommitTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "There is no commit timestamp available for DML batches."); + } + + @Override + public Timestamp getCommitTimestampOrNull() { + return null; + } + + @Override + public void executeDdl(ParsedStatement ddl) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing DDL statements is not allowed for DML batches."); + } + + @Override + public long executeUpdate(ParsedStatement update) { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, + "The batch is no longer active and cannot be used for further statements"); + Preconditions.checkArgument( + update.getType() == StatementType.UPDATE, + "Only DML statements are allowed. \"" + + update.getSqlWithoutComments() + + "\" is not a DML-statement."); + statements.add(update); + return -1L; + } + + @Override + public long[] executeBatchUpdate(Iterable updates) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Executing batch updates is not allowed for DML batches."); + } + + @Override + public void write(Mutation mutation) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DML batches."); + } + + @Override + public void write(Iterable mutations) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DML batches."); + } + + @Override + public long[] runBatch() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be ran"); + try { + long[] res; + if (statements.isEmpty()) { + res = new long[0]; + } else { + res = transaction.executeBatchUpdate(statements); + } + this.state = UnitOfWorkState.RAN; + return res; + } catch (SpannerException e) { + this.state = UnitOfWorkState.RUN_FAILED; + throw e; + } + } + + @Override + public void abortBatch() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be aborted."); + this.state = UnitOfWorkState.ABORTED; + } + + @Override + public void commit() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Commit is not allowed for DML batches."); + } + + @Override + public void rollback() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Rollback is not allowed for DML batches."); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java new file mode 100644 index 000000000000..d96d98a829a4 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.common.base.Preconditions; +import java.util.Arrays; +import java.util.Objects; + +/** + * A batch update that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The + * batch update can be retried if the transaction is aborted, and should throw the same exception + * during retry as during the original transaction. + */ +final class FailedBatchUpdate implements RetriableStatement { + private final ReadWriteTransaction transaction; + private final SpannerException exception; + private final Iterable statements; + + FailedBatchUpdate( + ReadWriteTransaction transaction, + SpannerException exception, + Iterable statements) { + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(exception); + Preconditions.checkNotNull(statements); + this.transaction = transaction; + this.exception = exception; + this.statements = statements; + } + + @Override + public void retry(AbortedException aborted) throws AbortedException { + transaction + .getStatementExecutor() + .invokeInterceptors( + ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, + StatementExecutionStep.RETRY_STATEMENT, + transaction); + try { + transaction.getReadContext().batchUpdate(statements); + } catch (SpannerBatchUpdateException e) { + // Check that we got the same exception as in the original transaction. + if (exception instanceof SpannerBatchUpdateException + && e.getErrorCode() == exception.getErrorCode() + && Objects.equals(e.getMessage(), exception.getMessage())) { + // Check that the returned update counts are equal. + if (Arrays.equals( + e.getUpdateCounts(), ((SpannerBatchUpdateException) exception).getUpdateCounts())) { + return; + } + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } catch (SpannerException e) { + // Check that we got the same exception as in the original transaction. + if (e.getErrorCode() == exception.getErrorCode() + && Objects.equals(e.getMessage(), exception.getMessage())) { + return; + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java new file mode 100644 index 000000000000..4e2a3ecda871 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java @@ -0,0 +1,82 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; +import java.util.Objects; + +/** + * A query that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The query + * can be retried if the transaction is aborted, and should throw the same exception during retry as + * during the original transaction. + */ +final class FailedQuery implements RetriableStatement { + private final ReadWriteTransaction transaction; + private final SpannerException exception; + private final ParsedStatement statement; + private final AnalyzeMode analyzeMode; + private final QueryOption[] options; + + FailedQuery( + ReadWriteTransaction transaction, + SpannerException exception, + ParsedStatement statement, + AnalyzeMode analyzeMode, + QueryOption... options) { + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(exception); + Preconditions.checkNotNull(statement); + this.transaction = transaction; + this.exception = exception; + this.statement = statement; + this.analyzeMode = analyzeMode; + this.options = options; + } + + @Override + public void retry(AbortedException aborted) throws AbortedException { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + try { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + try (ResultSet rs = + DirectExecuteResultSet.ofResultSet( + transaction.internalExecuteQuery(statement, analyzeMode, options))) { + // Do nothing with the results, we are only interested in whether the statement throws the + // same exception as in the original transaction. + } + } catch (SpannerException e) { + // Check that we got the same exception as in the original transaction + if (e.getErrorCode() == exception.getErrorCode() + && Objects.equals(e.getMessage(), exception.getMessage())) { + return; + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java new file mode 100644 index 000000000000..1974f0ccdbbe --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; +import java.util.Objects; + +/** + * An update that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The + * update can be retried if the transaction is aborted, and should throw the same exception during + * retry as during the original transaction. + */ +final class FailedUpdate implements RetriableStatement { + private final ReadWriteTransaction transaction; + private final SpannerException exception; + private final ParsedStatement statement; + + FailedUpdate( + ReadWriteTransaction transaction, SpannerException exception, ParsedStatement statement) { + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(exception); + Preconditions.checkNotNull(statement); + this.transaction = transaction; + this.exception = exception; + this.statement = statement; + } + + @Override + public void retry(AbortedException aborted) throws AbortedException { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + try { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + transaction.getReadContext().executeUpdate(statement.getStatement()); + } catch (SpannerException e) { + // Check that we got the same exception as in the original transaction. + if (e.getErrorCode() == exception.getErrorCode() + && Objects.equals(e.getMessage(), exception.getMessage())) { + return; + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java new file mode 100644 index 000000000000..67d8e0c15724 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -0,0 +1,204 @@ +/* + * Copyright 2019 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.rpc.Code; +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** Implementation of java.sql.Array for Google Cloud Spanner */ +class JdbcArray implements Array { + private static final String FREE_EXCEPTION = + "free() has been called, array is no longer available"; + + private final JdbcDataType type; + private Object data; + private boolean freed = false; + + /** + * Create a JDBC {@link Array} from the given type name and array elements. + * + * @param typeName The Google Cloud Spanner type name to be used as the base type of the array. + * @param elements The elements to store in the array. + * @return the initialized {@link Array}. + * @throws SQLException if the type name is not a valid Cloud Spanner type or if the contents of + * the elements array is not compatible with the base type of the array. + */ + static JdbcArray createArray(String typeName, Object[] elements) throws SQLException { + for (JdbcDataType type : JdbcDataType.values()) { + if (type.getTypeName().equalsIgnoreCase(typeName)) { + return new JdbcArray(type, elements); + } + } + throw JdbcSqlExceptionFactory.of( + "Data type " + typeName + " is unknown", Code.INVALID_ARGUMENT); + } + + /** + * Create a JDBC {@link Array} from the given type name and list. + * + * @param typeName The Google Cloud Spanner type name to be used as the base type of the array. + * @param elements The elements to store in the array. + * @return the initialized {@link Array}. + * @throws SQLException if the type name is not a valid Cloud Spanner type or if the contents of + * the elements array is not compatible with the base type of the array. + */ + static JdbcArray createArray(JdbcDataType type, List elements) { + return new JdbcArray(type, elements); + } + + private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException { + this.type = type; + if (elements != null) { + this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length); + try { + System.arraycopy(elements, 0, this.data, 0, elements.length); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Could not copy array elements. Make sure the supplied array only contains elements of class " + + type.getJavaClass().getName(), + Code.UNKNOWN, + e); + } + } + } + + private JdbcArray(JdbcDataType type, List elements) { + this.type = type; + if (elements != null) { + this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.size()); + elements.toArray((Object[]) data); + } + } + + private void checkFree() throws SQLException { + if (freed) { + throw JdbcSqlExceptionFactory.of(FREE_EXCEPTION, Code.FAILED_PRECONDITION); + } + } + + @Override + public String getBaseTypeName() throws SQLException { + checkFree(); + return type.getTypeName(); + } + + @Override + public int getBaseType() throws SQLException { + checkFree(); + return type.getSqlType(); + } + + @Override + public Object getArray() throws SQLException { + checkFree(); + return data; + } + + @Override + public Object getArray(Map> map) throws SQLException { + checkFree(); + return data; + } + + @Override + public Object getArray(long index, int count) throws SQLException { + checkFree(); + return getArray(index, count, null); + } + + @Override + public Object getArray(long index, int count, Map> map) throws SQLException { + checkFree(); + if (data != null) { + Object res = java.lang.reflect.Array.newInstance(type.getJavaClass(), count); + System.arraycopy(data, (int) index - 1, res, 0, count); + return res; + } + return null; + } + + private static final String RESULTSET_NOT_SUPPORTED = + "Getting a ResultSet from an array is not supported"; + + @Override + public ResultSet getResultSet() throws SQLException { + throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + } + + @Override + public ResultSet getResultSet(Map> map) throws SQLException { + throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + } + + @Override + public ResultSet getResultSet(long index, int count) throws SQLException { + throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + } + + @Override + public ResultSet getResultSet(long index, int count, Map> map) + throws SQLException { + throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + } + + @Override + public void free() throws SQLException { + this.freed = true; + this.data = null; + } + + @Override + public String toString() { + if (data == null) { + return "null"; + } + boolean first = true; + StringBuilder builder = new StringBuilder("{"); + for (Object o : (Object[]) data) { + if (!first) { + builder.append(","); + } + first = false; + if (o == null) { + builder.append("null"); + } else { + builder.append(o.toString()); + } + } + builder.append("}"); + return builder.toString(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof JdbcArray)) return false; + JdbcArray array = (JdbcArray) other; + return this.type == array.type + && Arrays.deepEquals((Object[]) this.data, (Object[]) array.data); + } + + @Override + public int hashCode() { + return this.type.hashCode() ^ Arrays.deepHashCode((Object[]) data); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java new file mode 100644 index 000000000000..071e3258c020 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java @@ -0,0 +1,271 @@ +/* + * Copyright 2019 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.common.base.Preconditions; +import com.google.rpc.Code; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Simple {@link Blob} implementation for Google Cloud Spanner. The value is mapped to a byte array + * in memory. The {@link Blob} data type can be used in combination with the BYTES Cloud Spanner + * data type. + */ +class JdbcBlob implements Blob { + private byte[] value = new byte[0]; + + /** Creates an empty blob. */ + JdbcBlob() {} + + /** Creates a blob with the specified bytes as its value. */ + JdbcBlob(byte[] value) { + this.value = value; + } + + private void checkPosition(long pos) { + Preconditions.checkArgument( + pos + 1 <= Integer.MAX_VALUE, + "position larger than " + Integer.MAX_VALUE + " is not supported"); + } + + private void checkLength(long length) { + Preconditions.checkArgument( + length <= Integer.MAX_VALUE, + "length larger than " + Integer.MAX_VALUE + " is not supported"); + } + + private void checkPositionPlusLength(long pos, long length) { + Preconditions.checkArgument( + pos + 1 + length <= Integer.MAX_VALUE, + "position+length larger than " + Integer.MAX_VALUE + " is not supported"); + } + + @Override + public long length() throws SQLException { + return value.length; + } + + @Override + public byte[] getBytes(long pos, int length) throws SQLException { + JdbcPreconditions.checkArgument(pos > 0L, "pos must be >= 1"); + JdbcPreconditions.checkArgument(length >= 0, "length must be >= 0"); + checkPosition(pos); + checkPositionPlusLength(pos, length); + int end = (int) pos + length - 1; + int blobLength = (int) length(); + if (end > blobLength) { + length = blobLength - (int) pos + 1; + } + byte[] res = new byte[length]; + System.arraycopy(value, (int) pos - 1, res, 0, length); + return res; + } + + @Override + public InputStream getBinaryStream() throws SQLException { + return new ByteArrayInputStream(value); + } + + @Override + public long position(byte[] pattern, long start) throws SQLException { + JdbcPreconditions.checkArgument( + pattern != null && pattern.length > 0, "pattern must not be empty"); + JdbcPreconditions.checkArgument(start > 0L, "start must be >= 1"); + checkPosition(start); + for (int outerIndex = (int) start - 1; outerIndex < value.length; outerIndex++) { + int innerIndex = 0; + int valueIndex = outerIndex; + while (valueIndex < value.length + && innerIndex < pattern.length + && value[valueIndex] == pattern[innerIndex]) { + innerIndex++; + valueIndex++; + } + if (innerIndex == pattern.length) { + return outerIndex + 1; + } + } + return -1; + } + + @Override + public long position(Blob pattern, long start) throws SQLException { + JdbcPreconditions.checkArgument(pattern != null, "pattern must not be empty"); + JdbcPreconditions.checkArgument(start > 0L, "start must be >= 1"); + checkPosition(start); + byte[] buffer = new byte[1024]; + int totalSize = 0; + List totalBytes = new ArrayList<>(); + try (InputStream is = pattern.getBinaryStream()) { + int bytesRead = 0; + while ((bytesRead = is.read(buffer)) > -1) { + if (bytesRead == buffer.length) { + totalBytes.add(buffer); + } else { + byte[] dest = new byte[bytesRead]; + System.arraycopy(buffer, 0, dest, 0, bytesRead); + totalBytes.add(dest); + } + totalSize += bytesRead; + buffer = new byte[1024]; + } + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of("reading blob failed", Code.UNKNOWN, e); + } + byte[] bytePattern = new byte[totalSize]; + int index = 0; + for (byte[] b : totalBytes) { + System.arraycopy(b, 0, bytePattern, index, b.length); + index += b.length; + } + return position(bytePattern, start); + } + + private void setLength(int length) { + int prevLength = value.length; + byte[] newValue = new byte[length]; + System.arraycopy(value, 0, newValue, 0, Math.min(prevLength, newValue.length)); + value = newValue; + } + + @Override + public int setBytes(long pos, byte[] bytes) throws SQLException { + JdbcPreconditions.checkArgument(bytes != null, "bytes must be non-null"); + JdbcPreconditions.checkArgument(pos > 0L, "pos must be >= 1"); + checkPosition(pos); + int end = (int) pos + bytes.length - 1; + if (end >= value.length) { + setLength(end); + } + System.arraycopy(bytes, 0, value, (int) pos - 1, bytes.length); + return bytes.length; + } + + @Override + public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { + JdbcPreconditions.checkArgument(bytes != null, "bytes must be non-null"); + JdbcPreconditions.checkArgument(pos > 0L, "pos must be >= 1"); + JdbcPreconditions.checkArgument(offset >= 0, "offset must be >= 0"); + JdbcPreconditions.checkArgument(len >= 0, "len must be >= 0"); + checkPosition(pos); + if (offset > bytes.length) { + offset = 0; + len = 0; + } else { + if (offset + len > bytes.length) { + len = bytes.length - offset; + } + } + int end = (int) pos + len - 1; + if (end >= value.length) { + setLength(end); + } + System.arraycopy(bytes, offset, value, (int) pos - 1, len); + return len; + } + + private final class BlobOutputStream extends OutputStream { + private byte[] buffer = new byte[1024]; + private int currentPos = 0; + private int blobPosition; + + private BlobOutputStream(int pos) { + blobPosition = pos; + } + + @Override + public void write(int b) throws IOException { + if (currentPos >= buffer.length) { + byte[] newBuffer = new byte[buffer.length * 2]; + System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); + buffer = newBuffer; + } + buffer[currentPos] = (byte) b; + currentPos++; + } + + @Override + public void flush() throws IOException { + try { + setBytes(blobPosition, buffer, 0, currentPos); + blobPosition += currentPos; + currentPos = 0; + Arrays.fill(buffer, (byte) 0); + } catch (SQLException e) { + throw new IOException(e); + } + } + + @Override + public void close() throws IOException { + flush(); + } + } + + @Override + public OutputStream setBinaryStream(long pos) throws SQLException { + JdbcPreconditions.checkArgument(pos > 0L, "pos must be >= 1"); + checkPosition(pos); + return new BlobOutputStream((int) pos); + } + + @Override + public void truncate(long len) throws SQLException { + JdbcPreconditions.checkArgument(len >= 0, "len must be >= 0"); + checkLength(len); + setLength((int) len); + } + + @Override + public void free() throws SQLException { + setLength(0); + } + + @Override + public InputStream getBinaryStream(long pos, long length) throws SQLException { + JdbcPreconditions.checkArgument(pos > 0, "pos must be >= 1"); + JdbcPreconditions.checkArgument(length >= 0, "length must be >= 0"); + checkPosition(pos); + checkPositionPlusLength(pos, length); + if (pos + length > value.length) { + length = value.length - pos + 1; + } + byte[] buffer = new byte[(int) length]; + System.arraycopy(value, (int) pos - 1, buffer, 0, (int) length); + return new ByteArrayInputStream(buffer); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof JdbcBlob)) return false; + JdbcBlob blob = (JdbcBlob) other; + return Arrays.equals(this.value, blob.value); + } + + @Override + public int hashCode() { + return Arrays.hashCode(value); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java new file mode 100644 index 000000000000..40e26733a562 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java @@ -0,0 +1,219 @@ +/* + * Copyright 2019 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.common.base.Preconditions; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.sql.Clob; +import java.sql.NClob; +import java.sql.SQLException; + +/** + * Simple implementation of {@link Clob} and {@link NClob} for Google Cloud Spanner. The value is + * mapped to a {@link StringBuilder} in memory. {@link Clob} and {@link NClob} can be used with the + * STRING data type of Cloud Spanner. + */ +class JdbcClob implements NClob { + private StringBuilder value = new StringBuilder(); + + JdbcClob() {} + + JdbcClob(String value) { + this.value.append(value); + } + + private void checkPosition(long pos) { + Preconditions.checkArgument( + pos + 1 <= Integer.MAX_VALUE, + "position larger than " + Integer.MAX_VALUE + " is not supported"); + } + + private void checkLength(long length) { + Preconditions.checkArgument( + length <= Integer.MAX_VALUE, + "length larger than " + Integer.MAX_VALUE + " is not supported"); + } + + private void checkPositionPlusLength(long pos, long length) { + Preconditions.checkArgument( + pos + 1 + length <= Integer.MAX_VALUE, + "position+length larger than " + Integer.MAX_VALUE + " is not supported"); + } + + private StringBuilder repeat(char c, long length) { + checkLength(length); + StringBuilder res = new StringBuilder((int) length); + for (int i = 0; i < length; i++) { + res.append(c); + } + return res; + } + + @Override + public long length() throws SQLException { + return value.length(); + } + + @Override + public String getSubString(long pos, int length) throws SQLException { + JdbcPreconditions.checkArgument(pos >= 1, "Start position must be >= 1"); + JdbcPreconditions.checkArgument(length >= 0, "Length must be >= 0"); + checkPosition(pos); + checkPositionPlusLength(pos, length); + if (pos > length()) { + return ""; + } + int end = (int) pos + length - 1; + if (end >= value.length()) { + end = value.length(); + } + return value.substring((int) pos - 1, end); + } + + @Override + public Reader getCharacterStream() throws SQLException { + return new StringReader(value.toString()); + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return new ByteArrayInputStream(StandardCharsets.US_ASCII.encode(value.toString()).array()); + } + + @Override + public long position(String searchStr, long start) throws SQLException { + JdbcPreconditions.checkArgument(start >= 1, "Start position must be >= 1"); + JdbcPreconditions.checkArgument(searchStr != null, "searchStr may not be null"); + checkPosition(start); + int res = value.indexOf(searchStr, (int) start - 1); + if (res == -1) { + return res; + } + return res + 1; + } + + @Override + public long position(Clob searchStr, long start) throws SQLException { + JdbcPreconditions.checkArgument(start >= 1, "Start position must be >= 1"); + JdbcPreconditions.checkArgument(searchStr != null, "searchStr may not be null"); + checkPosition(start); + checkPositionPlusLength(start, searchStr.length()); + int res = value.indexOf(searchStr.getSubString(1L, (int) searchStr.length()), (int) start - 1); + if (res == -1) { + return res; + } + return res + 1; + } + + @Override + public int setString(long pos, String str) throws SQLException { + JdbcPreconditions.checkArgument(str != null, "str is null"); + JdbcPreconditions.checkArgument(pos >= 1, "Position must be >= 1"); + checkPosition(pos); + if ((pos - 1) > length()) { + value.append(repeat(' ', pos - length() - 1)); + } + value.replace((int) pos - 1, (int) pos + str.length() - 1, str); + return str.length(); + } + + @Override + public int setString(long pos, String str, int offset, int len) throws SQLException { + JdbcPreconditions.checkArgument(str != null, "str is null"); + JdbcPreconditions.checkArgument(pos >= 1, "Position must be >= 1"); + JdbcPreconditions.checkArgument(offset >= 1, "Offset must be >= 1"); + JdbcPreconditions.checkArgument( + offset + len - 1 <= str.length(), "offset + len is greater than str.length()"); + checkPosition(pos); + return setString(pos, str.substring(offset - 1, offset + len - 1)); + } + + private class ClobWriter extends StringWriter { + private final long startPos; + + private ClobWriter(long startPos) { + this.startPos = startPos; + } + + @Override + public void flush() { + try { + setString(startPos, getBuffer().toString()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public void close() { + flush(); + } + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + throw JdbcSqlExceptionFactory.unsupported( + "setAsciiStream is not supported. Use setCharacterStream instead"); + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + JdbcPreconditions.checkArgument(pos >= 1, "pos must be >= 1"); + return new ClobWriter(pos); + } + + @Override + public void truncate(long len) throws SQLException { + JdbcPreconditions.checkArgument(len >= 0, "len must be >= 0"); + checkLength(len); + value.setLength((int) len); + } + + @Override + public void free() throws SQLException { + value = new StringBuilder(); + } + + @Override + public Reader getCharacterStream(long pos, long length) throws SQLException { + JdbcPreconditions.checkArgument(pos >= 1, "pos must be >= 1"); + JdbcPreconditions.checkArgument(length >= 0, "length must be >= 0"); + checkPosition(pos); + checkPositionPlusLength(pos, length); + return new StringReader( + value.substring((int) pos - 1, (int) pos + (int) length - 1).toString()); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof JdbcClob)) return false; + JdbcClob blob = (JdbcClob) other; + return value.toString().equals(blob.value.toString()); + } + + @Override + public int hashCode() { + return value.toString().hashCode(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java new file mode 100644 index 000000000000..0114eb0a32da --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -0,0 +1,401 @@ +/* + * Copyright 2019 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.Mutation; +import com.google.cloud.spanner.SpannerException; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** Jdbc Connection class for Google Cloud Spanner */ +class JdbcConnection extends AbstractJdbcConnection { + private static final String ONLY_RS_FORWARD_ONLY = + "Only result sets of type TYPE_FORWARD_ONLY are supported"; + private static final String ONLY_CONCUR_READ_ONLY = + "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"; + private static final String ONLY_NO_GENERATED_KEYS = "Only NO_GENERATED_KEYS are supported"; + private Map> typeMap = new HashMap<>(); + + JdbcConnection(String connectionUrl, ConnectionOptions options) { + super(connectionUrl, options); + } + + @Override + public Statement createStatement() throws SQLException { + checkClosed(); + return new JdbcStatement(this); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + checkClosed(); + return new JdbcPreparedStatement(this, sql); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + checkClosed(); + return JdbcParameterStore.convertPositionalParametersToNamedParameters( + StatementParser.removeCommentsAndTrim(sql)) + .sqlWithNamedParameters; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + checkClosed(); + try { + // According to the JDBC spec's we need to commit the current transaction when changing + // autocommit mode. + if (getSpannerConnection().isAutocommit() != autoCommit + && getSpannerConnection().isTransactionStarted()) { + commit(); + } + getSpannerConnection().setAutocommit(autoCommit); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public boolean getAutoCommit() throws SQLException { + checkClosed(); + return getSpannerConnection().isAutocommit(); + } + + @Override + public void commit() throws SQLException { + checkClosed(); + try { + getSpannerConnection().commit(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void rollback() throws SQLException { + checkClosed(); + try { + getSpannerConnection().rollback(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void close() throws SQLException { + try { + getSpannerConnection().close(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public boolean isClosed() throws SQLException { + return getSpannerConnection().isClosed(); + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + checkClosed(); + return new JdbcDatabaseMetaData(this); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setReadOnly(readOnly); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public boolean isReadOnly() throws SQLException { + checkClosed(); + return getSpannerConnection().isReadOnly(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) + throws SQLException { + checkClosed(); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetType == ResultSet.TYPE_FORWARD_ONLY, ONLY_RS_FORWARD_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetConcurrency == ResultSet.CONCUR_READ_ONLY, ONLY_CONCUR_READ_ONLY); + return createStatement(); + } + + @Override + public Statement createStatement( + int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + checkClosed(); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetType == ResultSet.TYPE_FORWARD_ONLY, ONLY_RS_FORWARD_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetConcurrency == ResultSet.CONCUR_READ_ONLY, ONLY_CONCUR_READ_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetHoldability == ResultSet.CLOSE_CURSORS_AT_COMMIT, ONLY_CLOSE_CURSORS_AT_COMMIT); + return createStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + checkClosed(); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetType == ResultSet.TYPE_FORWARD_ONLY, ONLY_RS_FORWARD_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetConcurrency == ResultSet.CONCUR_READ_ONLY, ONLY_CONCUR_READ_ONLY); + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement( + String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + checkClosed(); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetType == ResultSet.TYPE_FORWARD_ONLY, ONLY_RS_FORWARD_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetConcurrency == ResultSet.CONCUR_READ_ONLY, ONLY_CONCUR_READ_ONLY); + JdbcPreconditions.checkSqlFeatureSupported( + resultSetHoldability == ResultSet.CLOSE_CURSORS_AT_COMMIT, ONLY_CLOSE_CURSORS_AT_COMMIT); + return prepareStatement(sql); + } + + @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); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + checkClosed(); + return prepareStatement(sql); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + checkClosed(); + return prepareStatement(sql); + } + + @Override + public Map> getTypeMap() throws SQLException { + checkClosed(); + return new HashMap<>(typeMap); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + checkClosed(); + this.typeMap = new HashMap<>(map); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + checkClosed(); + JdbcPreconditions.checkArgument(timeout >= 0, "timeout must be >= 0"); + try { + Statement statement = createStatement(); + statement.setQueryTimeout(timeout); + try (ResultSet rs = statement.executeQuery("select 1")) { + if (rs.next()) { + if (rs.getLong(1) == 1L) { + return true; + } + } + } + } catch (SQLException e) { + // ignore + } + return false; + } + + @Override + public Blob createBlob() throws SQLException { + checkClosed(); + return new JdbcBlob(); + } + + @Override + public Clob createClob() throws SQLException { + checkClosed(); + return new JdbcClob(); + } + + @Override + public NClob createNClob() throws SQLException { + checkClosed(); + return new JdbcClob(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + checkClosed(); + return JdbcArray.createArray(typeName, elements); + } + + @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 + // and applications that set this when no catalog has been specified in the connection + // URL. + checkClosed(); + JdbcPreconditions.checkArgument("".equals(catalog), "Only catalog \"\" is supported"); + } + + @Override + public String getCatalog() throws SQLException { + checkClosed(); + return getConnectionOptions().getDatabaseName(); + } + + @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"); + } + + @Override + public String getSchema() throws SQLException { + checkClosed(); + return ""; + } + + @Override + public Timestamp getCommitTimestamp() throws SQLException { + checkClosed(); + try { + return getSpannerConnection().getCommitTimestamp().toSqlTimestamp(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public Timestamp getReadTimestamp() throws SQLException { + checkClosed(); + try { + return getSpannerConnection().getReadTimestamp().toSqlTimestamp(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public boolean isRetryAbortsInternally() throws SQLException { + checkClosed(); + try { + return getSpannerConnection().isRetryAbortsInternally(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void setRetryAbortsInternally(boolean retryAbortsInternally) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setRetryAbortsInternally(retryAbortsInternally); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void write(Mutation mutation) throws SQLException { + checkClosed(); + try { + getSpannerConnection().write(mutation); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void write(Iterable mutations) throws SQLException { + checkClosed(); + try { + getSpannerConnection().write(mutations); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void bufferedWrite(Mutation mutation) throws SQLException { + checkClosed(); + try { + getSpannerConnection().bufferedWrite(mutation); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void bufferedWrite(Iterable mutations) throws SQLException { + checkClosed(); + try { + getSpannerConnection().bufferedWrite(mutations); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void addTransactionRetryListener(TransactionRetryListener listener) throws SQLException { + checkClosed(); + getSpannerConnection().addTransactionRetryListener(listener); + } + + @Override + public boolean removeTransactionRetryListener(TransactionRetryListener listener) + throws SQLException { + checkClosed(); + return getSpannerConnection().removeTransactionRetryListener(listener); + } + + @Override + public Iterator getTransactionRetryListeners() throws SQLException { + checkClosed(); + return getSpannerConnection().getTransactionRetryListeners(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java new file mode 100644 index 000000000000..a8cca8abc40b --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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.jdbc.StatementResult.ResultType; +import java.sql.ResultSet; +import java.sql.Statement; + +/** Constants for special values used by the Cloud Spanner JDBC driver. */ +public final class JdbcConstants { + /** + * Special value that is used to indicate that a statement returned a {@link ResultSet}. The + * method {@link Statement#getUpdateCount()} will return this value if the previous statement that + * was executed with {@link Statement#execute(String)} returned a {@link ResultSet}. + */ + public static final int STATEMENT_RESULT_SET = -1; + /** + * Special value that is used to indicate that a statement had no result. The method {@link + * Statement#getUpdateCount()} will return this value if the previous statement that was executed + * with {@link Statement#execute(String)} returned {@link ResultType#NO_RESULT}, such as DDL + * statements {@link ResultType}. + */ + public static final int STATEMENT_NO_RESULT = -2; + + /** No instantiation */ + private JdbcConstants() {} +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java new file mode 100644 index 000000000000..31a4ad44e750 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java @@ -0,0 +1,197 @@ +/* + * Copyright 2019 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.rpc.Code; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; +import java.util.logging.Logger; +import javax.sql.DataSource; + +/** {@link DataSource} implementation for Google Cloud Spanner. */ +public class JdbcDataSource extends AbstractJdbcWrapper implements DataSource { + private String url; + private String credentials; + private Boolean autocommit; + private Boolean readonly; + private Boolean retryAbortsInternally; + + /** Make sure the JDBC driver class is loaded. */ + static { + try { + Class.forName("com.google.cloud.spanner.jdbc.JdbcDriver"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException( + "JdbcDataSource failed to load com.google.cloud.spanner.jdbc.JdbcDriver", e); + } + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + return null; + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + // no-op + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + // no-op + } + + @Override + public int getLoginTimeout() throws SQLException { + return 0; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw JdbcSqlExceptionFactory.unsupported("java.util.logging is not used"); + } + + @Override + public Connection getConnection() throws SQLException { + if (getUrl() == null) { + throw JdbcSqlExceptionFactory.of( + "There is no URL specified for this data source", Code.FAILED_PRECONDITION); + } + if (!JdbcDriver.getRegisteredDriver().acceptsURL(getUrl())) { + throw JdbcSqlExceptionFactory.of( + "The URL " + getUrl() + " is not valid for the data source " + getClass().getName(), + Code.FAILED_PRECONDITION); + } + return DriverManager.getConnection(getUrl(), createProperties()); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + return getConnection(); + } + + private Properties createProperties() { + Properties props = new Properties(); + if (this.credentials != null) { + props.setProperty(ConnectionOptions.CREDENTIALS_PROPERTY_NAME, this.credentials); + } + if (this.autocommit != null) { + props.setProperty( + ConnectionOptions.AUTOCOMMIT_PROPERTY_NAME, String.valueOf(this.autocommit)); + } + if (this.readonly != null) { + props.setProperty(ConnectionOptions.READONLY_PROPERTY_NAME, String.valueOf(this.readonly)); + } + if (this.retryAbortsInternally != null) { + props.setProperty( + ConnectionOptions.RETRY_ABORTS_INTERNALLY_PROPERTY_NAME, + String.valueOf(this.retryAbortsInternally)); + } + return props; + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + /** @return the JDBC URL to use for this {@link DataSource}. */ + public String getUrl() { + return url; + } + + /** @param url The JDBC URL to use for this {@link DataSource}. */ + public void setUrl(String url) { + this.url = url; + } + + /** + * @return the credentials URL to use for this {@link DataSource}. If a credentials URL is + * specified in both the connection URL and using this property, the value in the connection + * URL will be used. + */ + public String getCredentials() { + return credentials; + } + + /** + * @param credentials The credentials URL to use for this {@link DataSource}. If a credentials URL + * is specified in both the connection URL and using this property, the value in the + * connection URL will be used. + */ + public void setCredentials(String credentials) { + this.credentials = credentials; + } + + /** + * @return the initial autocommit setting to use for this {@link DataSource}. If autocommit is + * specified in both the connection URL and using this property, the value in the connection + * URL will be used. + */ + public Boolean getAutocommit() { + return autocommit; + } + + /** + * @param autocommit The initial autocommit setting to use for this {@link DataSource}. If + * autocommit is specified in both the connection URL and using this property, the value in + * the connection URL will be used. + */ + public void setAutocommit(Boolean autocommit) { + this.autocommit = autocommit; + } + + /** + * @return the initial readonly setting to use for this {@link DataSource}. If readonly is + * specified in both the connection URL and using this property, the value in the connection + * URL will be used. + */ + public Boolean getReadonly() { + return readonly; + } + + /** + * @param readonly The initial readonly setting to use for this {@link DataSource}. If readonly is + * specified in both the connection URL and using this property, the value in the connection + * URL will be used. + */ + public void setReadonly(Boolean readonly) { + this.readonly = readonly; + } + + /** + * @return the initial retryAbortsInternally setting to use for this {@link DataSource}. If + * retryAbortsInternally is specified in both the connection URL and using this property, the + * value in the connection URL will be used. + */ + public Boolean getRetryAbortsInternally() { + return retryAbortsInternally; + } + + /** + * @param retryAbortsInternally The initial retryAbortsInternally setting to use for this {@link + * DataSource}. If retryAbortsInternally is specified in both the connection URL and using + * this property, the value in the connection URL will be used. + */ + public void setRetryAbortsInternally(Boolean retryAbortsInternally) { + this.retryAbortsInternally = retryAbortsInternally; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java new file mode 100644 index 000000000000..1c984c74d493 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -0,0 +1,267 @@ +/* + * Copyright 2019 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.ResultSet; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.Code; +import java.sql.Date; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** Enum for mapping Cloud Spanner data types to Java classes and JDBC SQL {@link Types}. */ +enum JdbcDataType { + BOOL { + @Override + public int getSqlType() { + return Types.BOOLEAN; + } + + @Override + public Class getJavaClass() { + return Boolean.class; + } + + @Override + public Code getCode() { + return Code.BOOL; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getBooleanList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.bool(); + } + }, + BYTES { + @Override + public int getSqlType() { + return Types.BINARY; + } + + @Override + public Class getJavaClass() { + return byte[].class; + } + + @Override + public Code getCode() { + return Code.BYTES; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return JdbcTypeConverter.toJavaByteArrays(rs.getBytesList(columnIndex)); + } + + @Override + public Type getSpannerType() { + return Type.bytes(); + } + }, + DATE { + @Override + public int getSqlType() { + return Types.DATE; + } + + @Override + public Class getJavaClass() { + return Date.class; + } + + @Override + public Code getCode() { + return Code.DATE; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return JdbcTypeConverter.toSqlDates(rs.getDateList(columnIndex)); + } + + @Override + public Type getSpannerType() { + return Type.date(); + } + }, + FLOAT64 { + private Set> classes = new HashSet>(Arrays.asList(Float.class, Double.class)); + + @Override + public int getSqlType() { + return Types.DOUBLE; + } + + @Override + public Class getJavaClass() { + return Double.class; + } + + @Override + public Set> getSupportedJavaClasses() { + return classes; + } + + @Override + public Code getCode() { + return Code.FLOAT64; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getDoubleList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.float64(); + } + }, + INT64 { + private Set> classes = + new HashSet>(Arrays.asList(Byte.class, Integer.class, Long.class)); + + @Override + public int getSqlType() { + return Types.BIGINT; + } + + @Override + public Class getJavaClass() { + return Long.class; + } + + @Override + public Set> getSupportedJavaClasses() { + return classes; + } + + @Override + public Code getCode() { + return Code.INT64; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getLongList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.int64(); + } + }, + STRING { + @Override + public int getSqlType() { + return Types.NVARCHAR; + } + + @Override + public Class getJavaClass() { + return String.class; + } + + @Override + public Code getCode() { + return Code.STRING; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getStringList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.string(); + } + }, + TIMESTAMP { + @Override + public int getSqlType() { + return Types.TIMESTAMP; + } + + @Override + public Class getJavaClass() { + return Timestamp.class; + } + + @Override + public Code getCode() { + return Code.TIMESTAMP; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return JdbcTypeConverter.toSqlTimestamps(rs.getTimestampList(columnIndex)); + } + + @Override + public Type getSpannerType() { + return Type.timestamp(); + } + }; + + public abstract int getSqlType(); + + public abstract Code getCode(); + + public abstract Type getSpannerType(); + + /** + * @param rs the result set to look up the elements + * @param columnIndex zero based column index + * @return The corresponding array elements of the type in the given result set + */ + public abstract List getArrayElements(ResultSet rs, int columnIndex); + + public String getTypeName() { + return name(); + } + + public abstract Class getJavaClass(); + + public Set> getSupportedJavaClasses() { + return Collections.singleton(getJavaClass()); + } + + public static JdbcDataType getType(Class clazz) { + for (JdbcDataType type : JdbcDataType.values()) { + if (type.getSupportedJavaClasses().contains(clazz)) return type; + } + return null; + } + + public static JdbcDataType getType(Code code) { + for (JdbcDataType type : JdbcDataType.values()) { + if (type.getCode() == code) return type; + } + return null; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java new file mode 100644 index 000000000000..828bb06bbbf2 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -0,0 +1,1538 @@ +/* + * Copyright 2019 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.auth.Credentials; +import com.google.auth.ServiceAccountSigner; +import com.google.auth.oauth2.UserCredentials; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Arrays; +import java.util.Collections; +import java.util.Scanner; + +/** {@link DatabaseMetaData} implementation for Cloud Spanner */ +class JdbcDatabaseMetaData extends AbstractJdbcWrapper implements DatabaseMetaData { + private static final int JDBC_MAJOR_VERSION = 4; + private static final int JDBC_MINOR_VERSION = 1; + private static final int DATABASE_MAJOR_VERSION = 1; + private static final int DATABASE_MINOR_VERSION = 0; + private static final String PRODUCT_NAME = "Google Cloud Spanner"; + + private String readSqlFromFile(String filename) { + InputStream in = getClass().getResourceAsStream(filename); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + StringBuilder builder = new StringBuilder(); + try (Scanner scanner = new Scanner(reader)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + builder.append(line).append("\n"); + } + scanner.close(); + } + return builder.toString(); + } + + private JdbcConnection connection; + + JdbcDatabaseMetaData(JdbcConnection connection) { + this.connection = connection; + } + + @Override + public boolean isClosed() { + return false; + } + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return true; + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return true; + } + + @Override + public String getURL() throws SQLException { + return connection.getConnectionUrl(); + } + + @Override + public String getUserName() throws SQLException { + Credentials credentials = connection.getConnectionOptions().getCredentials(); + if (credentials != null) { + if (credentials instanceof ServiceAccountSigner) { + return ((ServiceAccountSigner) credentials).getAccount(); + } else if (credentials instanceof UserCredentials) { + return ((UserCredentials) credentials).getClientId(); + } + } + return ""; + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return false; + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return true; + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return true; + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return false; + } + + @Override + public String getDatabaseProductName() throws SQLException { + return PRODUCT_NAME; + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return getDatabaseMajorVersion() + "." + getDatabaseMinorVersion(); + } + + @Override + public String getDriverName() throws SQLException { + return JdbcDriver.class.getName(); + } + + @Override + public String getDriverVersion() throws SQLException { + return getDriverMajorVersion() + "." + getDriverMinorVersion(); + } + + @Override + public int getDriverMajorVersion() { + return JdbcDriver.MAJOR_VERSION; + } + + @Override + public int getDriverMinorVersion() { + return JdbcDriver.MINOR_VERSION; + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return false; + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return false; + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return true; + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return false; + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return true; + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return "`"; + } + + @Override + public String getSQLKeywords() throws SQLException { + return "ASSERT_ROWS_MODIFIED,ENUM,GROUPS,HASH,IGNORE,LOOKUP,PROTO,RESPECT,STRUCT,WINDOW"; + } + + @Override + public String getNumericFunctions() throws SQLException { + return "ABS,SIGN,IS_INF,IS_NAN,IEEE_DIVIDE,SQRT,POW,POWER,EXP,LN,LOG,LOG10,GREATEST,LEAST,DIV,MOD,ROUND,TRUNC,CEIL,CEILING,FLOOR,COS,COSH,ACOS,ACOSH,SIN,SINH,ASIN,ASINH,TAN,TANH,ATAN,ATANH,ATAN2,FARM_FINGERPRINT,SHA1,SHA256,SHA512"; + } + + @Override + public String getStringFunctions() throws SQLException { + return "BYTE_LENGTH,CHAR_LENGTH,CHARACTER_LENGTH,CODE_POINTS_TO_BYTES,CODE_POINTS_TO_STRING,CONCAT,ENDS_WITH,FORMAT,FROM_BASE64,FROM_HEX,LENGTH,LPAD,LOWER,LTRIM,REGEXP_CONTAINS,REGEXP_EXTRACT,REGEXP_EXTRACT_ALL,REGEXP_REPLACE,REPLACE,REPEAT,REVERSE,RPAD,RTRIM,SAFE_CONVERT_BYTES_TO_STRING,SPLIT,STARTS_WITH,STRPOS,SUBSTR,TO_BASE64,TO_CODE_POINTS,TO_HEX,TRIM,UPPER,JSON_QUERY,JSON_VALUE"; + } + + @Override + public String getSystemFunctions() throws SQLException { + return ""; + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return "CURRENT_DATE,EXTRACT,DATE,DATE_ADD,DATE_SUB,DATE_DIFF,DATE_TRUNC,DATE_FROM_UNIX_DATE,FORMAT_DATE,PARSE_DATE,UNIX_DATE,CURRENT_TIMESTAMP,STRING,TIMESTAMP,TIMESTAMP_ADD,TIMESTAMP_SUB,TIMESTAMP_DIFF,TIMESTAMP_TRUNC,FORMAT_TIMESTAMP,PARSE_TIMESTAMP,TIMESTAMP_SECONDS,TIMESTAMP_MILLIS,TIMESTAMP_MICROS,UNIX_SECONDS,UNIX_MILLIS,UNIX_MICROS"; + } + + @Override + public String getSearchStringEscape() throws SQLException { + return "\\"; + } + + @Override + public String getExtraNameCharacters() throws SQLException { + return ""; + } + + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLException { + return true; + } + + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLException { + return true; + } + + @Override + public boolean supportsColumnAliasing() throws SQLException { + return true; + } + + @Override + public boolean nullPlusNonNullIsNull() throws SQLException { + return true; + } + + @Override + public boolean supportsConvert() throws SQLException { + return false; + } + + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLException { + return false; + } + + @Override + public boolean supportsTableCorrelationNames() throws SQLException { + return true; + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return false; + } + + @Override + public boolean supportsExpressionsInOrderBy() throws SQLException { + return true; + } + + @Override + public boolean supportsOrderByUnrelated() throws SQLException { + return true; + } + + @Override + public boolean supportsGroupBy() throws SQLException { + return true; + } + + @Override + public boolean supportsGroupByUnrelated() throws SQLException { + return true; + } + + @Override + public boolean supportsGroupByBeyondSelect() throws SQLException { + return true; + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return true; + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return true; + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return true; + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return true; + } + + @Override + public boolean supportsMinimumSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsCoreSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsExtendedSQLGrammar() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsANSI92FullSQL() throws SQLException { + return false; + } + + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLException { + return false; + } + + @Override + public boolean supportsOuterJoins() throws SQLException { + return true; + } + + @Override + public boolean supportsFullOuterJoins() throws SQLException { + return true; + } + + @Override + public boolean supportsLimitedOuterJoins() throws SQLException { + return true; + } + + @Override + public String getSchemaTerm() throws SQLException { + return "SCHEMA"; + } + + @Override + public String getProcedureTerm() throws SQLException { + return "PROCEDURE"; + } + + @Override + public String getCatalogTerm() throws SQLException { + // Spanner does not support catalogs, but the term is included for compatibility with the SQL + // standard + return "CATALOG"; + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return false; + } + + @Override + public String getCatalogSeparator() throws SQLException { + return "."; + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return false; + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return false; + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return false; + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return true; + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return true; + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return true; + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return true; + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return true; + } + + @Override + public boolean supportsUnion() throws SQLException { + return true; + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return true; + } + + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + return false; + } + + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + return true; + } + + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + return true; + } + + @Override + public int getMaxBinaryLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return 128; + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return 1000; + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return 16; + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return 1024; + } + + @Override + public int getMaxConnections() throws SQLException { + // there is a max number of sessions, but that is not the same as the max number of connections + return 0; + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxIndexLength() throws SQLException { + return 8000; + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return 0; + } + + @Override + public int getMaxRowSize() throws SQLException { + return 1024 * 10000000; + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return true; + } + + @Override + public int getMaxStatementLength() throws SQLException { + return 1000000; + } + + @Override + public int getMaxStatements() throws SQLException { + return 0; + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return 128; + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return 0; + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return 0; + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return Connection.TRANSACTION_SERIALIZABLE; + } + + @Override + public boolean supportsTransactions() throws SQLException { + return true; + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return Connection.TRANSACTION_SERIALIZABLE == level; + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return false; + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return true; + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return false; + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return false; + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("PROCEDURE_CAT", Type.string()), + StructField.of("PROCEDURE_SCHEM", Type.string()), + StructField.of("PROCEDURE_NAME", Type.string()), + StructField.of("reserved1", Type.string()), + StructField.of("reserved2", Type.string()), + StructField.of("reserved3", Type.string()), + StructField.of("REMARKS", Type.string()), + StructField.of("PROCEDURE_TYPE", Type.int64()), + StructField.of("SPECIFIC_NAME", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getProcedureColumns( + String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("PROCEDURE_CAT", Type.string()), + StructField.of("PROCEDURE_SCHEM", Type.string()), + StructField.of("PROCEDURE_NAME", Type.string()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("COLUMN_TYPE", Type.int64()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("PRECISION", Type.string()), + StructField.of("LENGTH", Type.int64()), + StructField.of("SCALE", Type.int64()), + StructField.of("RADIX", Type.int64()), + StructField.of("NULLABLE", Type.int64()), + StructField.of("REMARKS", Type.string()), + StructField.of("COLUMN_DEF", Type.string()), + StructField.of("SQL_DATA_TYPE", Type.int64()), + StructField.of("SQL_DATETIME_SUB", Type.int64()), + StructField.of("CHAR_OCTET_LENGTH", Type.int64()), + StructField.of("ORDINAL_POSITION", Type.int64()), + StructField.of("IS_NULLABLE", Type.string()), + StructField.of("SPECIFIC_NAME", Type.string())), + Collections.emptyList())); + } + + private PreparedStatement prepareStatementReplaceNullWithAnyString(String sql, String... params) + throws SQLException { + PreparedStatement statement = connection.prepareStatement(sql); + int paramIndex = 1; + for (String param : params) { + if (param == null) { + statement.setString(paramIndex, "%"); + } else { + statement.setString(paramIndex, param.toUpperCase()); + } + paramIndex++; + } + return statement; + } + + @Override + public ResultSet getTables( + String catalog, String schemaPattern, String tableNamePattern, String[] types) + throws SQLException { + String sql = readSqlFromFile("DatabaseMetaData_GetTables.sql"); + String type1; + String type2; + if (types == null || types.length == 0) { + type1 = "TABLE"; + type2 = "VIEW"; + } else if (types.length == 1) { + type1 = types[0]; + type2 = "NON_EXISTENT_TYPE"; + } else { + type1 = types[0]; + type2 = types[1]; + } + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString( + sql, catalog, schemaPattern, tableNamePattern, type1, type2); + return statement.executeQuery(); + } + + @Override + public ResultSet getSchemas() throws SQLException { + return getSchemas(null, null); + } + + @Override + public ResultSet getCatalogs() throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct(StructField.of("TABLE_CAT", Type.string())), + Arrays.asList(Struct.newBuilder().set("TABLE_CAT").to("").build()))); + } + + @Override + public ResultSet getTableTypes() throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct(StructField.of("TABLE_TYPE", Type.string())), + Arrays.asList( + Struct.newBuilder().set("TABLE_TYPE").to("TABLE").build(), + Struct.newBuilder().set("TABLE_TYPE").to("VIEW").build()))); + } + + @Override + public ResultSet getColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + String sql = readSqlFromFile("DatabaseMetaData_GetColumns.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString( + sql, catalog, schemaPattern, tableNamePattern, columnNamePattern); + return statement.executeQuery(); + } + + @Override + public ResultSet getColumnPrivileges( + String catalog, String schema, String table, String columnNamePattern) throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TABLE_CAT", Type.string()), + StructField.of("TABLE_SCHEM", Type.string()), + StructField.of("TABLE_NAME", Type.string()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("GRANTOR", Type.string()), + StructField.of("GRANTEE", Type.string()), + StructField.of("PRIVILEGE", Type.string()), + StructField.of("IS_GRANTABLE", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TABLE_CAT", Type.string()), + StructField.of("TABLE_SCHEM", Type.string()), + StructField.of("TABLE_NAME", Type.string()), + StructField.of("GRANTOR", Type.string()), + StructField.of("GRANTEE", Type.string()), + StructField.of("PRIVILEGE", Type.string()), + StructField.of("IS_GRANTABLE", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getBestRowIdentifier( + String catalog, String schema, String table, int scope, boolean nullable) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("SCOPE", Type.int64()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("COLUMN_SIZE", Type.int64()), + StructField.of("BUFFER_LENGTH", Type.int64()), + StructField.of("DECIMAL_DIGITS", Type.int64()), + StructField.of("PSEUDO_COLUMN", Type.int64())), + Collections.emptyList())); + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("SCOPE", Type.int64()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("COLUMN_SIZE", Type.int64()), + StructField.of("BUFFER_LENGTH", Type.int64()), + StructField.of("DECIMAL_DIGITS", Type.int64()), + StructField.of("PSEUDO_COLUMN", Type.int64())), + Collections.emptyList())); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + JdbcPreconditions.checkArgument(table != null, "table may not be null"); + String sql = readSqlFromFile("DatabaseMetaData_GetPrimaryKeys.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); + return statement.executeQuery(); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) + throws SQLException { + JdbcPreconditions.checkArgument(table != null, "table may not be null"); + String sql = readSqlFromFile("DatabaseMetaData_GetImportedKeys.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); + return statement.executeQuery(); + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) + throws SQLException { + JdbcPreconditions.checkArgument(table != null, "table may not be null"); + String sql = readSqlFromFile("DatabaseMetaData_GetExportedKeys.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); + return statement.executeQuery(); + } + + @Override + public ResultSet getCrossReference( + String parentCatalog, + String parentSchema, + String parentTable, + String foreignCatalog, + String foreignSchema, + String foreignTable) + throws SQLException { + String sql = readSqlFromFile("DatabaseMetaData_GetCrossReferences.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString( + sql, + parentCatalog, + parentSchema, + parentTable, + foreignCatalog, + foreignSchema, + foreignTable); + return statement.executeQuery(); + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TYPE_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("PRECISION", Type.int64()), + StructField.of("LITERAL_PREFIX", Type.string()), + StructField.of("LITERAL_SUFFIX", Type.string()), + StructField.of("CREATE_PARAMS", Type.string()), + StructField.of("NULLABLE", Type.int64()), + StructField.of("CASE_SENSITIVE", Type.bool()), + StructField.of("SEARCHABLE", Type.int64()), + StructField.of("UNSIGNED_ATTRIBUTE", Type.bool()), + StructField.of("FIXED_PREC_SCALE", Type.bool()), + StructField.of("AUTO_INCREMENT", Type.bool()), + StructField.of("LOCAL_TYPE_NAME", Type.string()), + StructField.of("MINIMUM_SCALE", Type.int64()), + StructField.of("MAXIMUM_SCALE", Type.int64()), + StructField.of("SQL_DATA_TYPE", Type.int64()), + StructField.of("SQL_DATETIME_SUB", Type.int64()), + StructField.of("NUM_PREC_RADIX", Type.int64())), + Arrays.asList( + Struct.newBuilder() + .set("TYPE_NAME") + .to("STRING") + .set("DATA_TYPE") + .to(Types.NVARCHAR) // -9 + .set("PRECISION") + .to(2621440L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to("(length)") + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(true) + .set("SEARCHABLE") + .to(DatabaseMetaData.typeSearchable) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("STRING") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("INT64") + .set("DATA_TYPE") + .to(Types.BIGINT) // -5 + .set("PRECISION") + .to(19L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(false) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("INT64") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to(10) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("BYTES") + .set("DATA_TYPE") + .to(Types.BINARY) // -2 + .set("PRECISION") + .to(10485760L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to("(length)") + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("BYTES") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("FLOAT64") + .set("DATA_TYPE") + .to(Types.DOUBLE) // 8 + .set("PRECISION") + .to(15L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(false) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("FLOAT64") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to(2) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("BOOL") + .set("DATA_TYPE") + .to(Types.BOOLEAN) // 16 + .set("PRECISION") + .to((Long) null) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("BOOL") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("DATE") + .set("DATA_TYPE") + .to(Types.DATE) // 91 + .set("PRECISION") + .to(10L) + .set("LITERAL_PREFIX") + .to("DATE ") + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("DATE") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("TIMESTAMP") + .set("DATA_TYPE") + .to(Types.TIMESTAMP) // 93 + .set("PRECISION") + .to(35L) + .set("LITERAL_PREFIX") + .to("TIMESTAMP ") + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("TIMESTAMP") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build()))); + } + + @Override + public ResultSet getIndexInfo( + String catalog, String schema, String table, boolean unique, boolean approximate) + throws SQLException { + return getIndexInfo(catalog, schema, table, null, unique); + } + + public ResultSet getIndexInfo(String catalog, String schema, String indexName) + throws SQLException { + return getIndexInfo(catalog, schema, null, indexName, false); + } + + private ResultSet getIndexInfo( + String catalog, String schema, String table, String indexName, boolean unique) + throws SQLException { + String sql = readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString( + sql, catalog, schema, table, indexName, unique ? "YES" : "%"); + return statement.executeQuery(); + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return type == ResultSet.TYPE_FORWARD_ONLY; + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return type == ResultSet.TYPE_FORWARD_ONLY && concurrency == ResultSet.CONCUR_READ_ONLY; + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return false; + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return false; + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return true; + } + + @Override + public ResultSet getUDTs( + String catalog, String schemaPattern, String typeNamePattern, int[] types) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TYPE_CAT", Type.string()), + StructField.of("TYPE_SCHEM", Type.string()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("CLASS_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("REMARKS", Type.string()), + StructField.of("BASE_TYPE", Type.int64())), + Collections.emptyList())); + } + + @Override + public Connection getConnection() throws SQLException { + return connection; + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return false; + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return false; + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return true; + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return false; + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TYPE_CAT", Type.string()), + StructField.of("TYPE_SCHEM", Type.string()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("SUPERTYPE_CAT", Type.string()), + StructField.of("SUPERTYPE_SCHEM", Type.string()), + StructField.of("SUPERTYPE_NAME", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TABLE_CAT", Type.string()), + StructField.of("TABLE_SCHEM", Type.string()), + StructField.of("TABLE_NAME", Type.string()), + StructField.of("SUPERTABLE_NAME", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getAttributes( + String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TYPE_CAT", Type.string()), + StructField.of("TYPE_SCHEM", Type.string()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("ATTR_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("ATTR_TYPE_NAME", Type.string()), + StructField.of("ATTR_SIZE", Type.int64()), + StructField.of("DECIMAL_DIGITS", Type.int64()), + StructField.of("NUM_PREC_RADIX", Type.int64()), + StructField.of("NULLABLE", Type.int64()), + StructField.of("REMARKS", Type.string()), + StructField.of("ATTR_DEF", Type.string()), + StructField.of("SQL_DATA_TYPE", Type.int64()), + StructField.of("SQL_DATETIME_SUB", Type.int64()), + StructField.of("CHAR_OCTET_LENGTH", Type.int64()), + StructField.of("ORDINAL_POSITION", Type.int64()), + StructField.of("IS_NULLABLE", Type.string()), + StructField.of("SCOPE_CATALOG", Type.string()), + StructField.of("SCOPE_SCHEMA", Type.string()), + StructField.of("SCOPE_TABLE", Type.string()), + StructField.of("SOURCE_DATA_TYPE", Type.int64())), + Collections.emptyList())); + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + return DATABASE_MAJOR_VERSION; + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + return DATABASE_MINOR_VERSION; + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return JDBC_MAJOR_VERSION; + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return JDBC_MINOR_VERSION; + } + + @Override + public int getSQLStateType() throws SQLException { + return sqlStateSQL; + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return true; + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return false; + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return RowIdLifetime.ROWID_UNSUPPORTED; + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + String sql = readSqlFromFile("DatabaseMetaData_GetSchemas.sql"); + PreparedStatement statement = + prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern); + return statement.executeQuery(); + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return false; + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return false; + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("NAME", Type.string()), + StructField.of("MAX_LEN", Type.string()), + StructField.of("DEFAULT_VALUE", Type.string()), + StructField.of("DESCRIPTION", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) + throws SQLException { + // TODO: return system functions + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("FUNCTION_CAT", Type.string()), + StructField.of("FUNCTION_SCHEM", Type.string()), + StructField.of("FUNCTION_NAME", Type.string()), + StructField.of("REMARKS", Type.string()), + StructField.of("FUNCTION_TYPE", Type.int64()), + StructField.of("SPECIFIC_NAME", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getFunctionColumns( + String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) + throws SQLException { + // TODO: return system functions + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("FUNCTION_CAT", Type.string()), + StructField.of("FUNCTION_SCHEM", Type.string()), + StructField.of("FUNCTION_NAME", Type.string()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("COLUMN_TYPE", Type.int64()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("TYPE_NAME", Type.string()), + StructField.of("PRECISION", Type.int64()), + StructField.of("LENGTH", Type.int64()), + StructField.of("SCALE", Type.int64()), + StructField.of("RADIX", Type.int64()), + StructField.of("NULLABLE", Type.int64()), + StructField.of("REMARKS", Type.string()), + StructField.of("CHAR_OCTET_LENGTH", Type.int64()), + StructField.of("ORDINAL_POSITION", Type.int64()), + StructField.of("IS_NULLABLE", Type.string()), + StructField.of("SPECIFIC_NAME", Type.string())), + Collections.emptyList())); + } + + @Override + public ResultSet getPseudoColumns( + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) + throws SQLException { + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("TABLE_CAT", Type.string()), + StructField.of("TABLE_SCHEM", Type.string()), + StructField.of("TABLE_NAME", Type.string()), + StructField.of("COLUMN_NAME", Type.string()), + StructField.of("DATA_TYPE", Type.int64()), + StructField.of("COLUMN_SIZE", Type.int64()), + StructField.of("DECIMAL_DIGITS", Type.int64()), + StructField.of("NUM_PREC_RADIX", Type.int64()), + StructField.of("COLUMN_USAGE", Type.string()), + StructField.of("REMARKS", Type.string()), + StructField.of("CHAR_OCTET_LENGTH", Type.int64()), + StructField.of("IS_NULLABLE", Type.string())), + Collections.emptyList())); + } + + @Override + public boolean generatedKeyAlwaysReturned() throws SQLException { + return false; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java new file mode 100644 index 000000000000..80ee2cc6d14b --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -0,0 +1,239 @@ +/* + * Copyright 2019 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.api.core.InternalApi; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.jdbc.ConnectionOptions.ConnectionProperty; +import com.google.rpc.Code; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.DriverPropertyInfo; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * JDBC {@link Driver} for Google Cloud Spanner. + * + *

Usage: + * + *

+ * 
+ * {@code
+ * String url = "jdbc:cloudspanner:/projects/my_project_id/"
+ *            + "instances/my_instance_id/databases/my_database_name?"
+ *            + "credentials=/home/cloudspanner-keys/my-key.json;autocommit=false";
+ * try (Connection connection = DriverManager.getConnection(url)) {
+ *   try(ResultSet rs = connection.createStatement().executeQuery("SELECT SingerId, AlbumId, MarketingBudget FROM Albums")) {
+ *     while(rs.next()) {
+ *       // do something
+ *     }
+ *   }
+ * }
+ * }
+ * 
+ * 
+ * + * The connection that is returned will implement the interface {@link CloudSpannerJdbcConnection}. + * The JDBC connection URL must be specified in the following format: + * + *
+ * jdbc:cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\?property-name=property-value[;property-name=property-value]*]?
+ * 
+ * + * The property-value strings should be url-encoded. + * + *

The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This + * placeholder will be replaced by the default project id of the environment that is requesting a + * connection. + * + *

The supported properties are: + * + *

    + *
  • credentials (String): URL for the credentials file to use for the connection. If you do not + * specify any credentials at all, the default credentials of the environment as returned by + * {@link GoogleCredentials#getApplicationDefault()} will be used. + *
  • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. + *
  • readonly (boolean): Sets the initial readonly mode for the connection. Default is false. + *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the + * connection. Default is true. @see {@link + * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} + * for more information. + *
+ */ +public class JdbcDriver implements Driver { + private static final String JDBC_API_CLIENT_LIB_TOKEN = "sp-jdbc"; + static final int MAJOR_VERSION = 1; + static final int MINOR_VERSION = 0; + private static final String JDBC_URL_FORMAT = + "jdbc:" + ConnectionOptions.Builder.SPANNER_URI_FORMAT; + private static final Pattern URL_PATTERN = Pattern.compile(JDBC_URL_FORMAT); + + @InternalApi + public static String getClientLibToken() { + return JDBC_API_CLIENT_LIB_TOKEN; + } + + static { + try { + register(); + } catch (SQLException e) { + java.sql.DriverManager.println("Registering driver failed: " + e.getMessage()); + } + } + + private static JdbcDriver registeredDriver; + + static void register() throws SQLException { + if (isRegistered()) { + throw new IllegalStateException( + "Driver is already registered. It can only be registered once."); + } + JdbcDriver registeredDriver = new JdbcDriver(); + DriverManager.registerDriver(registeredDriver); + JdbcDriver.registeredDriver = registeredDriver; + } + + /** + * According to JDBC specification, this driver is registered against {@link DriverManager} when + * the class is loaded. To avoid leaks, this method allow unregistering the driver so that the + * class can be gc'ed if necessary. + * + * @throws IllegalStateException if the driver is not registered + * @throws SQLException if deregistering the driver fails + */ + static void deregister() throws SQLException { + if (!isRegistered()) { + throw new IllegalStateException( + "Driver is not registered (or it has not been registered using Driver.register() method)"); + } + ConnectionOptions.closeSpanner(); + DriverManager.deregisterDriver(registeredDriver); + registeredDriver = null; + } + + /** @return {@code true} if the driver is registered against {@link DriverManager} */ + static boolean isRegistered() { + return registeredDriver != null; + } + + /** + * @return the registered JDBC driver for Cloud Spanner. + * @throws SQLException if the driver has not been registered. + */ + static JdbcDriver getRegisteredDriver() throws SQLException { + if (isRegistered()) { + return registeredDriver; + } + throw JdbcSqlExceptionFactory.of( + "The driver has not been registered", Code.FAILED_PRECONDITION); + } + + public JdbcDriver() {} + + @Override + public Connection connect(String url, Properties info) throws SQLException { + if (url != null && url.startsWith("jdbc:cloudspanner")) { + try { + Matcher matcher = URL_PATTERN.matcher(url); + if (matcher.matches()) { + // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic + // Connection API + String connectionUri = appendPropertiesToUrl(url.substring(5), info); + ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build(); + return new JdbcConnection(url, options); + } + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of(e.getMessage(), Code.INVALID_ARGUMENT, e); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of(e.getMessage(), Code.UNKNOWN, e); + } + throw JdbcSqlExceptionFactory.of("invalid url: " + url, Code.INVALID_ARGUMENT); + } + return null; + } + + private String appendPropertiesToUrl(String url, Properties info) { + StringBuilder res = new StringBuilder(url); + for (Entry entry : info.entrySet()) { + if (entry.getValue() != null && !"".equals(entry.getValue())) { + res.append(";").append(entry.getKey()).append("=").append(entry.getValue()); + } + } + return res.toString(); + } + + @Override + public boolean acceptsURL(String url) throws SQLException { + return URL_PATTERN.matcher(url).matches(); + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { + String connectionUri = appendPropertiesToUrl(url.substring(5), info); + DriverPropertyInfo[] res = new DriverPropertyInfo[ConnectionOptions.VALID_PROPERTIES.size()]; + int i = 0; + for (ConnectionProperty prop : ConnectionOptions.VALID_PROPERTIES) { + res[i] = + new DriverPropertyInfo( + prop.getName(), + parseUriProperty(connectionUri, prop.getName(), prop.getDefaultValue())); + res[i].description = prop.getDescription(); + res[i].choices = prop.getValidValues(); + i++; + } + return res; + } + + private String parseUriProperty(String uri, String property, String defaultValue) { + Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); + Matcher matcher = pattern.matcher(uri); + if (matcher.find() && matcher.groupCount() == 1) { + return matcher.group(1); + } + return defaultValue; + } + + @Override + public int getMajorVersion() { + return 1; + } + + @Override + public int getMinorVersion() { + return 0; + } + + @Override + public boolean jdbcCompliant() { + return false; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java new file mode 100644 index 000000000000..f78f1f03dc65 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -0,0 +1,160 @@ +/* + * Copyright 2019 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.jdbc.JdbcParameterStore.ParametersInfo; +import java.math.BigDecimal; +import java.sql.Date; +import java.sql.ParameterMetaData; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; + +/** {@link ParameterMetaData} implementation for Cloud Spanner */ +class JdbcParameterMetaData extends AbstractJdbcWrapper implements ParameterMetaData { + private final JdbcPreparedStatement statement; + + JdbcParameterMetaData(JdbcPreparedStatement statement) throws SQLException { + this.statement = statement; + statement.getParameters().fetchMetaData(statement.getConnection()); + } + + @Override + public boolean isClosed() { + return false; + } + + @Override + public int getParameterCount() throws SQLException { + ParametersInfo info = statement.getParametersInfo(); + return info.numberOfParameters; + } + + @Override + public int isNullable(int param) throws SQLException { + Integer nullable = statement.getParameters().getNullable(param); + return nullable == null ? parameterNullableUnknown : nullable.intValue(); + } + + @Override + public boolean isSigned(int param) throws SQLException { + int type = getParameterType(param); + return type == Types.DOUBLE + || type == Types.FLOAT + || type == Types.BIGINT + || type == Types.INTEGER + || type == Types.SMALLINT + || type == Types.TINYINT + || type == Types.DECIMAL + || type == Types.NUMERIC; + } + + @Override + public int getPrecision(int param) throws SQLException { + Integer length = statement.getParameters().getScaleOrLength(param); + return length == null ? 0 : length.intValue(); + } + + @Override + public int getScale(int param) throws SQLException { + return 0; + } + + @Override + public int getParameterType(int param) throws SQLException { + Integer type = statement.getParameters().getType(param); + if (type != null) return type.intValue(); + + Object value = statement.getParameters().getParameter(param); + if (value == null) { + return Types.OTHER; + } else if (Boolean.class.isAssignableFrom(value.getClass())) { + return Types.BOOLEAN; + } else if (Byte.class.isAssignableFrom(value.getClass())) { + return Types.TINYINT; + } else if (Short.class.isAssignableFrom(value.getClass())) { + return Types.SMALLINT; + } else if (Integer.class.isAssignableFrom(value.getClass())) { + return Types.INTEGER; + } else if (Long.class.isAssignableFrom(value.getClass())) { + return Types.BIGINT; + } else if (Float.class.isAssignableFrom(value.getClass())) { + return Types.FLOAT; + } else if (Double.class.isAssignableFrom(value.getClass())) { + return Types.DOUBLE; + } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { + return Types.DECIMAL; + } else if (Date.class.isAssignableFrom(value.getClass())) { + return Types.DATE; + } else if (Timestamp.class.isAssignableFrom(value.getClass())) { + return Types.TIMESTAMP; + } else if (Time.class.isAssignableFrom(value.getClass())) { + return Types.TIME; + } else if (String.class.isAssignableFrom(value.getClass())) { + return Types.NVARCHAR; + } else if (byte[].class.isAssignableFrom(value.getClass())) { + return Types.BINARY; + } else { + return Types.OTHER; + } + } + + @Override + public String getParameterTypeName(int param) throws SQLException { + return getSpannerTypeName(getParameterType(param)); + } + + @Override + public String getParameterClassName(int param) throws SQLException { + Object value = statement.getParameters().getParameter(param); + if (value != null) return value.getClass().getName(); + Integer type = statement.getParameters().getType(param); + if (type != null) return getClassName(type.intValue()); + return null; + } + + @Override + public int getParameterMode(int param) throws SQLException { + return parameterModeIn; + } + + @Override + public String toString() { + StringBuilder res = new StringBuilder(); + try { + res.append("CloudSpannerPreparedStatementParameterMetaData, parameter count: ") + .append(getParameterCount()); + for (int param = 1; param <= getParameterCount(); param++) { + res.append("\nParameter ") + .append(param) + .append(":\n\t Class name: ") + .append(getParameterClassName(param)); + res.append(",\n\t Parameter type name: ").append(getParameterTypeName(param)); + res.append(",\n\t Parameter type: ").append(getParameterType(param)); + res.append(",\n\t Parameter precision: ").append(getPrecision(param)); + res.append(",\n\t Parameter scale: ").append(getScale(param)); + res.append(",\n\t Parameter signed: ").append(isSigned(param)); + res.append(",\n\t Parameter nullable: ").append(isNullable(param)); + res.append(",\n\t Parameter mode: ").append(getParameterMode(param)); + } + } catch (SQLException e) { + res.append("Error while fetching parameter metadata: ").append(e.getMessage()); + } + return res.toString(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java new file mode 100644 index 000000000000..5a139a9df0dc --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -0,0 +1,854 @@ +/* + * Copyright 2019 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.ByteArray; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Statement.Builder; +import com.google.cloud.spanner.ValueBinder; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.common.io.CharStreams; +import com.google.rpc.Code; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** This class handles the parameters of a {@link PreparedStatement}. */ +class JdbcParameterStore { + /** + * The initial size of the arrays that hold the parameter values. The array will automatically be + * extended when needed. + */ + private static final int INITIAL_PARAMETERS_ARRAY_SIZE = 10; + + private static final class JdbcParameter { + private Object value; + private Integer type; + private Integer nullable; + private Integer scaleOrLength; + private String column; + } + + private ArrayList parametersList = new ArrayList<>(INITIAL_PARAMETERS_ARRAY_SIZE); + + /** Name of the table that the parameters will be used to query/update. Can be null. */ + private String table; + + /** + * The highest parameter index in use. Parameter values do not need to be set in order, it could + * be that a parameter with for example index 10 is set first, and that the preceding parameters + * are set at a later time. + */ + private int highestIndex = 0; + + JdbcParameterStore() {} + + void clearParameters() { + parametersList = new ArrayList<>(INITIAL_PARAMETERS_ARRAY_SIZE); + highestIndex = 0; + table = null; + } + + /** Get parameter value. Index is 1-based. */ + Object getParameter(int parameterIndex) { + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) return null; + return parametersList.get(arrayIndex).value; + } + + /** Get parameter type code according to the values in {@link Types}. Index is 1-based. */ + Integer getType(int parameterIndex) { + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) return null; + return parametersList.get(arrayIndex).type; + } + + Integer getNullable(int parameterIndex) { + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) return null; + return parametersList.get(arrayIndex).nullable; + } + + Integer getScaleOrLength(int parameterIndex) { + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) return null; + return parametersList.get(arrayIndex).scaleOrLength; + } + + String getColumn(int parameterIndex) { + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) return null; + return parametersList.get(arrayIndex).column; + } + + String getTable() { + return table; + } + + void setTable(String table) { + this.table = table; + } + + void setColumn(int parameterIndex, String column) throws SQLException { + setParameter( + parameterIndex, + getParameter(parameterIndex), + getType(parameterIndex), + getScaleOrLength(parameterIndex), + column); + } + + void setType(int parameterIndex, Integer type) throws SQLException { + setParameter( + parameterIndex, + getParameter(parameterIndex), + type, + getScaleOrLength(parameterIndex), + getColumn(parameterIndex)); + } + + void setParameter(int parameterIndex, Object value, Integer sqlType) throws SQLException { + setParameter(parameterIndex, value, sqlType, null); + } + + void setParameter(int parameterIndex, Object value, Integer sqlType, Integer scaleOrLength) + throws SQLException { + setParameter(parameterIndex, value, sqlType, scaleOrLength, null); + } + + void setParameter( + int parameterIndex, Object value, Integer sqlType, Integer scaleOrLength, String column) + throws SQLException { + // check that only valid type/value combinations are entered + if (sqlType != null) { + checkTypeAndValueSupported(value, sqlType); + } + // set the parameter + highestIndex = Math.max(parameterIndex, highestIndex); + int arrayIndex = parameterIndex - 1; + if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) { + parametersList.ensureCapacity(parameterIndex); + while (parametersList.size() < parameterIndex) { + parametersList.add(null); + } + parametersList.set(arrayIndex, new JdbcParameter()); + } + JdbcParameter param = parametersList.get(arrayIndex); + param.value = value; + param.type = sqlType; + param.scaleOrLength = scaleOrLength; + param.column = column; + } + + private void checkTypeAndValueSupported(Object value, int sqlType) throws SQLException { + if (!isTypeSupported(sqlType)) { + throw JdbcSqlExceptionFactory.of( + "Type " + sqlType + " is not supported", Code.INVALID_ARGUMENT); + } + if (!isValidTypeAndValue(value, sqlType)) { + throw JdbcSqlExceptionFactory.of( + value + " is not a valid value for type " + sqlType, Code.INVALID_ARGUMENT); + } + } + + private boolean isTypeSupported(int sqlType) { + switch (sqlType) { + case Types.BIT: + case Types.BOOLEAN: + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.NCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + case Types.DATE: + case Types.TIME: + case Types.TIMESTAMP: + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + case Types.ARRAY: + case Types.BLOB: + case Types.CLOB: + case Types.NCLOB: + return true; + case Types.NUMERIC: + case Types.DECIMAL: + // currently not supported as Cloud Spanner does not have any decimal data type. + return false; + } + return false; + } + + private boolean isValidTypeAndValue(Object value, int sqlType) { + if (value == null) { + return true; + } + switch (sqlType) { + case Types.BIT: + case Types.BOOLEAN: + return value instanceof Boolean || value instanceof Number; + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + return value instanceof Number; + case Types.NUMERIC: + case Types.DECIMAL: + // currently not supported as Cloud Spanner does not have any decimal data type. + return false; + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.NCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + return value instanceof String + || value instanceof InputStream + || value instanceof Reader + || value instanceof URL; + case Types.DATE: + case Types.TIME: + case Types.TIMESTAMP: + return value instanceof Date || value instanceof Time || value instanceof Timestamp; + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + return value instanceof byte[] || value instanceof InputStream; + case Types.ARRAY: + return value instanceof Array; + case Types.BLOB: + return value instanceof Blob || value instanceof InputStream; + case Types.CLOB: + return value instanceof Clob || value instanceof Reader; + case Types.NCLOB: + return value instanceof NClob || value instanceof Reader; + } + return false; + } + + /** Return the highest param index in use in this store. */ + int getHighestIndex() { + return highestIndex; + } + + /** Fetch parameter metadata from the database. */ + void fetchMetaData(Connection connection) throws SQLException { + if (table != null && !"".equals(table)) { + try (ResultSet rsCols = connection.getMetaData().getColumns(null, null, table, null)) { + while (rsCols.next()) { + String col = rsCols.getString("COLUMN_NAME"); + int arrayIndex = getParameterArrayIndex(col); + if (arrayIndex > -1) { + JdbcParameter param = parametersList.get(arrayIndex); + if (param != null) { + param.scaleOrLength = rsCols.getInt("COLUMN_SIZE"); + param.type = rsCols.getInt("DATA_TYPE"); + param.nullable = rsCols.getInt("NULLABLE"); + } + } + } + } + } + } + + private int getParameterArrayIndex(String columnName) { + if (columnName != null) { + for (int index = 0; index < highestIndex; index++) { + JdbcParameter param = parametersList.get(index); + if (param != null && param.column != null) { + if (columnName.equalsIgnoreCase(param.column)) { + return index; + } + } + } + } + return -1; + } + + /** Parameter information with positional parameters translated to named parameters. */ + static class ParametersInfo { + final int numberOfParameters; + final String sqlWithNamedParameters; + + private ParametersInfo(int numberOfParameters, String sqlWithNamedParameters) { + this.numberOfParameters = numberOfParameters; + this.sqlWithNamedParameters = sqlWithNamedParameters; + } + } + + /** + * Converts all positional parameters (?) in the given sql string into named parameters. The + * parameters are named @p1, @p2, etc. This method is used when converting a JDBC statement that + * uses positional parameters to a Cloud Spanner {@link Statement} instance that requires named + * parameters. The input SQL string may not contain any comments. + * + * @param sql The sql string without comments that should be converted + * @return A {@link ParametersInfo} object containing a string with named parameters instead of + * positional parameters and the number of parameters. + * @throws JdbcSqlExceptionImpl If the input sql string contains an unclosed string/byte literal. + */ + static ParametersInfo convertPositionalParametersToNamedParameters(String sql) + throws SQLException { + final char POS_PARAM = '?'; + final char SINGLE_QUOTE = '\''; + final char DOUBLE_QUOTE = '"'; + final char BACKTICK_QUOTE = '`'; + boolean isInQuoted = false; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + boolean isTripleQuoted = false; + int paramIndex = 1; + StringBuilder named = new StringBuilder(sql.length() + countOccurrencesOf(POS_PARAM, sql)); + for (int index = 0; index < sql.length(); index++) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && !isTripleQuoted) { + throw JdbcSqlExceptionFactory.of( + "SQL statement contains an unclosed literal: " + sql, Code.INVALID_ARGUMENT); + } else if (c == startQuote) { + if (lastCharWasEscapeChar) { + lastCharWasEscapeChar = false; + } else if (isTripleQuoted) { + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isInQuoted = false; + startQuote = 0; + isTripleQuoted = false; + } + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + named.append(c); + } else { + if (c == POS_PARAM) { + named.append("@p" + paramIndex); + paramIndex++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { + isInQuoted = true; + startQuote = c; + // check whether it is a triple-quote + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isTripleQuoted = true; + } + } + named.append(c); + } + } + } + if (isInQuoted) { + throw JdbcSqlExceptionFactory.of( + "SQL statement contains an unclosed literal: " + sql, Code.INVALID_ARGUMENT); + } + return new ParametersInfo(paramIndex - 1, named.toString()); + } + + /** Convenience method that is used to estimate the number of parameters in a SQL statement. */ + private static int countOccurrencesOf(char c, String string) { + int res = 0; + for (int i = 0; i < string.length(); i++) { + if (string.charAt(i) == c) { + res++; + } + } + return res; + } + + /** Bind a JDBC parameter to a parameter on a Spanner {@link Statement}. */ + Builder bindParameterValue(ValueBinder binder, int index) throws SQLException { + return setValue(binder, getParameter(index), getType(index)); + } + + /** Set a value from a JDBC parameter on a Spanner {@link Statement}. */ + Builder setValue(ValueBinder binder, Object value, Integer sqlType) throws SQLException { + Builder res; + if (sqlType != null && sqlType == Types.ARRAY) { + if (value instanceof Array) { + Array array = (Array) value; + value = array.getArray(); + sqlType = array.getBaseType(); + } + res = setArrayValue(binder, sqlType, value); + } else { + res = setSingleValue(binder, value, sqlType); + } + if (res == null && value != null) { + throw JdbcSqlExceptionFactory.of( + "Unsupported parameter type: " + value.getClass().getName() + " - " + value.toString(), + Code.INVALID_ARGUMENT); + } + return res; + } + + private Builder setSingleValue(ValueBinder binder, Object value, Integer sqlType) + throws SQLException { + if (value == null) { + return setNullValue(binder, sqlType); + } else if (sqlType == null || sqlType == Integer.valueOf(Types.OTHER)) { + return setParamWithUnknownType(binder, value); + } else { + return setParamWithKnownType(binder, value, sqlType); + } + } + + /** Set a JDBC parameter value on a Spanner {@link Statement} with a known SQL type. */ + private Builder setParamWithKnownType(ValueBinder binder, Object value, Integer sqlType) + throws SQLException { + switch (sqlType) { + case Types.BIT: + case Types.BOOLEAN: + if (value instanceof Boolean) { + return binder.to((Boolean) value); + } else if (value instanceof Number) { + return binder.to(((Number) value).longValue() != 0L); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid boolean", Code.INVALID_ARGUMENT); + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + if (value instanceof Number) { + return binder.to(((Number) value).longValue()); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid long", Code.INVALID_ARGUMENT); + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + if (value instanceof Number) { + return binder.to(((Number) value).doubleValue()); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid double", Code.INVALID_ARGUMENT); + case Types.NUMERIC: + case Types.DECIMAL: + // currently not supported as Cloud Spanner does not have any decimal data type. + throw JdbcSqlExceptionFactory.of( + "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.NCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + if (value instanceof String) { + return binder.to((String) value); + } else if (value instanceof InputStream) { + InputStreamReader reader = + new InputStreamReader((InputStream) value, StandardCharsets.US_ASCII); + try { + return binder.to(CharStreams.toString(reader)); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from input stream", Code.INVALID_ARGUMENT, e); + } + } else if (value instanceof Reader) { + try { + return binder.to(CharStreams.toString((Reader) value)); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from reader", Code.INVALID_ARGUMENT, e); + } + } else if (value instanceof URL) { + return binder.to(((URL) value).toString()); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); + case Types.DATE: + if (value instanceof Date) { + return binder.to(JdbcTypeConverter.toGoogleDate((Date) value)); + } else if (value instanceof Time) { + return binder.to(JdbcTypeConverter.toGoogleDate((Time) value)); + } else if (value instanceof Timestamp) { + return binder.to(JdbcTypeConverter.toGoogleDate((Timestamp) value)); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid date", Code.INVALID_ARGUMENT); + case Types.TIME: + case Types.TIMESTAMP: + if (value instanceof Date) { + return binder.to(JdbcTypeConverter.toGoogleTimestamp((Date) value)); + } else if (value instanceof Time) { + return binder.to(JdbcTypeConverter.toGoogleTimestamp((Time) value)); + } else if (value instanceof Timestamp) { + return binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); + } + throw JdbcSqlExceptionFactory.of( + value + " is not a valid timestamp", Code.INVALID_ARGUMENT); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + if (value instanceof byte[]) { + return binder.to(ByteArray.copyFrom((byte[]) value)); + } else if (value instanceof InputStream) { + try { + return binder.to(ByteArray.copyFrom((InputStream) value)); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "Could not copy bytes from input stream: " + e.getMessage(), + Code.INVALID_ARGUMENT, + e); + } + } + throw JdbcSqlExceptionFactory.of( + value + " is not a valid byte array", Code.INVALID_ARGUMENT); + case Types.ARRAY: + if (value instanceof Array) { + Array jdbcArray = (Array) value; + return setArrayValue(binder, sqlType, jdbcArray == null ? null : jdbcArray.getArray()); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid array", Code.INVALID_ARGUMENT); + case Types.BLOB: + if (value instanceof Blob) { + try { + return binder.to(ByteArray.copyFrom(((Blob) value).getBinaryStream())); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set bytes from blob", Code.INVALID_ARGUMENT, e); + } + } else if (value instanceof InputStream) { + try { + return binder.to(ByteArray.copyFrom((InputStream) value)); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set bytes from input stream", Code.INVALID_ARGUMENT, e); + } + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid blob", Code.INVALID_ARGUMENT); + case Types.CLOB: + case Types.NCLOB: + if (value instanceof Clob) { + try { + return binder.to(CharStreams.toString(((Clob) value).getCharacterStream())); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from clob", Code.INVALID_ARGUMENT, e); + } + } else if (value instanceof Reader) { + try { + return binder.to(CharStreams.toString((Reader) value)); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from reader", Code.INVALID_ARGUMENT, e); + } + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid clob", Code.INVALID_ARGUMENT); + } + return null; + } + + /** Set the parameter value based purely on the type of the value. */ + private Builder setParamWithUnknownType(ValueBinder binder, Object value) + throws SQLException { + if (Boolean.class.isAssignableFrom(value.getClass())) { + return binder.to((Boolean) value); + } else if (Byte.class.isAssignableFrom(value.getClass())) { + return binder.to(((Byte) value).longValue()); + } else if (Short.class.isAssignableFrom(value.getClass())) { + return binder.to(((Short) value).longValue()); + } else if (Integer.class.isAssignableFrom(value.getClass())) { + return binder.to(((Integer) value).longValue()); + } else if (Long.class.isAssignableFrom(value.getClass())) { + return binder.to(((Long) value).longValue()); + } else if (Float.class.isAssignableFrom(value.getClass())) { + return binder.to(((Float) value).doubleValue()); + } else if (Double.class.isAssignableFrom(value.getClass())) { + return binder.to(((Double) value).doubleValue()); + } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { + // currently not supported + return null; + } else if (Date.class.isAssignableFrom(value.getClass())) { + Date dateValue = (Date) value; + return binder.to(JdbcTypeConverter.toGoogleDate(dateValue)); + } else if (Timestamp.class.isAssignableFrom(value.getClass())) { + return binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); + } else if (Time.class.isAssignableFrom(value.getClass())) { + Time timeValue = (Time) value; + return binder.to(JdbcTypeConverter.toGoogleTimestamp(new Timestamp(timeValue.getTime()))); + } else if (String.class.isAssignableFrom(value.getClass())) { + String stringVal = (String) value; + return binder.to(stringVal); + } else if (Reader.class.isAssignableFrom(value.getClass())) { + try { + Reader readable = (Reader) value; + return binder.to(CharStreams.toString(readable)); + } catch (IOException e) { + throw new IllegalArgumentException("Could not read from readable", e); + } + } else if (Clob.class.isAssignableFrom(value.getClass()) + || NClob.class.isAssignableFrom(value.getClass())) { + try { + Clob clob = (Clob) value; + return binder.to(CharStreams.toString(clob.getCharacterStream())); + } catch (IOException e) { + throw new IllegalArgumentException("Could not read from readable", e); + } + } else if (Character.class.isAssignableFrom(value.getClass())) { + return binder.to(((Character) value).toString()); + } else if (Character[].class.isAssignableFrom(value.getClass())) { + List list = Arrays.asList((Character[]) value); + StringBuilder s = new StringBuilder(); + for (Character c : list) { + s.append(c.charValue()); + } + return binder.to(s.toString()); + } else if (char[].class.isAssignableFrom(value.getClass())) { + return binder.to(String.valueOf((char[]) value)); + } else if (URL.class.isAssignableFrom(value.getClass())) { + return binder.to(((URL) value).toString()); + } else if (byte[].class.isAssignableFrom(value.getClass())) { + return binder.to(ByteArray.copyFrom((byte[]) value)); + } else if (InputStream.class.isAssignableFrom(value.getClass())) { + try { + return binder.to(ByteArray.copyFrom((InputStream) value)); + } catch (IOException e) { + throw new IllegalArgumentException( + "Could not copy bytes from input stream: " + e.getMessage(), e); + } + } else if (Blob.class.isAssignableFrom(value.getClass())) { + try { + return binder.to(ByteArray.copyFrom(((Blob) value).getBinaryStream())); + } catch (IOException e) { + throw new IllegalArgumentException( + "Could not copy bytes from input stream: " + e.getMessage(), e); + } + } else if (Array.class.isAssignableFrom(value.getClass())) { + try { + Array jdbcArray = (Array) value; + if (value != null) { + return setArrayValue(binder, jdbcArray.getBaseType(), jdbcArray.getArray()); + } + } catch (SQLException e) { + throw new IllegalArgumentException( + "Unsupported parameter type: " + value.getClass().getName() + " - " + value.toString()); + } + } + return null; + } + + private Builder setArrayValue(ValueBinder binder, int type, Object value) + throws SQLException { + if (value == null) { + switch (type) { + case Types.BIT: + case Types.BOOLEAN: + return binder.toBoolArray((boolean[]) null); + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + return binder.toInt64Array((long[]) null); + case Types.FLOAT: + case Types.REAL: + case Types.DOUBLE: + return binder.toFloat64Array((double[]) null); + case Types.NUMERIC: + case Types.DECIMAL: + throw JdbcSqlExceptionFactory.of( + "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.NCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + case Types.CLOB: + case Types.NCLOB: + return binder.toStringArray((Iterable) null); + case Types.DATE: + return binder.toDateArray((Iterable) null); + case Types.TIME: + case Types.TIMESTAMP: + return binder.toTimestampArray((Iterable) null); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + case Types.BLOB: + return binder.toBytesArray((Iterable) null); + } + throw JdbcSqlExceptionFactory.unsupported("Unknown/unsupported array base type: " + type); + } + + if (boolean[].class.isAssignableFrom(value.getClass())) { + return binder.toBoolArray((boolean[]) value); + } else if (Boolean[].class.isAssignableFrom(value.getClass())) { + return binder.toBoolArray(Arrays.asList((Boolean[]) value)); + } else if (short[].class.isAssignableFrom(value.getClass())) { + long[] l = new long[((short[]) value).length]; + for (int i = 0; i < l.length; i++) { + l[i] = ((short[]) value)[i]; + } + return binder.toInt64Array(l); + } else if (Short[].class.isAssignableFrom(value.getClass())) { + return binder.toInt64Array(toLongList((Short[]) value)); + } else if (int[].class.isAssignableFrom(value.getClass())) { + long[] l = new long[((int[]) value).length]; + for (int i = 0; i < l.length; i++) { + l[i] = ((int[]) value)[i]; + } + return binder.toInt64Array(l); + } else if (Integer[].class.isAssignableFrom(value.getClass())) { + return binder.toInt64Array(toLongList((Integer[]) value)); + } else if (long[].class.isAssignableFrom(value.getClass())) { + return binder.toInt64Array((long[]) value); + } else if (Long[].class.isAssignableFrom(value.getClass())) { + return binder.toInt64Array(toLongList((Long[]) value)); + } else if (float[].class.isAssignableFrom(value.getClass())) { + double[] l = new double[((float[]) value).length]; + for (int i = 0; i < l.length; i++) { + l[i] = ((float[]) value)[i]; + } + return binder.toFloat64Array(l); + } else if (Float[].class.isAssignableFrom(value.getClass())) { + return binder.toFloat64Array(toDoubleList((Float[]) value)); + } else if (double[].class.isAssignableFrom(value.getClass())) { + return binder.toFloat64Array((double[]) value); + } else if (Double[].class.isAssignableFrom(value.getClass())) { + return binder.toFloat64Array(toDoubleList((Double[]) value)); + } else if (BigDecimal[].class.isAssignableFrom(value.getClass())) { + // currently not supported + return null; + } else if (Date[].class.isAssignableFrom(value.getClass())) { + return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value)); + } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { + return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value)); + } else if (String[].class.isAssignableFrom(value.getClass())) { + return binder.toStringArray(Arrays.asList((String[]) value)); + } else if (byte[][].class.isAssignableFrom(value.getClass())) { + return binder.toBytesArray(JdbcTypeConverter.toGoogleBytes((byte[][]) value)); + } + return null; + } + + private List toLongList(Number[] input) { + List res = new ArrayList<>(input.length); + for (int i = 0; i < input.length; i++) { + res.add(input[i] == null ? null : input[i].longValue()); + } + return res; + } + + private List toDoubleList(Number[] input) { + List res = new ArrayList<>(input.length); + for (int i = 0; i < input.length; i++) { + res.add(input[i] == null ? null : input[i].doubleValue()); + } + return res; + } + + /** + * Sets a null value with a specific SQL type. If the sqlType is null, the value will be set as a + * String. + */ + private Builder setNullValue(ValueBinder binder, Integer sqlType) throws SQLException { + if (sqlType == null) { + return binder.to((String) null); + } + switch (sqlType) { + case Types.BIGINT: + return binder.to((Long) null); + case Types.BINARY: + return binder.to((ByteArray) null); + case Types.BLOB: + return binder.to((ByteArray) null); + case Types.BOOLEAN: + return binder.to((Boolean) null); + case Types.CHAR: + return binder.to((String) null); + case Types.CLOB: + return binder.to((String) null); + case Types.DATE: + return binder.to((com.google.cloud.Date) null); + case Types.NUMERIC: + case Types.DECIMAL: + // currently not supported + throw JdbcSqlExceptionFactory.of( + "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + case Types.DOUBLE: + return binder.to((Double) null); + case Types.FLOAT: + return binder.to((Double) null); + case Types.INTEGER: + return binder.to((Long) null); + case Types.LONGNVARCHAR: + return binder.to((String) null); + case Types.LONGVARBINARY: + return binder.to((ByteArray) null); + case Types.LONGVARCHAR: + return binder.to((String) null); + case Types.NCHAR: + return binder.to((String) null); + case Types.NCLOB: + return binder.to((String) null); + case Types.NVARCHAR: + return binder.to((String) null); + case Types.REAL: + return binder.to((Double) null); + case Types.SMALLINT: + return binder.to((Long) null); + case Types.SQLXML: + return binder.to((String) null); + case Types.TIME: + return binder.to((com.google.cloud.Timestamp) null); + case Types.TIMESTAMP: + return binder.to((com.google.cloud.Timestamp) null); + case Types.TINYINT: + return binder.to((Long) null); + case Types.VARBINARY: + return binder.to((ByteArray) null); + case Types.VARCHAR: + return binder.to((String) null); + default: + throw new IllegalArgumentException("Unsupported sql type for setting to null: " + sqlType); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java new file mode 100644 index 000000000000..a516e68b7da7 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java @@ -0,0 +1,70 @@ +/* + * Copyright 2019 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.rpc.Code; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import javax.annotation.Nullable; + +/** + * Convenience class for throwing {@link SQLException}s when a certain condition has not been met. + */ +class JdbcPreconditions { + + /** + * Ensures the truth of an expression involving a parameter to a method. + * + * @param expression the boolean expression that should be true. + * @param value the parameter value that is being checked. + * @throws JdbcSqlException with {@link Code#INVALID_ARGUMENT} if {@code expression} is false + */ + static void checkArgument(boolean expression, Object value) throws SQLException { + if (!expression) { + throw JdbcSqlExceptionFactory.of("invalid argument: " + value, Code.INVALID_ARGUMENT); + } + } + + /** + * Ensures the truth of an expression involving the state of the calling instance, but not + * involving any parameters to the calling method. + * + * @param expression a boolean expression + * @param errorMessage the exception message to use if the check fails; will be converted to a + * string using {@link String#valueOf(Object)} + * @throws JdbcSqlException with {@link Code#FAILED_PRECONDITION} if {@code expression} is false + */ + static void checkState(boolean expression, @Nullable Object errorMessage) throws SQLException { + if (!expression) { + throw JdbcSqlExceptionFactory.of(String.valueOf(errorMessage), Code.FAILED_PRECONDITION); + } + } + + /** + * Ensures the support of a certain JDBC feature. + * + * @param expression the boolean expression that indicates whether the feature is supported. + * @param message the exception message to use if the feature is not supported. + * @throws SQLFeatureNotSupportedException if the feature is not supported. + */ + static void checkSqlFeatureSupported(boolean expression, String message) + throws SQLFeatureNotSupportedException { + if (!expression) { + throw JdbcSqlExceptionFactory.unsupported(message); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java new file mode 100644 index 000000000000..a42720ddc550 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -0,0 +1,82 @@ +/* + * Copyright 2019 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.Statement; +import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** Implementation of {@link PreparedStatement} for Cloud Spanner. */ +class JdbcPreparedStatement extends AbstractJdbcPreparedStatement { + private final String sql; + private final String sqlWithoutComments; + private final ParametersInfo parameters; + + JdbcPreparedStatement(JdbcConnection connection, String sql) throws SQLException { + super(connection); + this.sql = sql; + this.sqlWithoutComments = StatementParser.removeCommentsAndTrim(this.sql); + this.parameters = + JdbcParameterStore.convertPositionalParametersToNamedParameters(sqlWithoutComments); + } + + ParametersInfo getParametersInfo() throws SQLException { + return parameters; + } + + private Statement createStatement() throws SQLException { + ParametersInfo paramInfo = getParametersInfo(); + Statement.Builder builder = Statement.newBuilder(paramInfo.sqlWithNamedParameters); + for (int index = 1; index <= getParameters().getHighestIndex(); index++) { + getParameters().bindParameterValue(builder.bind("p" + index), index); + } + return builder.build(); + } + + @Override + public ResultSet executeQuery() throws SQLException { + checkClosed(); + return executeQuery(createStatement()); + } + + @Override + public int executeUpdate() throws SQLException { + checkClosed(); + return executeUpdate(createStatement()); + } + + @Override + public boolean execute() throws SQLException { + checkClosed(); + return executeStatement(createStatement()); + } + + @Override + public void addBatch() throws SQLException { + checkClosed(); + checkAndSetBatchType(sql); + batchedStatements.add(createStatement()); + } + + @Override + public JdbcParameterMetaData getParameterMetaData() throws SQLException { + checkClosed(); + return new JdbcParameterMetaData(this); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java new file mode 100644 index 000000000000..00c6361ff47e --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -0,0 +1,682 @@ +/* + * Copyright 2019 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.Type; +import com.google.cloud.spanner.Type.Code; +import com.google.common.base.Preconditions; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + +/** Implementation of {@link ResultSet} for Cloud Spanner */ +class JdbcResultSet extends AbstractJdbcResultSet { + + static JdbcResultSet of(com.google.cloud.spanner.ResultSet resultSet) { + Preconditions.checkNotNull(resultSet); + return new JdbcResultSet(null, resultSet); + } + + static JdbcResultSet of(Statement statement, com.google.cloud.spanner.ResultSet resultSet) { + Preconditions.checkNotNull(statement); + Preconditions.checkNotNull(resultSet); + return new JdbcResultSet(statement, resultSet); + } + + private boolean closed = false; + private final Statement statement; + private boolean wasNull = false; + private boolean nextReturnedFalse = false; + private boolean nextCalledForMetaData = false; + private boolean nextCalledForMetaDataResult = false; + private long currentRow = 0L; + + private JdbcResultSet(Statement statement, com.google.cloud.spanner.ResultSet spanner) { + super(spanner); + this.statement = statement; + } + + void checkClosedAndValidRow() throws SQLException { + checkClosed(); + if (currentRow == 0L) { + throw JdbcSqlExceptionFactory.of( + "ResultSet is before first row. Call next() first.", + com.google.rpc.Code.FAILED_PRECONDITION); + } + if (nextReturnedFalse) { + throw JdbcSqlExceptionFactory.of( + "ResultSet is after last row. There is no more data available.", + com.google.rpc.Code.FAILED_PRECONDITION); + } + } + + @Override + public boolean next() throws SQLException { + checkClosed(); + currentRow++; + if (nextCalledForMetaData) { + nextReturnedFalse = !nextCalledForMetaDataResult; + nextCalledForMetaData = false; + } else { + nextReturnedFalse = !spanner.next(); + } + + return !nextReturnedFalse; + } + + @Override + public void close() throws SQLException { + spanner.close(); + this.closed = true; + } + + @Override + public boolean wasNull() throws SQLException { + checkClosedAndValidRow(); + return wasNull; + } + + private boolean isNull(int columnIndex) { + wasNull = spanner.isNull(columnIndex - 1); + return wasNull; + } + + private boolean isNull(String columnName) { + wasNull = spanner.isNull(columnName); + return wasNull; + } + + @Override + public String getString(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) ? null : spanner.getString(columnIndex - 1); + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) ? false : spanner.getBoolean(columnIndex - 1); + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); + return checkedCastToByte(val); + } + + @Override + public short getShort(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); + return checkedCastToShort(val); + } + + @Override + public int getInt(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); + return checkedCastToInt(val); + } + + @Override + public long getLong(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + double val = isNull(columnIndex) ? 0D : spanner.getDouble(columnIndex - 1); + return checkedCastToFloat(val); + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) ? 0D : spanner.getDouble(columnIndex - 1); + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) ? null : spanner.getBytes(columnIndex - 1).toByteArray(); + } + + @Override + public Date getDate(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.toSqlDate(spanner.getDate(columnIndex - 1)); + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnIndex - 1)); + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(columnIndex - 1)); + } + + private InputStream getInputStream(String val, Charset charset) { + if (val == null) return null; + byte[] b = val.getBytes(charset); + return new ByteArrayInputStream(b); + } + + @Override + public InputStream getAsciiStream(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return getInputStream(getString(columnIndex), StandardCharsets.US_ASCII); + } + + @Override + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return getInputStream(getString(columnIndex), StandardCharsets.UTF_16LE); + } + + @Override + public InputStream getBinaryStream(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + byte[] val = getBytes(columnIndex); + return val == null ? null : new ByteArrayInputStream(val); + } + + @Override + public String getString(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? null : spanner.getString(columnLabel); + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? false : spanner.getBoolean(columnLabel); + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); + return checkedCastToByte(val); + } + + @Override + public short getShort(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); + return checkedCastToShort(val); + } + + @Override + public int getInt(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); + return checkedCastToInt(val); + } + + @Override + public long getLong(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + double val = isNull(columnLabel) ? 0D : spanner.getDouble(columnLabel); + return checkedCastToFloat(val); + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? 0D : spanner.getDouble(columnLabel); + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? null : spanner.getBytes(columnLabel).toByteArray(); + } + + @Override + public Date getDate(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) ? null : JdbcTypeConverter.toSqlDate(spanner.getDate(columnLabel)); + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) + ? null + : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnLabel)); + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) + ? null + : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(columnLabel)); + } + + @Override + public InputStream getAsciiStream(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getInputStream(getString(columnLabel), StandardCharsets.US_ASCII); + } + + @Override + public InputStream getUnicodeStream(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getInputStream(getString(columnLabel), StandardCharsets.UTF_16LE); + } + + @Override + public InputStream getBinaryStream(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + byte[] val = getBytes(columnLabel); + return val == null ? null : new ByteArrayInputStream(val); + } + + @Override + public JdbcResultSetMetaData getMetaData() throws SQLException { + checkClosed(); + if (isBeforeFirst()) { + // do a call to next() on the underlying resultset to initialize metadata + nextCalledForMetaData = true; + nextCalledForMetaDataResult = spanner.next(); + } + return new JdbcResultSetMetaData(this, statement); + } + + @Override + public Object getObject(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + Type type = spanner.getColumnType(columnLabel); + return isNull(columnLabel) ? null : getObject(type, columnLabel); + } + + @Override + public Object getObject(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + Type type = spanner.getColumnType(columnIndex - 1); + return isNull(columnIndex) ? null : getObject(type, columnIndex); + } + + private Object getObject(Type type, String columnLabel) throws SQLException { + return getObject(type, spanner.getColumnIndex(columnLabel) + 1); + } + + private Object getObject(Type type, int columnIndex) throws SQLException { + if (type == Type.bool()) return getBoolean(columnIndex); + if (type == Type.bytes()) return getBytes(columnIndex); + if (type == Type.date()) return getDate(columnIndex); + if (type == Type.float64()) return getDouble(columnIndex); + if (type == Type.int64()) return getLong(columnIndex); + if (type == Type.string()) return getString(columnIndex); + if (type == Type.timestamp()) return getTimestamp(columnIndex); + if (type.getCode() == Code.ARRAY) return getArray(columnIndex); + throw JdbcSqlExceptionFactory.of( + "Unknown type: " + type.toString(), com.google.rpc.Code.INVALID_ARGUMENT); + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + checkClosed(); + try { + return spanner.getColumnIndex(columnLabel) + 1; + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of( + "no column with label " + columnLabel + " found", com.google.rpc.Code.INVALID_ARGUMENT); + } + } + + @Override + public Reader getCharacterStream(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnIndex); + return val == null ? null : new StringReader(val); + } + + @Override + public Reader getCharacterStream(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnLabel); + return val == null ? null : new StringReader(val); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return getBigDecimal(columnIndex, false, 0); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getBigDecimal(spanner.getColumnIndex(columnLabel) + 1, false, 0); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + checkClosedAndValidRow(); + return getBigDecimal(columnIndex, true, scale); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { + checkClosedAndValidRow(); + return getBigDecimal(spanner.getColumnIndex(columnLabel) + 1, true, scale); + } + + private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) + throws SQLException { + Type type = spanner.getColumnType(columnIndex - 1); + BigDecimal res; + if (isNull(columnIndex)) { + res = null; + } else { + if (type.getCode() == Code.STRING) { + try { + res = new BigDecimal(spanner.getString(columnIndex - 1)); + } catch (NumberFormatException e) { + throw JdbcSqlExceptionFactory.of( + "The column does not contain a valid BigDecimal", + com.google.rpc.Code.INVALID_ARGUMENT, + e); + } + } else if (type.getCode() == Code.INT64) { + res = BigDecimal.valueOf(spanner.getLong(columnIndex - 1)); + } else if (type.getCode() == Code.FLOAT64) { + res = BigDecimal.valueOf(spanner.getDouble(columnIndex - 1)); + } else { + throw JdbcSqlExceptionFactory.of( + "The column does not contain a valid BigDecimal", com.google.rpc.Code.INVALID_ARGUMENT); + } + if (fixedScale) { + res = res.setScale(scale, RoundingMode.HALF_UP); + } + } + return res; + } + + @Override + public boolean isBeforeFirst() throws SQLException { + checkClosed(); + return currentRow == 0L; + } + + @Override + public boolean isAfterLast() throws SQLException { + checkClosed(); + return nextReturnedFalse; + } + + @Override + public boolean isFirst() throws SQLException { + checkClosed(); + return currentRow == 1L; + } + + @Override + public int getRow() throws SQLException { + checkClosed(); + return checkedCastToInt(currentRow); + } + + @Override + public Statement getStatement() throws SQLException { + checkClosed(); + return statement; + } + + @Override + public Array getArray(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getArray(findColumn(columnLabel)); + } + + @Override + public Array getArray(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + if (isNull(columnIndex)) return null; + Type type = spanner.getColumnType(columnIndex - 1); + if (type.getCode() != Code.ARRAY) + throw JdbcSqlExceptionFactory.of( + "Column with index " + columnIndex + " does not contain an array", + com.google.rpc.Code.INVALID_ARGUMENT); + JdbcDataType dataType = JdbcDataType.getType(type.getArrayElementType().getCode()); + List elements = dataType.getArrayElements(spanner, columnIndex - 1); + + return JdbcArray.createArray(dataType, elements); + } + + @Override + public Date getDate(int columnIndex, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.toSqlDate(spanner.getDate(columnIndex - 1), cal); + } + + @Override + public Date getDate(String columnLabel, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) + ? null + : JdbcTypeConverter.toSqlDate(spanner.getDate(columnLabel), cal); + } + + @Override + public Time getTime(int columnIndex, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnIndex - 1), cal); + } + + @Override + public Time getTime(String columnLabel, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) + ? null + : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnLabel), cal); + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnIndex) + ? null + : JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(columnIndex - 1), cal); + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { + checkClosedAndValidRow(); + return isNull(columnLabel) + ? null + : JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(columnLabel), cal); + } + + @Override + public URL getURL(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + try { + return isNull(columnIndex) ? null : new URL(spanner.getString(columnIndex - 1)); + } catch (MalformedURLException e) { + throw JdbcSqlExceptionFactory.of( + "Invalid URL: " + spanner.getString(columnIndex - 1), + com.google.rpc.Code.INVALID_ARGUMENT); + } + } + + @Override + public URL getURL(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getURL(findColumn(columnLabel)); + } + + @Override + public int getHoldability() throws SQLException { + checkClosed(); + return CLOSE_CURSORS_AT_COMMIT; + } + + @Override + public boolean isClosed() throws SQLException { + return closed; + } + + @Override + public String getNString(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return getString(columnIndex); + } + + @Override + public String getNString(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getString(columnLabel); + } + + @Override + public Reader getNCharacterStream(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + return getCharacterStream(columnIndex); + } + + @Override + public Reader getNCharacterStream(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + return getCharacterStream(columnLabel); + } + + @Override + public T getObject(int columnIndex, Class type) throws SQLException { + checkClosedAndValidRow(); + return convertObject(getObject(columnIndex), type, spanner.getColumnType(columnIndex - 1)); + } + + @Override + public T getObject(String columnLabel, Class type) throws SQLException { + checkClosedAndValidRow(); + return convertObject(getObject(columnLabel), type, spanner.getColumnType(columnLabel)); + } + + @Override + public Object getObject(int columnIndex, Map> map) throws SQLException { + checkClosedAndValidRow(); + return convertObject(getObject(columnIndex), map, spanner.getColumnType(columnIndex - 1)); + } + + @Override + public Object getObject(String columnLabel, Map> map) throws SQLException { + checkClosedAndValidRow(); + return convertObject(getObject(columnLabel), map, spanner.getColumnType(columnLabel)); + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + byte[] val = getBytes(columnIndex); + return val == null ? null : new JdbcBlob(val); + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + byte[] val = getBytes(columnLabel); + return val == null ? null : new JdbcBlob(val); + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnIndex); + return val == null ? null : new JdbcClob(val); + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnLabel); + return val == null ? null : new JdbcClob(val); + } + + @Override + public NClob getNClob(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnIndex); + return val == null ? null : new JdbcClob(val); + } + + @Override + public NClob getNClob(String columnLabel) throws SQLException { + checkClosedAndValidRow(); + String val = getString(columnLabel); + return val == null ? null : new JdbcClob(val); + } + + @SuppressWarnings("unchecked") + private T convertObject(Object o, Class javaType, Type type) throws SQLException { + return (T) JdbcTypeConverter.convert(o, type, javaType); + } + + private Object convertObject(Object o, Map> map, Type type) throws SQLException { + if (map == null) + throw JdbcSqlExceptionFactory.of("Map may not be null", com.google.rpc.Code.INVALID_ARGUMENT); + if (o == null) return null; + Class javaType = map.get(type.getCode().name()); + if (javaType == null) return o; + return JdbcTypeConverter.convert(o, type, javaType); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java new file mode 100644 index 000000000000..4292c9225515 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -0,0 +1,211 @@ +/* + * Copyright 2019 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.ResultSet; +import com.google.common.base.Preconditions; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; + +/** Implementation of {@link ResultSetMetaData} for Cloud Spanner */ +class JdbcResultSetMetaData extends AbstractJdbcWrapper implements ResultSetMetaData { + /** + * The default column display size for columns with a data type of variable size that is used when + * the actual column size is not known. + */ + private static final int DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS = 50; + + private final ResultSet spannerResultSet; + private final Statement statement; + + JdbcResultSetMetaData(JdbcResultSet jdbcResultSet, Statement statement) { + Preconditions.checkNotNull(jdbcResultSet); + this.spannerResultSet = jdbcResultSet.spanner; + this.statement = statement; + } + + @Override + public boolean isClosed() { + return false; + } + + @Override + public int getColumnCount() throws SQLException { + return spannerResultSet.getColumnCount(); + } + + @Override + public boolean isAutoIncrement(int column) throws SQLException { + return false; + } + + @Override + public boolean isCaseSensitive(int column) throws SQLException { + int type = getColumnType(column); + return type == Types.NVARCHAR || type == Types.BINARY; + } + + @Override + public boolean isSearchable(int column) throws SQLException { + return true; + } + + @Override + public boolean isCurrency(int column) throws SQLException { + return false; + } + + @Override + public int isNullable(int column) throws SQLException { + return columnNullableUnknown; + } + + @Override + public boolean isSigned(int column) throws SQLException { + int type = getColumnType(column); + return type == Types.DOUBLE || type == Types.BIGINT; + } + + @Override + public int getColumnDisplaySize(int column) throws SQLException { + int colType = getColumnType(column); + switch (colType) { + case Types.ARRAY: + return DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS; + case Types.BOOLEAN: + return 5; + case Types.BINARY: + int binaryLength = getPrecision(column); + return binaryLength == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : binaryLength; + case Types.DATE: + return 10; + case Types.DOUBLE: + return 14; + case Types.BIGINT: + return 10; + case Types.NVARCHAR: + int length = getPrecision(column); + return length == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : length; + case Types.TIMESTAMP: + return 16; + default: + return 10; + } + } + + @Override + public String getColumnLabel(int column) throws SQLException { + return spannerResultSet.getType().getStructFields().get(column - 1).getName(); + } + + @Override + public String getColumnName(int column) throws SQLException { + return spannerResultSet.getType().getStructFields().get(column - 1).getName(); + } + + @Override + public String getSchemaName(int column) throws SQLException { + return statement.getConnection().getSchema(); + } + + @Override + public int getPrecision(int column) throws SQLException { + int colType = getColumnType(column); + switch (colType) { + case Types.BOOLEAN: + return 1; + case Types.DATE: + return 10; + case Types.DOUBLE: + return 14; + case Types.BIGINT: + return 10; + case Types.TIMESTAMP: + return 24; + default: + // For column types with variable size, such as text columns, we should return the length + // in characters. We could try to fetch it from INFORMATION_SCHEMA, but that would mean + // parsing the SQL statement client side in order to figure out which column it actually + // is. For now we just return the default column display size. + return DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS; + } + } + + @Override + public int getScale(int column) throws SQLException { + int colType = getColumnType(column); + if (colType == Types.DOUBLE) return 15; + return 0; + } + + @Override + public String getTableName(int column) throws SQLException { + return ""; + } + + @Override + public String getCatalogName(int column) throws SQLException { + return statement.getConnection().getCatalog(); + } + + @Override + public int getColumnType(int column) throws SQLException { + return extractColumnType(spannerResultSet.getColumnType(column - 1)); + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + return spannerResultSet.getColumnType(column - 1).getCode().name(); + } + + @Override + public boolean isReadOnly(int column) throws SQLException { + return false; + } + + @Override + public boolean isWritable(int column) throws SQLException { + return !isReadOnly(column); + } + + @Override + public boolean isDefinitelyWritable(int column) throws SQLException { + return false; + } + + @Override + public String getColumnClassName(int column) throws SQLException { + return getClassName(spannerResultSet.getColumnType(column - 1)); + } + + @Override + public String toString() { + StringBuilder res = new StringBuilder(); + try { + for (int col = 1; col <= getColumnCount(); col++) { + res.append("Col ").append(col).append(": "); + res.append(getColumnName(col)).append(" ").append(getColumnTypeName(col)); + res.append("\n"); + } + } catch (SQLException e) { + return "An error occurred while generating string: " + e.getMessage(); + } + return res.toString(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java new file mode 100644 index 000000000000..c36b8134a8d8 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.rpc.Code; +import java.sql.SQLException; + +/** + * Base interface for all Cloud Spanner {@link SQLException}s. All {@link SQLException}s that are + * thrown by the Cloud Spanner JDBC driver implement this interface. + */ +public interface JdbcSqlException { + + /** @see Throwable#getMessage() */ + String getMessage(); + + /** @see Throwable#getCause() */ + Throwable getCause(); + + /** @see SQLException#getSQLState() */ + String getSQLState(); + + /** Returns the gRPC error code as an int */ + int getErrorCode(); + + /** Returns the corresponding gRPC code for this exception */ + Code getCode(); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java new file mode 100644 index 000000000000..a6fc2bfaa30f --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java @@ -0,0 +1,314 @@ +/* + * Copyright 2019 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.AbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.rpc.Code; +import java.sql.BatchUpdateException; +import java.sql.ClientInfoStatus; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLTimeoutException; +import java.util.Collections; + +/** Factory class for creating {@link SQLException}s for Cloud Spanner */ +public final class JdbcSqlExceptionFactory { + + /** Base {@link SQLException} for Cloud Spanner */ + public static class JdbcSqlExceptionImpl extends SQLException implements JdbcSqlException { + private static final long serialVersionUID = 235381453830069910L; + private final Code code; + + private JdbcSqlExceptionImpl(String message, Code code) { + super(message, null, code.getNumber(), null); + this.code = code; + } + + private JdbcSqlExceptionImpl(String message, Code code, Throwable cause) { + super(message, null, code.getNumber(), cause); + this.code = code; + } + + private JdbcSqlExceptionImpl(SpannerException e) { + super(e.getMessage(), null, e.getCode(), e); + this.code = Code.forNumber(e.getCode()); + } + + private JdbcSqlExceptionImpl(String message, SpannerException e) { + super(message, null, e.getCode(), e); + this.code = Code.forNumber(e.getCode()); + } + + @Override + public Code getCode() { + return code; + } + } + + /** Specific {@link SQLException} that is thrown when a statement times out */ + public static class JdbcSqlTimeoutException extends SQLTimeoutException + implements JdbcSqlException { + private static final long serialVersionUID = 2363793358642102814L; + + private JdbcSqlTimeoutException(String message) { + super(message, "Timed out", Code.DEADLINE_EXCEEDED_VALUE); + } + + @Override + public Code getCode() { + return Code.DEADLINE_EXCEEDED; + } + } + + /** Specific {@link SQLException} that is thrown when setting client info on a connection */ + public static class JdbcSqlClientInfoException extends SQLClientInfoException + implements JdbcSqlException { + private static final long serialVersionUID = 5341238042343668540L; + private final Code code; + + private JdbcSqlClientInfoException(String message, Code code) { + super(message, Collections.emptyMap()); + this.code = code; + } + + @Override + public Code getCode() { + return code; + } + } + + /** Specific {@link SQLException} that is thrown for unsupported methods and values */ + public static class JdbcSqlFeatureNotSupportedException extends SQLFeatureNotSupportedException + implements JdbcSqlException { + private static final long serialVersionUID = 2363793358642102814L; + + private JdbcSqlFeatureNotSupportedException(String message) { + super(message, "not supported", Code.UNIMPLEMENTED_VALUE); + } + + @Override + public Code getCode() { + return Code.UNIMPLEMENTED; + } + } + + /** + * Specific {@link SQLException} that is thrown when a {@link SpannerBatchUpdateException} occurs. + */ + public static class JdbcSqlBatchUpdateException extends BatchUpdateException + implements JdbcSqlException { + private static final long serialVersionUID = 8894995110837971444L; + private final Code code; + + private JdbcSqlBatchUpdateException(int[] updateCounts, SpannerBatchUpdateException cause) { + super(cause.getMessage(), updateCounts, cause); + this.code = Code.forNumber(cause.getCode()); + } + + @Override + public Code getCode() { + return code; + } + } + + /** + * Specific {@link SQLException} that is thrown when a transaction was aborted and could not be + * successfully retried. + */ + public static class JdbcAbortedException extends JdbcSqlExceptionImpl { + private JdbcAbortedException(AbortedException cause) { + super(cause); + } + + private JdbcAbortedException(String message) { + super(message, Code.ABORTED); + } + + private JdbcAbortedException(String message, AbortedException cause) { + super(message, cause); + } + + @Override + public synchronized AbortedException getCause() { + return (AbortedException) super.getCause(); + } + } + + /** + * Specific {@link SQLException} that is thrown when a transaction was aborted and could not be + * retried due to a concurrent modification. + */ + public static class JdbcAbortedDueToConcurrentModificationException extends JdbcAbortedException { + private JdbcAbortedDueToConcurrentModificationException( + AbortedDueToConcurrentModificationException cause) { + super(cause); + } + + private JdbcAbortedDueToConcurrentModificationException( + String message, AbortedDueToConcurrentModificationException cause) { + super(message, cause); + } + + @Override + public synchronized AbortedDueToConcurrentModificationException getCause() { + return (AbortedDueToConcurrentModificationException) super.getCause(); + } + + public SpannerException getDatabaseErrorDuringRetry() { + return getCause().getDatabaseErrorDuringRetry(); + } + } + + /** Creates a {@link JdbcSqlException} from the given {@link SpannerException}. */ + static SQLException of(SpannerException e) { + switch (e.getErrorCode()) { + case ABORTED: + if (e instanceof AbortedDueToConcurrentModificationException) { + return new JdbcAbortedDueToConcurrentModificationException( + (AbortedDueToConcurrentModificationException) e); + } else if (e instanceof AbortedException) { + return new JdbcAbortedException((AbortedException) e); + } + case DEADLINE_EXCEEDED: + return new JdbcSqlTimeoutException(e.getMessage()); + case ALREADY_EXISTS: + case CANCELLED: + case DATA_LOSS: + case FAILED_PRECONDITION: + case INTERNAL: + case INVALID_ARGUMENT: + case NOT_FOUND: + case OUT_OF_RANGE: + case PERMISSION_DENIED: + case RESOURCE_EXHAUSTED: + case UNAUTHENTICATED: + case UNAVAILABLE: + case UNIMPLEMENTED: + case UNKNOWN: + default: + } + return new JdbcSqlExceptionImpl(e); + } + + /** Creates a {@link JdbcSqlException} with the given message and error code. */ + static SQLException of(String message, Code code) { + switch (code) { + case ABORTED: + return new JdbcAbortedException(code.name() + ": " + message); + case DEADLINE_EXCEEDED: + return new JdbcSqlTimeoutException(code.name() + ": " + message); + case ALREADY_EXISTS: + case CANCELLED: + case DATA_LOSS: + case FAILED_PRECONDITION: + case INTERNAL: + case INVALID_ARGUMENT: + case NOT_FOUND: + case OUT_OF_RANGE: + case PERMISSION_DENIED: + case RESOURCE_EXHAUSTED: + case UNAUTHENTICATED: + case UNAVAILABLE: + case UNIMPLEMENTED: + case UNKNOWN: + default: + } + return new JdbcSqlExceptionImpl(code.name() + ": " + message, code); + } + + /** Creates a {@link JdbcSqlException} with the given message and cause. */ + static SQLException of(String message, SpannerException e) { + switch (e.getErrorCode()) { + case ABORTED: + if (e instanceof AbortedDueToConcurrentModificationException) { + return new JdbcAbortedDueToConcurrentModificationException( + message, (AbortedDueToConcurrentModificationException) e); + } else if (e instanceof AbortedException) { + return new JdbcAbortedException(message, (AbortedException) e); + } + case DEADLINE_EXCEEDED: + return new JdbcSqlTimeoutException(e.getErrorCode().name() + ": " + message); + case ALREADY_EXISTS: + case CANCELLED: + case DATA_LOSS: + case FAILED_PRECONDITION: + case INTERNAL: + case INVALID_ARGUMENT: + case NOT_FOUND: + case OUT_OF_RANGE: + case PERMISSION_DENIED: + case RESOURCE_EXHAUSTED: + case UNAUTHENTICATED: + case UNAVAILABLE: + case UNIMPLEMENTED: + case UNKNOWN: + default: + } + return new JdbcSqlExceptionImpl(e.getErrorCode().name() + ": " + message, e); + } + + /** Creates a {@link JdbcSqlException} with the given message, error code and cause. */ + static SQLException of(String message, Code code, Throwable cause) { + switch (code) { + case ABORTED: + if (cause instanceof AbortedDueToConcurrentModificationException) { + return new JdbcAbortedDueToConcurrentModificationException( + message, (AbortedDueToConcurrentModificationException) cause); + } else if (cause instanceof AbortedException) { + return new JdbcAbortedException(message, (AbortedException) cause); + } + case DEADLINE_EXCEEDED: + return new JdbcSqlTimeoutException(code.name() + ": " + message); + case ALREADY_EXISTS: + case CANCELLED: + case DATA_LOSS: + case FAILED_PRECONDITION: + case INTERNAL: + case INVALID_ARGUMENT: + case NOT_FOUND: + case OUT_OF_RANGE: + case PERMISSION_DENIED: + case RESOURCE_EXHAUSTED: + case UNAUTHENTICATED: + case UNAVAILABLE: + case UNIMPLEMENTED: + case UNKNOWN: + default: + } + return new JdbcSqlExceptionImpl(code.name() + ": " + message, code, cause); + } + + /** Creates a {@link JdbcSqlException} for unsupported methods/values. */ + static SQLFeatureNotSupportedException unsupported(String message) { + return new JdbcSqlFeatureNotSupportedException(message); + } + + /** Creates a {@link JdbcSqlException} for client info exceptions. */ + static SQLClientInfoException clientInfoException(String message, Code code) { + return new JdbcSqlClientInfoException(code.name() + ": " + message, code); + } + + /** Creates a {@link JdbcSqlException} for batch update exceptions. */ + static BatchUpdateException batchException( + int[] updateCounts, SpannerBatchUpdateException cause) { + return new JdbcSqlBatchUpdateException(updateCounts, cause); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java new file mode 100644 index 000000000000..54488c6ea3cc --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -0,0 +1,364 @@ +/* + * Copyright 2019 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; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.rpc.Code; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** Implementation of {@link java.sql.Statement} for Google Cloud Spanner. */ +class JdbcStatement extends AbstractJdbcStatement { + enum BatchType { + NONE, + DML, + DDL; + } + + private ResultSet currentResultSet; + private long currentUpdateCount; + private int fetchSize; + private BatchType currentBatchType = BatchType.NONE; + final List batchedStatements = new ArrayList<>(); + + JdbcStatement(JdbcConnection connection) { + super(connection); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + checkClosed(); + return executeQuery(Statement.of(sql)); + } + + /** + * @see java.sql.Statement#executeUpdate(String) + *

This method allows both DML and DDL statements to be executed. It assumes that the user + * knows what kind of statement is being executed, and the method will therefore return 0 for + * both DML statements that changed 0 rows as well as for all DDL statements. + */ + @Override + public int executeUpdate(String sql) throws SQLException { + checkClosed(); + Statement statement = Statement.of(sql); + StatementResult result = execute(statement); + switch (result.getResultType()) { + case RESULT_SET: + throw JdbcSqlExceptionFactory.of( + "The statement is not an update or DDL statement", Code.INVALID_ARGUMENT); + case UPDATE_COUNT: + if (result.getUpdateCount() > Integer.MAX_VALUE) { + throw JdbcSqlExceptionFactory.of( + "update count too large: " + result.getUpdateCount(), Code.OUT_OF_RANGE); + } + return result.getUpdateCount().intValue(); + case NO_RESULT: + return 0; + default: + throw JdbcSqlExceptionFactory.of( + "unknown result: " + result.getResultType(), Code.FAILED_PRECONDITION); + } + } + + @Override + public boolean execute(String sql) throws SQLException { + checkClosed(); + return executeStatement(Statement.of(sql)); + } + + boolean executeStatement(Statement statement) throws SQLException { + StatementResult result = execute(statement); + switch (result.getResultType()) { + case RESULT_SET: + currentResultSet = JdbcResultSet.of(this, result.getResultSet()); + currentUpdateCount = JdbcConstants.STATEMENT_RESULT_SET; + return true; + case UPDATE_COUNT: + currentResultSet = null; + currentUpdateCount = result.getUpdateCount(); + return false; + case NO_RESULT: + currentResultSet = null; + currentUpdateCount = JdbcConstants.STATEMENT_NO_RESULT; + return false; + default: + throw JdbcSqlExceptionFactory.of( + "unknown result: " + result.getResultType(), Code.FAILED_PRECONDITION); + } + } + + @Override + public ResultSet getResultSet() throws SQLException { + checkClosed(); + return currentResultSet; + } + + /** + * Returns the update count of the last update statement. Will return {@link + * JdbcConstants#STATEMENT_RESULT_SET} if the last statement returned a {@link ResultSet} and will + * return {@link JdbcConstants#STATEMENT_NO_RESULT} if the last statement did not have any return + * value, such as for example DDL statements. + */ + @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; + } + + @Override + public boolean getMoreResults() throws SQLException { + checkClosed(); + return getMoreResults(CLOSE_CURRENT_RESULT); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + checkClosed(); + if (currentResultSet != null + && !currentResultSet.isClosed() + && (current == CLOSE_CURRENT_RESULT || current == CLOSE_ALL_RESULTS)) { + currentResultSet.close(); + } + currentResultSet = null; + currentUpdateCount = -1L; + return false; + } + + /** This value is set as the value for {@link Options#prefetchChunks(int)} */ + @Override + public void setFetchSize(int rows) throws SQLException { + checkClosed(); + this.fetchSize = rows; + } + + /** This value is set as the value for {@link Options#prefetchChunks(int)} */ + @Override + public int getFetchSize() throws SQLException { + checkClosed(); + return fetchSize; + } + + /** + * Determine the batch type (DML/DDL) based on the sql statement. + * + * @throws SQLException if the sql statement is not allowed for batching. + */ + private BatchType determineStatementBatchType(String sql) throws SQLException { + String sqlWithoutComments = StatementParser.removeCommentsAndTrim(sql); + if (StatementParser.INSTANCE.isDdlStatement(sqlWithoutComments)) { + return BatchType.DDL; + } else if (StatementParser.INSTANCE.isUpdateStatement(sqlWithoutComments)) { + return BatchType.DML; + } + throw JdbcSqlExceptionFactory.of( + "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching.", + Code.INVALID_ARGUMENT); + } + + /** + * Check that the sql statement is of the same type as the current batch on this statement. If + * there is no active batch on this statement, a batch will be started with the type that is + * determined from the sql statement (DML/DDL). + * + * @throws SQLException if the sql statement is of a different type than the already active batch + * on this statement, if the statement is not allowed for batching (i.e. it is a query or a + * client side statement) or if the connection of this statement has an active batch. + */ + void checkAndSetBatchType(String sql) throws SQLException { + checkConnectionHasNoActiveBatch(); + BatchType type = determineStatementBatchType(sql); + if (this.currentBatchType == BatchType.NONE) { + this.currentBatchType = type; + } else if (this.currentBatchType != type) { + throw JdbcSqlExceptionFactory.of( + "Mixing DML and DDL statements in a batch is not allowed.", Code.INVALID_ARGUMENT); + } + } + + private void checkConnectionHasNoActiveBatch() throws SQLException { + if (getConnection().getSpannerConnection().isDdlBatchActive() + || getConnection().getSpannerConnection().isDmlBatchActive()) { + throw JdbcSqlExceptionFactory.of( + "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection.", + Code.FAILED_PRECONDITION); + } + } + + @Override + public void addBatch(String sql) throws SQLException { + checkClosed(); + checkAndSetBatchType(sql); + batchedStatements.add(Statement.of(sql)); + } + + @Override + public void clearBatch() throws SQLException { + checkClosed(); + checkConnectionHasNoActiveBatch(); + batchedStatements.clear(); + this.currentBatchType = BatchType.NONE; + } + + @Override + public int[] executeBatch() throws SQLException { + checkClosed(); + checkConnectionHasNoActiveBatch(); + try { + switch (this.currentBatchType) { + case DML: + try { + long[] updateCounts = + getConnection().getSpannerConnection().executeBatchUpdate(batchedStatements); + int[] res = convertUpdateCounts(updateCounts); + return res; + } catch (SpannerBatchUpdateException e) { + int[] updateCounts = convertUpdateCounts(e.getUpdateCounts()); + throw JdbcSqlExceptionFactory.batchException(updateCounts, e); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + case DDL: + try { + getConnection().getSpannerConnection().startBatchDdl(); + for (Statement statement : batchedStatements) { + execute(statement); + } + getConnection().getSpannerConnection().runBatch(); + int[] res = new int[batchedStatements.size()]; + Arrays.fill(res, java.sql.Statement.SUCCESS_NO_INFO); + return res; + } catch (SpannerBatchUpdateException e) { + int[] res = new int[batchedStatements.size()]; + Arrays.fill(res, java.sql.Statement.EXECUTE_FAILED); + convertUpdateCountsToSuccessNoInfo(e.getUpdateCounts(), res); + throw JdbcSqlExceptionFactory.batchException(res, e); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + case NONE: + // There is no batch on this statement, this is a no-op. + return new int[0]; + default: + throw JdbcSqlExceptionFactory.unsupported( + String.format("Unknown batch type: %s", this.currentBatchType.name())); + } + } finally { + batchedStatements.clear(); + this.currentBatchType = BatchType.NONE; + } + } + + @VisibleForTesting + 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]; + } + return res; + } + + @VisibleForTesting + void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, int[] res) throws SQLException { + Preconditions.checkNotNull(updateCounts); + Preconditions.checkNotNull(res); + Preconditions.checkArgument(res.length >= 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); + } + if (updateCounts[index] > 0L) { + res[index] = java.sql.Statement.SUCCESS_NO_INFO; + } else { + res[index] = java.sql.Statement.EXECUTE_FAILED; + } + } + } + + @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); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + checkClosed(); + return executeUpdate(sql); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + checkClosed(); + return executeUpdate(sql); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + checkClosed(); + return executeUpdate(sql); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + checkClosed(); + return execute(sql); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + checkClosed(); + return execute(sql); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + checkClosed(); + return execute(sql); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java new file mode 100644 index 000000000000..f8b9701c4155 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -0,0 +1,274 @@ +/* + * Copyright 2019 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.ByteArray; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.Code; +import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.SQLException; +import java.sql.Time; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** Convenience class for converting values between Java, JDBC and Cloud Spanner. */ +class JdbcTypeConverter { + + /** + * Converts the given value from the Google {@link Type} to the Java {@link Class} type. + * + * @param value The value to convert + * @param type The type in the database + * @param targetType The java class target type to convert to + * @return The converted value + * @throws CloudSpannerSQLException Thrown if the given value cannot be converted to the specified + * type + */ + static Object convert(Object value, Type type, Class targetType) throws SQLException { + Preconditions.checkNotNull(type, "type may not be null"); + Preconditions.checkNotNull(targetType, "targetType may not be null"); + if (value == null) return null; + if (targetType.equals(String.class)) return value.toString(); + + try { + if (targetType.equals(Boolean.class)) { + if (type.getCode() == Code.BOOL) return value; + if (type.getCode() == Code.INT64) return Boolean.valueOf((Long) value != 0); + if (type.getCode() == Code.FLOAT64) return Boolean.valueOf((Double) value != 0d); + if (type.getCode() == Code.STRING) return Boolean.valueOf((String) value); + } + if (targetType.equals(BigDecimal.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; + if (type.getCode() == Code.INT64) return BigDecimal.valueOf((Long) value); + if (type.getCode() == Code.FLOAT64) return BigDecimal.valueOf((Double) value); + if (type.getCode() == Code.STRING) return new BigDecimal((String) value); + } + if (targetType.equals(Long.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? 1L : 0L; + if (type.getCode() == Code.INT64) return value; + if (type.getCode() == Code.FLOAT64) return ((Double) value).longValue(); + if (type.getCode() == Code.STRING) return Long.valueOf((String) value); + } + if (targetType.equals(Integer.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; + if (type.getCode() == Code.INT64) return ((Long) value).intValue(); + if (type.getCode() == Code.FLOAT64) return ((Double) value).intValue(); + if (type.getCode() == Code.STRING) return Integer.valueOf((String) value); + } + if (targetType.equals(BigInteger.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; + if (type.getCode() == Code.INT64) return BigInteger.valueOf((Long) value); + if (type.getCode() == Code.FLOAT64) return BigInteger.valueOf(((Double) value).longValue()); + if (type.getCode() == Code.STRING) return new BigInteger((String) value); + } + if (targetType.equals(Float.class)) { + if (type.getCode() == Code.BOOL) + return (Boolean) value ? Float.valueOf(1f) : Float.valueOf(0f); + if (type.getCode() == Code.INT64) return ((Long) value).floatValue(); + if (type.getCode() == Code.FLOAT64) return ((Double) value).floatValue(); + if (type.getCode() == Code.STRING) return Float.valueOf((String) value); + } + if (targetType.equals(Double.class)) { + if (type.getCode() == Code.BOOL) + return (Boolean) value ? Double.valueOf(1d) : Double.valueOf(0d); + if (type.getCode() == Code.INT64) return ((Long) value).doubleValue(); + if (type.getCode() == Code.FLOAT64) return value; + if (type.getCode() == Code.STRING) return Double.valueOf((String) value); + } + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Cannot convert " + value + " to " + targetType.getName(), + com.google.rpc.Code.INVALID_ARGUMENT, + e); + } + + throw JdbcSqlExceptionFactory.of( + "Cannot convert " + type.getCode().name() + " to " + targetType.getName(), + com.google.rpc.Code.INVALID_ARGUMENT); + } + + @SuppressWarnings("deprecation") + static Date toGoogleDate(java.sql.Date date) { + return date == null + ? null + : Date.fromYearMonthDay(date.getYear() + 1900, date.getMonth() + 1, date.getDate()); + } + + static Date toGoogleDate(java.sql.Time date) { + return Date.fromYearMonthDay(1970, 1, 1); + } + + @SuppressWarnings("deprecation") + static Date toGoogleDate(java.sql.Timestamp date) { + return date == null + ? null + : Date.fromYearMonthDay(date.getYear() + 1900, date.getMonth() + 1, date.getDate()); + } + + static List toGoogleDates(java.sql.Date[] dates) { + List res = new ArrayList<>(dates.length); + for (int index = 0; index < dates.length; index++) res.add(toGoogleDate(dates[index])); + return res; + } + + static java.sql.Date toSqlDate(Date date) { + return toSqlDate(date, Calendar.getInstance()); + } + + static java.sql.Date toSqlDate(Date date, Calendar cal) { + if (date != null) { + cal.set(date.getYear(), date.getMonth() - 1, date.getDayOfMonth(), 0, 0, 0); + cal.clear(Calendar.MILLISECOND); + return new java.sql.Date(cal.getTimeInMillis()); + } + return null; + } + + static List toSqlDates(List dates) { + List res = new ArrayList<>(dates.size()); + for (Date date : dates) res.add(toSqlDate(date)); + return res; + } + + static java.sql.Timestamp toSqlTimestamp(Timestamp ts) { + return ts == null ? null : ts.toSqlTimestamp(); + } + + static java.sql.Timestamp getAsSqlTimestamp(Timestamp ts, Calendar cal) { + return ts == null ? null : getTimestampInCalendar(ts.toSqlTimestamp(), cal); + } + + static java.sql.Timestamp getTimestampInCalendar(java.sql.Timestamp sqlTs, Calendar cal) { + return getOrSetTimestampInCalendar(sqlTs, cal, GetOrSetTimestampInCalendar.GET); + } + + static java.sql.Timestamp setTimestampInCalendar(java.sql.Timestamp sqlTs, Calendar cal) { + return getOrSetTimestampInCalendar(sqlTs, cal, GetOrSetTimestampInCalendar.SET); + } + + private enum GetOrSetTimestampInCalendar { + GET, + SET; + } + + private static java.sql.Timestamp getOrSetTimestampInCalendar( + java.sql.Timestamp sqlTs, Calendar cal, GetOrSetTimestampInCalendar getOrSet) { + if (sqlTs != null) { + // Get a calendar in the requested timezone + Calendar newCal = Calendar.getInstance(cal.getTimeZone()); + // set the millisecond time on this calendar from the timestamp + newCal.setTimeInMillis(sqlTs.getTime()); + newCal.set(Calendar.MILLISECOND, 0); + // then shift the time of the calendar by the difference between UTC and the timezone of the + // given calendar + int offset = newCal.getTimeZone().getOffset(newCal.getTimeInMillis()); + newCal.add( + Calendar.MILLISECOND, getOrSet == GetOrSetTimestampInCalendar.GET ? offset : -offset); + // then use that to create a sql timestamp + java.sql.Timestamp res = new java.sql.Timestamp(newCal.getTimeInMillis()); + // set the nanosecond value that will also set the millisecond value of the timestamp + // as the nanosecond value contains all fraction of a second information + res.setNanos(sqlTs.getNanos()); + return res; + } + return null; + } + + static List toSqlTimestamps(List timestamps) { + List res = new ArrayList<>(timestamps.size()); + for (Timestamp timestamp : timestamps) { + res.add(toSqlTimestamp(timestamp)); + } + return res; + } + + static Timestamp toGoogleTimestamp(java.sql.Date ts) { + if (ts != null) { + long milliseconds = ts.getTime(); + long seconds = milliseconds / 1000l; + long nanos = (milliseconds - (seconds * 1000)) * 1000000; + return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, (int) nanos); + } + return null; + } + + static Timestamp toGoogleTimestamp(java.sql.Time ts) { + if (ts != null) { + long milliseconds = ts.getTime(); + long seconds = milliseconds / 1000l; + long nanos = (milliseconds - (seconds * 1000)) * 1000000; + return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, (int) nanos); + } + return null; + } + + static Timestamp toGoogleTimestamp(java.sql.Timestamp ts) { + if (ts != null) { + long milliseconds = ts.getTime(); + long seconds = milliseconds / 1000l; + int nanos = ts.getNanos(); + return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, nanos); + } + return null; + } + + static List toGoogleTimestamps(java.sql.Timestamp[] timestamps) { + List res = new ArrayList<>(timestamps.length); + for (int index = 0; index < timestamps.length; index++) { + res.add(toGoogleTimestamp(timestamps[index])); + } + return res; + } + + static Time toSqlTime(Timestamp ts) { + return toSqlTime(ts, Calendar.getInstance()); + } + + static Time toSqlTime(Timestamp ts, Calendar cal) { + if (ts != null) { + cal.set(1970, 0, 1, 0, 0, 0); + cal.clear(Calendar.MILLISECOND); + cal.setTimeInMillis( + ts.getSeconds() * 1000 + + TimeUnit.MILLISECONDS.convert(ts.getNanos(), TimeUnit.NANOSECONDS)); + return new Time(cal.getTimeInMillis()); + } + return null; + } + + static List toGoogleBytes(byte[][] bytes) { + List res = new ArrayList<>(bytes.length); + for (int index = 0; index < bytes.length; index++) { + res.add(bytes[index] == null ? null : ByteArray.copyFrom(bytes[index])); + } + return res; + } + + static List toJavaByteArrays(List bytes) { + List res = new ArrayList<>(bytes.size()); + for (ByteArray ba : bytes) { + res.add(ba == null ? null : ba.toByteArray()); + } + return res; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java new file mode 100644 index 000000000000..291665867409 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java @@ -0,0 +1,261 @@ +/* + * Copyright 2019 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.api.client.util.DateTime; +import com.google.api.client.util.DateTime.SecondsAndNanos; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.protobuf.Duration; +import com.google.protobuf.util.Durations; +import java.util.concurrent.TimeUnit; + +/** + * Util class for parsing and converting ReadOnlyStaleness values to/from strings. This util is used + * to parse client side statements and values for read only staleness for read-only transactions on + * Cloud Spanner. + */ +class ReadOnlyStalenessUtil { + /** + * Parses an RFC3339 date/time value with nanosecond precision and returns this as a {@link + * Timestamp}. + */ + static Timestamp parseRfc3339(String str) throws SpannerException { + try { + SecondsAndNanos secondsAndNanos = DateTime.parseRfc3339ToSecondsAndNanos(str); + return Timestamp.ofTimeSecondsAndNanos( + secondsAndNanos.getSeconds(), secondsAndNanos.getNanos()); + } catch (NumberFormatException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, String.format("Invalid timestamp: %s", str), e); + } + } + + /** The abbreviations for time units that may be used for client side statements. */ + enum TimeUnitAbbreviation { + NANOSECONDS("ns", TimeUnit.NANOSECONDS), + MICROSECONDS("us", TimeUnit.MICROSECONDS), + MILLISECONDS("ms", TimeUnit.MILLISECONDS), + SECONDS("s", TimeUnit.SECONDS); + + private final String abbreviation; + private final TimeUnit unit; + + private TimeUnitAbbreviation(String abbreviation, TimeUnit unit) { + this.abbreviation = abbreviation; + this.unit = unit; + } + + String getAbbreviation() { + return abbreviation; + } + + TimeUnit getUnit() { + return unit; + } + } + + /** Get the abbreviation for the given {@link TimeUnit}. */ + static String getTimeUnitAbbreviation(TimeUnit unit) { + for (TimeUnitAbbreviation abb : TimeUnitAbbreviation.values()) { + if (abb.unit == unit) return abb.abbreviation; + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "Invalid option for time unit: " + unit); + } + + /** Get the {@link TimeUnit} corresponding with the given abbreviation. */ + static TimeUnit parseTimeUnit(String unit) { + for (TimeUnitAbbreviation abb : TimeUnitAbbreviation.values()) { + if (abb.abbreviation.equalsIgnoreCase(unit)) return abb.unit; + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "Invalid option for time unit: " + unit); + } + + /** + * Internal interface that is used to generalize getting a time duration from Cloud Spanner + * read-only staleness settings. + */ + static interface DurationValueGetter { + long getDuration(TimeUnit unit); + + boolean hasDuration(); + } + + static final class GetExactStaleness implements DurationValueGetter { + private final TimestampBound staleness; + + public GetExactStaleness(TimestampBound staleness) { + this.staleness = staleness; + } + + @Override + public long getDuration(TimeUnit unit) { + return staleness.getExactStaleness(unit); + } + + @Override + public boolean hasDuration() { + return staleness.getMode() == Mode.EXACT_STALENESS; + } + } + + static final class MaxStalenessGetter implements DurationValueGetter { + private final TimestampBound staleness; + + public MaxStalenessGetter(TimestampBound staleness) { + this.staleness = staleness; + } + + @Override + public long getDuration(TimeUnit unit) { + return staleness.getMaxStaleness(unit); + } + + @Override + public boolean hasDuration() { + return staleness.getMode() == Mode.MAX_STALENESS; + } + } + + static final class DurationGetter implements DurationValueGetter { + private final Duration duration; + + public DurationGetter(Duration duration) { + this.duration = duration; + } + + @Override + public long getDuration(TimeUnit unit) { + return durationToUnits(duration, unit); + } + + @Override + public boolean hasDuration() { + return duration.getNanos() > 0 || duration.getSeconds() > 0L; + } + } + + /** + * Converts a {@link TimestampBound} to a human readable string representation. + * + * @param staleness The staleness to convert + * @return a human readable representation of the staleness. + */ + static String timestampBoundToString(TimestampBound staleness) { + switch (staleness.getMode()) { + case STRONG: + return "STRONG"; + case READ_TIMESTAMP: + return "READ_TIMESTAMP " + staleness.getReadTimestamp().toString(); + case MIN_READ_TIMESTAMP: + return "MIN_READ_TIMESTAMP " + staleness.getMinReadTimestamp().toString(); + case EXACT_STALENESS: + return "EXACT_STALENESS " + durationToString(new GetExactStaleness(staleness)); + case MAX_STALENESS: + return "MAX_STALENESS " + durationToString(new MaxStalenessGetter(staleness)); + default: + throw new IllegalStateException("Unknown mode: " + staleness.getMode()); + } + } + + /** The {@link TimeUnit}s that are supported for timeout and staleness durations. */ + static final TimeUnit[] SUPPORTED_UNITS = + new TimeUnit[] { + TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS + }; + + /** + * Converts a duration value to a human readable string. The method will search for the most + * appropriate {@link TimeUnit} to use to represent the value. + * + * @param function The function that should be called to get the duration in a specific {@link + * TimeUnit}. + * @return a human readable value of the duration. + */ + static String durationToString(DurationValueGetter function) { + TimeUnit unit = getAppropriateTimeUnit(function); + return String.valueOf(function.getDuration(unit)) + getTimeUnitAbbreviation(unit); + } + + /** + * Calculates the most appropriate {@link TimeUnit} to use to represent the duration that is + * returned by the given function. The most appropriate {@link TimeUnit} is the unit with the + * least precision that still retains all information of the given input. + * + * @param durationGetter The function that will return the duration in different {@link + * TimeUnit}s. + * @return the most appropriate {@link TimeUnit} to represent the duration. + */ + static TimeUnit getAppropriateTimeUnit(DurationValueGetter durationGetter) { + int index = 0; + if (durationGetter.hasDuration()) { + for (TimeUnit unit : SUPPORTED_UNITS) { + long duration = durationGetter.getDuration(unit); + if (index + 1 < SUPPORTED_UNITS.length) { + if (duration > 0L + && duration * 1000 == durationGetter.getDuration(SUPPORTED_UNITS[index + 1])) { + return unit; + } + } else { + // last unit, we have to use this one + return unit; + } + index++; + } + throw new IllegalStateException("Unsupported duration"); + } + return TimeUnit.NANOSECONDS; + } + + /** Converts a value into a duration using the specified {@link TimeUnit}. */ + static Duration createDuration(long num, TimeUnit units) { + switch (units) { + case NANOSECONDS: + return Durations.fromNanos(num); + case MICROSECONDS: + return Durations.fromMicros(num); + case MILLISECONDS: + return Durations.fromMillis(num); + case SECONDS: + return Durations.fromSeconds(num); + default: + return Durations.fromMillis(units.toMillis(num)); + } + } + + /** Converts a duration to a number using the specified {@link TimeUnit}. */ + static long durationToUnits(Duration duration, TimeUnit units) { + switch (units) { + case NANOSECONDS: + return Durations.toNanos(duration); + case MICROSECONDS: + return Durations.toMicros(duration); + case MILLISECONDS: + return Durations.toMillis(duration); + case SECONDS: + return Durations.toSeconds(duration); + default: + throw new IllegalArgumentException(); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java new file mode 100644 index 000000000000..e0c408970032 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java @@ -0,0 +1,178 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ReadContext; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; + +/** + * Transaction that is used when a {@link Connection} is in read-only mode or when the transaction + * mode is set to read-only. This transaction can only be used to execute queries. + */ +class ReadOnlyTransaction extends AbstractMultiUseTransaction { + private final DatabaseClient dbClient; + private final TimestampBound readOnlyStaleness; + private com.google.cloud.spanner.ReadOnlyTransaction transaction; + private UnitOfWorkState state = UnitOfWorkState.STARTED; + + static class Builder extends AbstractBaseUnitOfWork.Builder { + private DatabaseClient dbClient; + private TimestampBound readOnlyStaleness; + + private Builder() {} + + Builder setDatabaseClient(DatabaseClient client) { + Preconditions.checkNotNull(client); + this.dbClient = client; + return this; + } + + Builder setReadOnlyStaleness(TimestampBound staleness) { + Preconditions.checkNotNull(staleness); + this.readOnlyStaleness = staleness; + return this; + } + + @Override + ReadOnlyTransaction build() { + Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); + Preconditions.checkState(readOnlyStaleness != null, "No ReadOnlyStaleness specified"); + return new ReadOnlyTransaction(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private ReadOnlyTransaction(Builder builder) { + super(builder); + this.dbClient = builder.dbClient; + this.readOnlyStaleness = builder.readOnlyStaleness; + } + + @Override + public UnitOfWorkState getState() { + return this.state; + } + + @Override + public boolean isReadOnly() { + return true; + } + + @Override + void checkValidTransaction() { + if (transaction == null) { + transaction = dbClient.readOnlyTransaction(readOnlyStaleness); + } + } + + @Override + ReadContext getReadContext() { + ConnectionPreconditions.checkState(transaction != null, "Missing read-only transaction"); + return transaction; + } + + @Override + public Timestamp getReadTimestamp() { + ConnectionPreconditions.checkState( + transaction != null, "There is no read timestamp available for this transaction."); + ConnectionPreconditions.checkState( + state != UnitOfWorkState.ROLLED_BACK, "This transaction was rolled back"); + return transaction.getReadTimestamp(); + } + + @Override + public Timestamp getReadTimestampOrNull() { + if (transaction != null && state != UnitOfWorkState.ROLLED_BACK) { + try { + return transaction.getReadTimestamp(); + } catch (SpannerException e) { + // ignore + } + } + return null; + } + + @Override + public Timestamp getCommitTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "There is no commit timestamp available for this transaction."); + } + + @Override + public Timestamp getCommitTimestampOrNull() { + return null; + } + + @Override + public void executeDdl(ParsedStatement ddl) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "DDL statements are not allowed for read-only transactions"); + } + + @Override + public long executeUpdate(ParsedStatement update) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "Update statements are not allowed for read-only transactions"); + } + + @Override + public long[] executeBatchUpdate(Iterable updates) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Batch updates are not allowed for read-only transactions."); + } + + @Override + public void write(Mutation mutation) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Mutations are not allowed for read-only transactions"); + } + + @Override + public void write(Iterable mutations) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Mutations are not allowed for read-only transactions"); + } + + @Override + public void commit() { + if (this.transaction != null) { + this.transaction.close(); + } + this.state = UnitOfWorkState.COMMITTED; + } + + @Override + public void rollback() { + if (this.transaction != null) { + this.transaction.close(); + } + this.state = UnitOfWorkState.ROLLED_BACK; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java new file mode 100644 index 000000000000..a9fcbc53883b --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java @@ -0,0 +1,762 @@ +/* + * Copyright 2019 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 com.google.common.base.Preconditions.checkNotNull; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.TransactionRetryListener.RetryResult; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Transaction that is used when a {@link Connection} is normal read/write mode (i.e. not autocommit + * and not read-only). These transactions can be automatically retried if an {@link + * AbortedException} is thrown. The transaction will keep track of a running checksum of all {@link + * ResultSet}s that have been returned, and the update counts returned by any DML statement executed + * during the transaction. As long as these checksums and update counts are equal for both the + * original transaction and the retried transaction, the retry can safely be assumed to have the + * exact same results as the original transaction. + */ +class ReadWriteTransaction extends AbstractMultiUseTransaction { + private static final Logger logger = Logger.getLogger(ReadWriteTransaction.class.getName()); + private static final AtomicLong ID_GENERATOR = new AtomicLong(); + private static final String MAX_INTERNAL_RETRIES_EXCEEDED = + "Internal transaction retry maximum exceeded"; + private static final int MAX_INTERNAL_RETRIES = 50; + private final long transactionId; + private final DatabaseClient dbClient; + private TransactionManager txManager; + private final boolean retryAbortsInternally; + private int transactionRetryAttempts; + private int successfulRetries; + private final List transactionRetryListeners; + private volatile TransactionContext txContext; + private volatile UnitOfWorkState state = UnitOfWorkState.STARTED; + private boolean timedOutOrCancelled = false; + private final List statements = new ArrayList<>(); + private final List mutations = new ArrayList<>(); + private Timestamp transactionStarted; + + static class Builder extends AbstractMultiUseTransaction.Builder { + private DatabaseClient dbClient; + private Boolean retryAbortsInternally; + private List transactionRetryListeners; + + private Builder() {} + + Builder setDatabaseClient(DatabaseClient client) { + Preconditions.checkNotNull(client); + this.dbClient = client; + return this; + } + + Builder setRetryAbortsInternally(boolean retryAbortsInternally) { + this.retryAbortsInternally = retryAbortsInternally; + return this; + } + + Builder setTransactionRetryListeners(List listeners) { + Preconditions.checkNotNull(listeners); + this.transactionRetryListeners = listeners; + return this; + } + + @Override + ReadWriteTransaction build() { + Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); + Preconditions.checkState( + retryAbortsInternally != null, "RetryAbortsInternally is not specified"); + Preconditions.checkState( + transactionRetryListeners != null, "TransactionRetryListeners are not specified"); + return new ReadWriteTransaction(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private ReadWriteTransaction(Builder builder) { + super(builder); + this.transactionId = ID_GENERATOR.incrementAndGet(); + this.dbClient = builder.dbClient; + this.retryAbortsInternally = builder.retryAbortsInternally; + this.transactionRetryListeners = builder.transactionRetryListeners; + this.txManager = dbClient.transactionManager(); + } + + @Override + public String toString() { + return new StringBuilder() + .append("ReadWriteTransaction - ID: ") + .append(transactionId) + .append("; Status: ") + .append(internalGetStateName()) + .append("; Started: ") + .append(internalGetTimeStarted()) + .append("; Retry attempts: ") + .append(transactionRetryAttempts) + .append("; Successful retries: ") + .append(successfulRetries) + .toString(); + } + + private String internalGetStateName() { + return transactionStarted == null ? "Not yet started" : getState().toString(); + } + + private String internalGetTimeStarted() { + return transactionStarted == null ? "Not yet started" : transactionStarted.toString(); + } + + @Override + public UnitOfWorkState getState() { + return this.state; + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + void checkValidTransaction() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, + "This transaction has status " + + state.name() + + ", only " + + UnitOfWorkState.STARTED + + " is allowed."); + ConnectionPreconditions.checkState( + !timedOutOrCancelled, + "The last statement of this transaction timed out or was cancelled. " + + "The transaction is no longer usable. " + + "Rollback the transaction and start a new one."); + if (txManager.getState() == null) { + transactionStarted = Timestamp.now(); + txContext = txManager.begin(); + } + if (txManager.getState() + != com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + String.format("Invalid transaction state: %s", txManager.getState())); + } + } + + @Override + TransactionContext getReadContext() { + ConnectionPreconditions.checkState(txContext != null, "Missing transaction context"); + return txContext; + } + + @Override + public Timestamp getReadTimestamp() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "There is no read timestamp available for read/write transactions."); + } + + @Override + public Timestamp getReadTimestampOrNull() { + return null; + } + + private boolean hasCommitTimestamp() { + return txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.COMMITTED; + } + + @Override + public Timestamp getCommitTimestamp() { + ConnectionPreconditions.checkState(hasCommitTimestamp(), "This transaction has not committed."); + return txManager.getCommitTimestamp(); + } + + @Override + public Timestamp getCommitTimestampOrNull() { + return hasCommitTimestamp() ? txManager.getCommitTimestamp() : null; + } + + @Override + public void executeDdl(ParsedStatement ddl) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "DDL-statements are not allowed inside a read/write transaction."); + } + + private void handlePossibleInvalidatingException(SpannerException e) { + if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED + || e.getErrorCode() == ErrorCode.CANCELLED) { + this.timedOutOrCancelled = true; + } + } + + @Override + public ResultSet executeQuery( + final ParsedStatement statement, + final AnalyzeMode analyzeMode, + final QueryOption... options) { + Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); + checkValidTransaction(); + try { + if (retryAbortsInternally) { + return asyncExecuteStatement( + statement, + new Callable() { + @Override + public ResultSet call() throws Exception { + return runWithRetry( + new Callable() { + @Override + public ResultSet call() throws Exception { + try { + getStatementExecutor() + .invokeInterceptors( + statement, + StatementExecutionStep.EXECUTE_STATEMENT, + ReadWriteTransaction.this); + ResultSet delegate = + DirectExecuteResultSet.ofResultSet( + internalExecuteQuery(statement, analyzeMode, options)); + return createAndAddRetryResultSet( + delegate, statement, analyzeMode, options); + } catch (AbortedException e) { + throw e; + } catch (SpannerException e) { + createAndAddFailedQuery(e, statement, analyzeMode, options); + throw e; + } + } + }); + } + }, + InterceptorsUsage + .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the + // Callable. + } else { + return super.executeQuery(statement, analyzeMode, options); + } + } catch (SpannerException e) { + handlePossibleInvalidatingException(e); + throw e; + } + } + + @Override + public long executeUpdate(final ParsedStatement update) { + Preconditions.checkNotNull(update); + Preconditions.checkArgument(update.isUpdate(), "The statement is not an update statement"); + checkValidTransaction(); + try { + if (retryAbortsInternally) { + return asyncExecuteStatement( + update, + new Callable() { + @Override + public Long call() throws Exception { + return runWithRetry( + new Callable() { + @Override + public Long call() throws Exception { + try { + getStatementExecutor() + .invokeInterceptors( + update, + StatementExecutionStep.EXECUTE_STATEMENT, + ReadWriteTransaction.this); + long updateCount = txContext.executeUpdate(update.getStatement()); + createAndAddRetriableUpdate(update, updateCount); + return updateCount; + } catch (AbortedException e) { + throw e; + } catch (SpannerException e) { + createAndAddFailedUpdate(e, update); + throw e; + } + } + }); + } + }, + InterceptorsUsage + .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the + // Callable. + } else { + return asyncExecuteStatement( + update, + new Callable() { + @Override + public Long call() throws Exception { + return txContext.executeUpdate(update.getStatement()); + } + }); + } + } catch (SpannerException e) { + handlePossibleInvalidatingException(e); + throw e; + } + } + + /** + * Create a RUN BATCH statement to use with the {@link #executeBatchUpdate(Iterable)} method to + * allow it to be cancelled, time out or retried. + * + *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, + * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout + * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link + * #executeBatchUpdate(Iterable)} method is called, we do not have one {@link ParsedStatement}, + * and the method uses this statement instead in order to use the same logic as the other + * statements. + */ + static final ParsedStatement EXECUTE_BATCH_UPDATE_STATEMENT = + StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); + + @Override + public long[] executeBatchUpdate(final Iterable updates) { + Preconditions.checkNotNull(updates); + final List updateStatements = new LinkedList<>(); + for (ParsedStatement update : updates) { + Preconditions.checkArgument( + update.isUpdate(), + "Statement is not an update statement: " + update.getSqlWithoutComments()); + updateStatements.add(update.getStatement()); + } + checkValidTransaction(); + try { + if (retryAbortsInternally) { + return asyncExecuteStatement( + EXECUTE_BATCH_UPDATE_STATEMENT, + new Callable() { + @Override + public long[] call() throws Exception { + return runWithRetry( + new Callable() { + @Override + public long[] call() throws Exception { + try { + getStatementExecutor() + .invokeInterceptors( + EXECUTE_BATCH_UPDATE_STATEMENT, + StatementExecutionStep.EXECUTE_STATEMENT, + ReadWriteTransaction.this); + long[] updateCounts = txContext.batchUpdate(updateStatements); + createAndAddRetriableBatchUpdate(updateStatements, updateCounts); + return updateCounts; + } catch (AbortedException e) { + throw e; + } catch (SpannerException e) { + createAndAddFailedBatchUpdate(e, updateStatements); + throw e; + } + } + }); + } + }, + InterceptorsUsage + .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the + // Callable. + } else { + return asyncExecuteStatement( + EXECUTE_BATCH_UPDATE_STATEMENT, + new Callable() { + @Override + public long[] call() throws Exception { + return txContext.batchUpdate(updateStatements); + } + }); + } + } catch (SpannerException e) { + handlePossibleInvalidatingException(e); + throw e; + } + } + + @Override + public void write(Mutation mutation) { + Preconditions.checkNotNull(mutation); + checkValidTransaction(); + mutations.add(mutation); + } + + @Override + public void write(Iterable mutations) { + Preconditions.checkNotNull(mutations); + checkValidTransaction(); + for (Mutation mutation : mutations) { + this.mutations.add(checkNotNull(mutation)); + } + } + + /** + * Create a COMMIT statement to use with the {@link #commit()} method to allow it to be cancelled, + * time out or retried. + * + *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, + * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout + * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link + * #commit()} method is called directly, we do not have a {@link ParsedStatement}, and the method + * uses this statement instead in order to use the same logic as the other statements. + */ + private static final ParsedStatement COMMIT_STATEMENT = + StatementParser.INSTANCE.parse(Statement.of("COMMIT")); + + private final Callable commitCallable = + new Callable() { + @Override + public Void call() throws Exception { + txContext.buffer(mutations); + txManager.commit(); + return null; + } + }; + + @Override + public void commit() { + checkValidTransaction(); + try { + if (retryAbortsInternally) { + asyncExecuteStatement( + COMMIT_STATEMENT, + new Callable() { + @Override + public Void call() throws Exception { + return runWithRetry( + new Callable() { + @Override + public Void call() throws Exception { + getStatementExecutor() + .invokeInterceptors( + COMMIT_STATEMENT, + StatementExecutionStep.EXECUTE_STATEMENT, + ReadWriteTransaction.this); + commitCallable.call(); + return null; + } + }); + } + }, + InterceptorsUsage.IGNORE_INTERCEPTORS); + } else { + asyncExecuteStatement(COMMIT_STATEMENT, commitCallable); + } + ReadWriteTransaction.this.state = UnitOfWorkState.COMMITTED; + } catch (SpannerException e) { + try { + txManager.close(); + } catch (Throwable t) { + // ignore + } + this.state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } + } + + /** + * Executes a database call that could throw an {@link AbortedException}. If an {@link + * AbortedException} is thrown, the transaction will automatically be retried and the checksums of + * all {@link ResultSet}s and update counts of DML statements will be checked against the original + * values of the original transaction. If the checksums and/or update counts do not match, the + * method will throw an {@link AbortedException} that cannot be retried, as the underlying data + * have actually changed. + * + *

If {@link ReadWriteTransaction#retryAbortsInternally} has been set to false, + * this method will throw an exception instead of retrying the transaction if the transaction was + * aborted. + * + * @param callable The actual database calls. + * @return the results of the database calls. + * @throws SpannerException if the database calls threw an exception, an {@link + * AbortedDueToConcurrentModificationException} if a retry of the transaction yielded + * different results than the original transaction, or an {@link AbortedException} if the + * maximum number of retries has been exceeded. + */ + T runWithRetry(Callable callable) throws SpannerException { + while (true) { + try { + return callable.call(); + } catch (final AbortedException aborted) { + if (retryAbortsInternally) { + handleAborted(aborted); + } else { + throw aborted; + } + } catch (SpannerException e) { + throw e; + } catch (Exception e) { + throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, e.getMessage(), e); + } + } + } + + /** + * Registers a {@link ResultSet} on this transaction that must be checked during a retry, and + * returns a retryable {@link ResultSet}. + */ + private ResultSet createAndAddRetryResultSet( + ResultSet resultSet, + ParsedStatement statement, + AnalyzeMode analyzeMode, + QueryOption... options) { + if (retryAbortsInternally) { + ChecksumResultSet checksumResultSet = + createChecksumResultSet(resultSet, statement, analyzeMode, options); + addRetryStatement(checksumResultSet); + return checksumResultSet; + } + return resultSet; + } + + /** Registers the statement as a query that should return an error during a retry. */ + private void createAndAddFailedQuery( + SpannerException e, + ParsedStatement statement, + AnalyzeMode analyzeMode, + QueryOption... options) { + if (retryAbortsInternally) { + addRetryStatement(new FailedQuery(this, e, statement, analyzeMode, options)); + } + } + + private void createAndAddRetriableUpdate(ParsedStatement update, long updateCount) { + if (retryAbortsInternally) { + addRetryStatement(new RetriableUpdate(this, update, updateCount)); + } + } + + private void createAndAddRetriableBatchUpdate(Iterable updates, long[] updateCounts) { + if (retryAbortsInternally) { + addRetryStatement(new RetriableBatchUpdate(this, updates, updateCounts)); + } + } + + /** Registers the statement as an update that should return an error during a retry. */ + private void createAndAddFailedUpdate(SpannerException e, ParsedStatement update) { + if (retryAbortsInternally) { + addRetryStatement(new FailedUpdate(this, e, update)); + } + } + + /** Registers the statements as a batch of updates that should return an error during a retry. */ + private void createAndAddFailedBatchUpdate(SpannerException e, Iterable updates) { + if (retryAbortsInternally) { + addRetryStatement(new FailedBatchUpdate(this, e, updates)); + } + } + + /** + * Adds a statement to the list of statements that should be retried if this transaction aborts. + */ + private void addRetryStatement(RetriableStatement statement) { + Preconditions.checkState( + retryAbortsInternally, "retryAbortsInternally is not enabled for this transaction"); + statements.add(statement); + } + + /** + * Handles an aborted exception by checking whether the transaction may be retried internally, and + * if so, does the retry. If retry is not allowed, or if the retry fails, the method will throw an + * {@link AbortedException}. + */ + private void handleAborted(AbortedException aborted) { + if (transactionRetryAttempts >= MAX_INTERNAL_RETRIES) { + // If the same statement in transaction keeps aborting, then we need to abort here. + throwAbortWithRetryAttemptsExceeded(); + } else if (retryAbortsInternally) { + logger.fine(toString() + ": Starting internal transaction retry"); + while (true) { + // First back off and then restart the transaction. + try { + Thread.sleep(aborted.getRetryDelayInMillis() / 1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "The statement was cancelled"); + } + try { + txContext = txManager.resetForRetry(); + // Inform listeners about the transaction retry that is about to start. + invokeTransactionRetryListenersOnStart(); + // Then retry all transaction statements. + transactionRetryAttempts++; + for (RetriableStatement statement : statements) { + statement.retry(aborted); + } + successfulRetries++; + invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_SUCCESSFUL); + logger.fine( + toString() + + ": Internal transaction retry succeeded. Starting retry of original statement."); + // Retry succeeded, return and continue the original transaction. + break; + } catch (AbortedDueToConcurrentModificationException e) { + // Retry failed because of a concurrent modification, we have to abort. + invokeTransactionRetryListenersOnFinish( + RetryResult.RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION); + logger.fine( + toString() + ": Internal transaction retry aborted due to a concurrent modification"); + // Try to rollback the new transaction and ignore any exceptions. + try { + txManager.rollback(); + } catch (Throwable t) { + // ignore + } + this.state = UnitOfWorkState.ABORTED; + throw e; + } catch (AbortedException e) { + // Retry aborted, do another retry of the transaction. + if (transactionRetryAttempts >= MAX_INTERNAL_RETRIES) { + throwAbortWithRetryAttemptsExceeded(); + } + invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_ABORTED_AND_RESTARTING); + logger.fine(toString() + ": Internal transaction retry aborted, trying again"); + } catch (SpannerException e) { + // unexpected exception + logger.log( + Level.FINE, + toString() + ": Internal transaction retry failed due to an unexpected exception", + e); + // Try to rollback the new transaction and ignore any exceptions. + try { + txManager.rollback(); + } catch (Throwable t) { + // ignore + } + // Set transaction state to aborted as the retry failed. + this.state = UnitOfWorkState.ABORTED; + // Re-throw underlying exception. + throw e; + } + } + } else { + try { + txManager.close(); + } catch (Throwable t) { + // ignore + } + // Internal retry is not enabled. + this.state = UnitOfWorkState.ABORTED; + throw aborted; + } + } + + private void throwAbortWithRetryAttemptsExceeded() throws SpannerException { + invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_ABORTED_AND_MAX_ATTEMPTS_EXCEEDED); + logger.fine( + toString() + + ": Internal transaction retry aborted and max number of retry attempts has been exceeded"); + // Try to rollback the transaction and ignore any exceptions. + // Normally it should not be necessary to do this, but in order to be sure we never leak + // any sessions it is better to do so. + try { + txManager.rollback(); + } catch (Throwable t) { + // ignore + } + this.state = UnitOfWorkState.ABORTED; + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.ABORTED, MAX_INTERNAL_RETRIES_EXCEEDED); + } + + private void invokeTransactionRetryListenersOnStart() { + for (TransactionRetryListener listener : transactionRetryListeners) { + listener.retryStarting(transactionStarted, transactionId, transactionRetryAttempts); + } + } + + private void invokeTransactionRetryListenersOnFinish(RetryResult result) { + for (TransactionRetryListener listener : transactionRetryListeners) { + listener.retryFinished(transactionStarted, transactionId, transactionRetryAttempts, result); + } + } + + /** The {@link Statement} and {@link Callable} for rollbacks */ + private final ParsedStatement rollbackStatement = + StatementParser.INSTANCE.parse(Statement.of("ROLLBACK")); + + private final Callable rollbackCallable = + new Callable() { + @Override + public Void call() throws Exception { + txManager.rollback(); + return null; + } + }; + + @Override + public void rollback() { + ConnectionPreconditions.checkState( + state == UnitOfWorkState.STARTED, "This transaction has status " + state.name()); + try { + asyncExecuteStatement(rollbackStatement, rollbackCallable); + } finally { + // Whatever happens, we should always call close in order to return the underlying session to + // the session pool to avoid any session leaks. + try { + txManager.close(); + } catch (Throwable e) { + // ignore + } + this.state = UnitOfWorkState.ROLLED_BACK; + } + } + + /** + * A retriable statement is a query or DML statement during a read/write transaction that can be + * retried if the original transaction aborted. + */ + interface RetriableStatement { + /** + * Retry this statement in a new transaction. Throws an {@link + * AbortedDueToConcurrentModificationException} if the retry could not successfully be executed + * because of an actual concurrent modification of the underlying data. This {@link + * AbortedDueToConcurrentModificationException} cannot be retried. + */ + void retry(AbortedException aborted) throws AbortedException; + } + + /** Creates a {@link ChecksumResultSet} for this {@link ReadWriteTransaction}. */ + @VisibleForTesting + ChecksumResultSet createChecksumResultSet( + ResultSet delegate, + ParsedStatement statement, + AnalyzeMode analyzeMode, + QueryOption... options) { + return new ChecksumResultSet(this, delegate, statement, analyzeMode, options); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java new file mode 100644 index 000000000000..0a72b36951c9 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java @@ -0,0 +1,352 @@ +/* + * Copyright 2019 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.ByteArray; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.common.base.Preconditions; +import com.google.spanner.v1.ResultSetStats; +import java.util.List; + +/** + * Forwarding implementation of {@link ResultSet} that forwards all calls to a delegate that can be + * replaced. This is used by the JDBC Driver when a read/write transaction is successfully retried. + * Any {@link ResultSet} that is open during a transaction retry, must be replaced by a result set + * that is fetched using the new transaction. This is achieved by wrapping the returned result sets + * in a {@link ReplaceableForwardingResultSet} that replaces its delegate after a transaction retry. + */ +class ReplaceableForwardingResultSet implements ResultSet { + private ResultSet delegate; + private boolean closed; + + ReplaceableForwardingResultSet(ResultSet delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + /** Replace the underlying delegate {@link ResultSet} with a new one. */ + void replaceDelegate(ResultSet delegate) { + Preconditions.checkNotNull(delegate); + checkClosed(); + if (this.delegate != null) { + this.delegate.close(); + } + this.delegate = delegate; + } + + private void checkClosed() { + if (closed) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "This ResultSet is closed"); + } + } + + boolean isClosed() { + return closed; + } + + @Override + public boolean next() throws SpannerException { + checkClosed(); + return delegate.next(); + } + + @Override + public Struct getCurrentRowAsStruct() { + checkClosed(); + return delegate.getCurrentRowAsStruct(); + } + + @Override + public void close() { + if (delegate != null) { + delegate.close(); + delegate = null; + } + closed = true; + } + + @Override + public ResultSetStats getStats() { + checkClosed(); + return delegate.getStats(); + } + + @Override + public Type getType() { + checkClosed(); + return delegate.getType(); + } + + @Override + public int getColumnCount() { + checkClosed(); + return delegate.getColumnCount(); + } + + @Override + public int getColumnIndex(String columnName) { + checkClosed(); + return delegate.getColumnIndex(columnName); + } + + @Override + public Type getColumnType(int columnIndex) { + checkClosed(); + return delegate.getColumnType(columnIndex); + } + + @Override + public Type getColumnType(String columnName) { + checkClosed(); + return delegate.getColumnType(columnName); + } + + @Override + public boolean isNull(int columnIndex) { + checkClosed(); + return delegate.isNull(columnIndex); + } + + @Override + public boolean isNull(String columnName) { + checkClosed(); + return delegate.isNull(columnName); + } + + @Override + public boolean getBoolean(int columnIndex) { + checkClosed(); + return delegate.getBoolean(columnIndex); + } + + @Override + public boolean getBoolean(String columnName) { + checkClosed(); + return delegate.getBoolean(columnName); + } + + @Override + public long getLong(int columnIndex) { + checkClosed(); + return delegate.getLong(columnIndex); + } + + @Override + public long getLong(String columnName) { + checkClosed(); + return delegate.getLong(columnName); + } + + @Override + public double getDouble(int columnIndex) { + checkClosed(); + return delegate.getDouble(columnIndex); + } + + @Override + public double getDouble(String columnName) { + checkClosed(); + return delegate.getDouble(columnName); + } + + @Override + public String getString(int columnIndex) { + checkClosed(); + return delegate.getString(columnIndex); + } + + @Override + public String getString(String columnName) { + checkClosed(); + return delegate.getString(columnName); + } + + @Override + public ByteArray getBytes(int columnIndex) { + checkClosed(); + return delegate.getBytes(columnIndex); + } + + @Override + public ByteArray getBytes(String columnName) { + checkClosed(); + return delegate.getBytes(columnName); + } + + @Override + public Timestamp getTimestamp(int columnIndex) { + checkClosed(); + return delegate.getTimestamp(columnIndex); + } + + @Override + public Timestamp getTimestamp(String columnName) { + checkClosed(); + return delegate.getTimestamp(columnName); + } + + @Override + public Date getDate(int columnIndex) { + checkClosed(); + return delegate.getDate(columnIndex); + } + + @Override + public Date getDate(String columnName) { + checkClosed(); + return delegate.getDate(columnName); + } + + @Override + public boolean[] getBooleanArray(int columnIndex) { + checkClosed(); + return delegate.getBooleanArray(columnIndex); + } + + @Override + public boolean[] getBooleanArray(String columnName) { + checkClosed(); + return delegate.getBooleanArray(columnName); + } + + @Override + public List getBooleanList(int columnIndex) { + checkClosed(); + return delegate.getBooleanList(columnIndex); + } + + @Override + public List getBooleanList(String columnName) { + checkClosed(); + return delegate.getBooleanList(columnName); + } + + @Override + public long[] getLongArray(int columnIndex) { + checkClosed(); + return delegate.getLongArray(columnIndex); + } + + @Override + public long[] getLongArray(String columnName) { + checkClosed(); + return delegate.getLongArray(columnName); + } + + @Override + public List getLongList(int columnIndex) { + checkClosed(); + return delegate.getLongList(columnIndex); + } + + @Override + public List getLongList(String columnName) { + checkClosed(); + return delegate.getLongList(columnName); + } + + @Override + public double[] getDoubleArray(int columnIndex) { + checkClosed(); + return delegate.getDoubleArray(columnIndex); + } + + @Override + public double[] getDoubleArray(String columnName) { + checkClosed(); + return delegate.getDoubleArray(columnName); + } + + @Override + public List getDoubleList(int columnIndex) { + checkClosed(); + return delegate.getDoubleList(columnIndex); + } + + @Override + public List getDoubleList(String columnName) { + checkClosed(); + return delegate.getDoubleList(columnName); + } + + @Override + public List getStringList(int columnIndex) { + checkClosed(); + return delegate.getStringList(columnIndex); + } + + @Override + public List getStringList(String columnName) { + checkClosed(); + return delegate.getStringList(columnName); + } + + @Override + public List getBytesList(int columnIndex) { + checkClosed(); + return delegate.getBytesList(columnIndex); + } + + @Override + public List getBytesList(String columnName) { + checkClosed(); + return delegate.getBytesList(columnName); + } + + @Override + public List getTimestampList(int columnIndex) { + checkClosed(); + return delegate.getTimestampList(columnIndex); + } + + @Override + public List getTimestampList(String columnName) { + checkClosed(); + return delegate.getTimestampList(columnName); + } + + @Override + public List getDateList(int columnIndex) { + checkClosed(); + return delegate.getDateList(columnIndex); + } + + @Override + public List getDateList(String columnName) { + checkClosed(); + return delegate.getDateList(columnName); + } + + @Override + public List getStructList(int columnIndex) { + checkClosed(); + return delegate.getStructList(columnIndex); + } + + @Override + public List getStructList(String columnName) { + checkClosed(); + return delegate.getStructList(columnName); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java new file mode 100644 index 000000000000..73609e8ba62f --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.common.base.Preconditions; +import java.util.Arrays; + +/** + * Retriable batch of DML statements. The check whether the statements had the same effect during + * retry is done by comparing the number of records affected. + */ +final class RetriableBatchUpdate implements RetriableStatement { + private final ReadWriteTransaction transaction; + private final Iterable statements; + private final long[] updateCounts; + + RetriableBatchUpdate( + ReadWriteTransaction transaction, Iterable statements, long[] updateCounts) { + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(statements); + this.transaction = transaction; + this.statements = statements; + this.updateCounts = updateCounts; + } + + @Override + public void retry(AbortedException aborted) throws AbortedException { + long[] newCount = null; + try { + transaction + .getStatementExecutor() + .invokeInterceptors( + ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, + StatementExecutionStep.RETRY_STATEMENT, + transaction); + newCount = transaction.getReadContext().batchUpdate(statements); + } catch (AbortedException e) { + // Just re-throw the AbortedException and let the retry logic determine whether another try + // should be executed or not. + throw e; + } catch (SpannerException e) { + // Unexpected database error that is different from the original transaction. + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } + if (newCount == null || !Arrays.equals(updateCounts, newCount)) { + // The update counts do not match, we cannot retry the transaction. + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java new file mode 100644 index 000000000000..ac2b82422465 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java @@ -0,0 +1,64 @@ +/* + * Copyright 2019 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.AbortedException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; + +/** + * Retriable DML statement. The check whether the statement had the same effect during retry is done + * by comparing the number of records affected. + */ +final class RetriableUpdate implements RetriableStatement { + private final ReadWriteTransaction transaction; + private final ParsedStatement statement; + private final long updateCount; + + RetriableUpdate(ReadWriteTransaction transaction, ParsedStatement statement, long updateCount) { + Preconditions.checkNotNull(transaction); + Preconditions.checkNotNull(statement); + this.transaction = transaction; + this.statement = statement; + this.updateCount = updateCount; + } + + @Override + public void retry(AbortedException aborted) throws AbortedException { + long newCount = -1; + try { + transaction + .getStatementExecutor() + .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); + newCount = transaction.getReadContext().executeUpdate(statement.getStatement()); + } catch (AbortedException e) { + // Just re-throw the AbortedException and let the retry logic determine whether another try + // should be executed or not. + throw e; + } catch (SpannerException e) { + // Unexpected database error that is different from the original transaction. + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); + } + if (newCount != updateCount) { + // The update counts do not match, we cannot retry the transaction. + throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java new file mode 100644 index 000000000000..67e6539f71b1 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java @@ -0,0 +1,546 @@ +/* + * Copyright 2019 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.api.gax.longrunning.OperationFuture; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionRunner; +import com.google.cloud.spanner.TransactionRunner.TransactionCallable; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.common.base.Preconditions; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * Transaction that is used when a {@link Connection} is in autocommit mode. Each method on this + * transaction actually starts a new transaction on Spanner. The type of transaction that is started + * depends on the type of statement that is being executed. A {@link SingleUseTransaction} will + * always try to choose the most efficient type of one-time transaction that is available for the + * statement. + * + *

A {@link SingleUseTransaction} can be used to execute any type of statement on Cloud Spanner: + * + *

    + *
  • Client side statements, e.g. SHOW VARIABLE AUTOCOMMIT + *
  • Queries, e.g. SELECT * FROM FOO + *
  • DML statements, e.g. UPDATE FOO SET BAR=1 + *
  • DDL statements, e.g. CREATE TABLE FOO (...) + *
+ */ +class SingleUseTransaction extends AbstractBaseUnitOfWork { + private final boolean readOnly; + private final DdlClient ddlClient; + private final DatabaseClient dbClient; + private final TimestampBound readOnlyStaleness; + private final AutocommitDmlMode autocommitDmlMode; + private Timestamp readTimestamp = null; + private volatile TransactionManager txManager; + private TransactionRunner writeTransaction; + private boolean used = false; + private UnitOfWorkState state = UnitOfWorkState.STARTED; + + static class Builder extends AbstractBaseUnitOfWork.Builder { + private DdlClient ddlClient; + private DatabaseClient dbClient; + private boolean readOnly; + private TimestampBound readOnlyStaleness; + private AutocommitDmlMode autocommitDmlMode; + + private Builder() {} + + Builder setDdlClient(DdlClient ddlClient) { + Preconditions.checkNotNull(ddlClient); + this.ddlClient = ddlClient; + return this; + } + + Builder setDatabaseClient(DatabaseClient client) { + Preconditions.checkNotNull(client); + this.dbClient = client; + return this; + } + + Builder setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + Builder setReadOnlyStaleness(TimestampBound staleness) { + Preconditions.checkNotNull(staleness); + this.readOnlyStaleness = staleness; + return this; + } + + Builder setAutocommitDmlMode(AutocommitDmlMode dmlMode) { + Preconditions.checkNotNull(dmlMode); + this.autocommitDmlMode = dmlMode; + return this; + } + + @Override + SingleUseTransaction build() { + Preconditions.checkState(ddlClient != null, "No DDL client specified"); + Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); + Preconditions.checkState(readOnlyStaleness != null, "No read-only staleness specified"); + Preconditions.checkState(autocommitDmlMode != null, "No autocommit dml mode specified"); + return new SingleUseTransaction(this); + } + } + + static Builder newBuilder() { + return new Builder(); + } + + private SingleUseTransaction(Builder builder) { + super(builder); + this.ddlClient = builder.ddlClient; + this.dbClient = builder.dbClient; + this.readOnly = builder.readOnly; + this.readOnlyStaleness = builder.readOnlyStaleness; + this.autocommitDmlMode = builder.autocommitDmlMode; + } + + @Override + public Type getType() { + return Type.TRANSACTION; + } + + @Override + public UnitOfWorkState getState() { + return state; + } + + @Override + public boolean isActive() { + // Single-use transactions are never active as they can be used only once. + return false; + } + + @Override + public boolean isReadOnly() { + return readOnly; + } + + private void checkAndMarkUsed() { + Preconditions.checkState(!used, "This single-use transaction has already been used"); + used = true; + } + + @Override + public ResultSet executeQuery( + final ParsedStatement statement, + final AnalyzeMode analyzeMode, + final QueryOption... options) { + Preconditions.checkNotNull(statement); + Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); + checkAndMarkUsed(); + + final ReadOnlyTransaction currentTransaction = + dbClient.singleUseReadOnlyTransaction(readOnlyStaleness); + Callable callable = + new Callable() { + @Override + public ResultSet call() throws Exception { + try { + ResultSet rs; + if (analyzeMode == AnalyzeMode.NONE) { + rs = currentTransaction.executeQuery(statement.getStatement(), options); + } else { + rs = + currentTransaction.analyzeQuery( + statement.getStatement(), analyzeMode.getQueryAnalyzeMode()); + } + // Return a DirectExecuteResultSet, which will directly do a next() call in order to + // ensure that the query is actually sent to Spanner. + return DirectExecuteResultSet.ofResultSet(rs); + } finally { + currentTransaction.close(); + } + } + }; + try { + ResultSet res = asyncExecuteStatement(statement, callable); + readTimestamp = currentTransaction.getReadTimestamp(); + state = UnitOfWorkState.COMMITTED; + return res; + } catch (Throwable e) { + state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } finally { + currentTransaction.close(); + } + } + + @Override + public Timestamp getReadTimestamp() { + ConnectionPreconditions.checkState( + readTimestamp != null, "There is no read timestamp available for this transaction."); + return readTimestamp; + } + + @Override + public Timestamp getReadTimestampOrNull() { + return readTimestamp; + } + + private boolean hasCommitTimestamp() { + return writeTransaction != null + || (txManager != null + && txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.COMMITTED); + } + + @Override + public Timestamp getCommitTimestamp() { + ConnectionPreconditions.checkState( + hasCommitTimestamp(), "There is no commit timestamp available for this transaction."); + return writeTransaction != null + ? writeTransaction.getCommitTimestamp() + : txManager.getCommitTimestamp(); + } + + @Override + public Timestamp getCommitTimestampOrNull() { + if (hasCommitTimestamp()) { + try { + return writeTransaction != null + ? writeTransaction.getCommitTimestamp() + : txManager.getCommitTimestamp(); + } catch (SpannerException e) { + // ignore + } + } + return null; + } + + @Override + public void executeDdl(final ParsedStatement ddl) { + Preconditions.checkNotNull(ddl); + Preconditions.checkArgument( + ddl.getType() == StatementType.DDL, "Statement is not a ddl statement"); + ConnectionPreconditions.checkState( + !isReadOnly(), "DDL statements are not allowed in read-only mode"); + checkAndMarkUsed(); + + try { + Callable callable = + new Callable() { + @Override + public Void call() throws Exception { + OperationFuture operation = + ddlClient.executeDdl(ddl.getSqlWithoutComments()); + return operation.get(); + } + }; + asyncExecuteStatement(ddl, callable); + state = UnitOfWorkState.COMMITTED; + } catch (Throwable e) { + state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } + } + + @Override + public long executeUpdate(final ParsedStatement update) { + Preconditions.checkNotNull(update); + Preconditions.checkArgument(update.isUpdate(), "Statement is not an update statement"); + ConnectionPreconditions.checkState( + !isReadOnly(), "Update statements are not allowed in read-only mode"); + checkAndMarkUsed(); + + long res; + try { + switch (autocommitDmlMode) { + case TRANSACTIONAL: + res = executeAsyncTransactionalUpdate(update, new TransactionalUpdateCallable(update)); + break; + case PARTITIONED_NON_ATOMIC: + res = executeAsyncPartitionedUpdate(update); + break; + default: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Unknown dml mode: " + autocommitDmlMode); + } + } catch (Throwable e) { + state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } + state = UnitOfWorkState.COMMITTED; + return res; + } + + /** Execute an update statement as a partitioned DML statement. */ + private long executeAsyncPartitionedUpdate(final ParsedStatement update) { + Callable callable = + new Callable() { + @Override + public Long call() throws Exception { + return dbClient.executePartitionedUpdate(update.getStatement()); + } + }; + return asyncExecuteStatement(update, callable); + } + + private final ParsedStatement executeBatchUpdateStatement = + StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); + + @Override + public long[] executeBatchUpdate(Iterable updates) { + Preconditions.checkNotNull(updates); + for (ParsedStatement update : updates) { + Preconditions.checkArgument( + update.isUpdate(), + "Statement is not an update statement: " + update.getSqlWithoutComments()); + } + ConnectionPreconditions.checkState( + !isReadOnly(), "Batch update statements are not allowed in read-only mode"); + checkAndMarkUsed(); + + long[] res; + try { + switch (autocommitDmlMode) { + case TRANSACTIONAL: + res = + executeAsyncTransactionalUpdate( + executeBatchUpdateStatement, new TransactionalBatchUpdateCallable(updates)); + break; + case PARTITIONED_NON_ATOMIC: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "Batch updates are not allowed in " + autocommitDmlMode); + default: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Unknown dml mode: " + autocommitDmlMode); + } + } catch (SpannerBatchUpdateException e) { + // Batch update exceptions does not cause a rollback. + state = UnitOfWorkState.COMMITTED; + throw e; + } catch (Throwable e) { + state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } + state = UnitOfWorkState.COMMITTED; + return res; + } + + /** Base class for executing DML updates (both single statements and batches). */ + private abstract class AbstractUpdateCallable implements Callable { + abstract T executeUpdate(TransactionContext txContext); + + @Override + public T call() throws Exception { + txManager = dbClient.transactionManager(); + // Check the interrupted state after each (possible) round-trip to the db to allow the + // statement to be cancelled. + checkInterrupted(); + try (TransactionContext txContext = + txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.ABORTED + ? txManager.resetForRetry() + : txManager.begin()) { + checkInterrupted(); + T res = executeUpdate(txContext); + checkInterrupted(); + txManager.commit(); + checkInterrupted(); + return res; + } finally { + txManager.close(); + } + } + } + + /** {@link Callable} for a single update statement. */ + private final class TransactionalUpdateCallable extends AbstractUpdateCallable { + private final ParsedStatement update; + + private TransactionalUpdateCallable(ParsedStatement update) { + this.update = update; + } + + @Override + Long executeUpdate(TransactionContext txContext) { + return txContext.executeUpdate(update.getStatement()); + } + } + + /** {@link Callable} for a batch update. */ + private final class TransactionalBatchUpdateCallable extends AbstractUpdateCallable { + private final List updates; + + private TransactionalBatchUpdateCallable(Iterable updates) { + this.updates = new LinkedList<>(); + for (ParsedStatement update : updates) { + this.updates.add(update.getStatement()); + } + } + + @Override + long[] executeUpdate(TransactionContext txContext) { + return txContext.batchUpdate(updates); + } + } + + private T executeAsyncTransactionalUpdate( + final ParsedStatement update, final AbstractUpdateCallable callable) { + long startedTime = System.currentTimeMillis(); + // This method uses a TransactionManager instead of the TransactionRunner in order to be able to + // handle timeouts and canceling of a statement. + while (true) { + try { + try { + return asyncExecuteStatement(update, callable); + } catch (AbortedException e) { + try { + Thread.sleep(e.getRetryDelayInMillis() / 1000); + } catch (InterruptedException e1) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "Statement execution was interrupted", e1); + } + // Check whether the timeout time has been exceeded. + long executionTime = System.currentTimeMillis() - startedTime; + if (getStatementTimeout().hasTimeout() + && executionTime > getStatementTimeout().getTimeoutValue(TimeUnit.MILLISECONDS)) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.DEADLINE_EXCEEDED, + "Statement execution timeout occurred for " + update.getSqlWithoutComments()); + } + } + } catch (Exception e) { + if (txManager != null) { + try { + if (txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { + fireAndForgetRollbackAndCloseTxManager(txManager); + } + } finally { + txManager.close(); + } + } + throw e; + } + } + } + + private void checkInterrupted() throws InterruptedException { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + } + + /** + * Do a fire-and-forget rollback and close the transaction manager. Fire-and-forget is ok as Cloud + * Spanner will abort the transaction automatically after a while if the rollback request should + * not actually reach Cloud Spanner. + */ + private void fireAndForgetRollbackAndCloseTxManager(final TransactionManager txManager) { + Preconditions.checkNotNull(txManager); + Preconditions.checkArgument( + txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED); + ExecutorService rollbackExecutor = + Executors.newSingleThreadExecutor(new ConnectionImpl.DaemonThreadFactory()); + rollbackExecutor.submit( + new Callable() { + @Override + public Void call() throws Exception { + try { + txManager.rollback(); + return null; + } finally { + txManager.close(); + } + } + }); + rollbackExecutor.shutdown(); + } + + @Override + public void write(final Mutation mutation) { + write(Arrays.asList(mutation)); + } + + @Override + public void write(final Iterable mutations) { + Preconditions.checkNotNull(mutations); + ConnectionPreconditions.checkState( + !isReadOnly(), "Update statements are not allowed in read-only mode"); + checkAndMarkUsed(); + + writeTransaction = dbClient.readWriteTransaction(); + try { + writeTransaction.run( + new TransactionCallable() { + @Override + public Void run(TransactionContext transaction) throws Exception { + transaction.buffer(mutations); + return null; + } + }); + } catch (Throwable e) { + state = UnitOfWorkState.COMMIT_FAILED; + throw e; + } + state = UnitOfWorkState.COMMITTED; + } + + @Override + public void commit() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Commit is not supported for single-use transactions"); + } + + @Override + public void rollback() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Rollback is not supported for single-use transactions"); + } + + @Override + public long[] runBatch() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for single-use transactions"); + } + + @Override + public void abortBatch() { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for single-use transactions"); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java new file mode 100644 index 000000000000..771ad505c77f --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java @@ -0,0 +1,428 @@ +/* + * Copyright 2019 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.api.core.ApiFunction; +import com.google.auth.Credentials; +import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import io.grpc.ManagedChannelBuilder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + +/** + * Pool for keeping track of {@link Spanner} instances needed by JDBC connections. + * + *

When a JDBC connection is opened for a Google Cloud Spanner database, a {@link Spanner} object + * can be opened in the background. The {@link SpannerPool} keeps track of which {@link Spanner} + * objects have been opened by connections during the lifetime of the JVM, which connections are + * still opened and closed, and which {@link Spanner} objects could be closed. + * + *

Call the method {@link SpannerPool#closeSpannerPool()} at the end of your application to + * gracefully shutdown all instances in the pool. + */ +public class SpannerPool { + private static final Logger logger = Logger.getLogger(SpannerPool.class.getName()); + + /** + * Closes the default {@link SpannerPool} and all {@link Spanner} instances that have been opened + * by connections and that are still open. Call this method at the end of your application to + * gracefully close all {@link Spanner} instances in the pool. Failing to call this method will + * keep your application running for 60 seconds after you close the last {@link + * java.sql.Connection} to Cloud Spanner, as this is the default timeout before the {@link + * SpannerPool} closes the unused {@link Spanner} instances. + */ + public static void closeSpannerPool() { + INSTANCE.checkAndCloseSpanners(); + } + + /** + * The minimum number of milliseconds a {@link Spanner} should not have been used for a connection + * before it is closed. + */ + private static final long DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED = 60000L; + + static final SpannerPool INSTANCE = + new SpannerPool(DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED); + + @VisibleForTesting + enum CheckAndCloseSpannersMode { + WARN, + ERROR; + } + + private final class CloseSpannerRunnable implements Runnable { + @Override + public void run() { + try { + checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); + } catch (Exception e) { + // ignore + } + } + } + + private final class CloseUnusedSpannersRunnable implements Runnable { + @Override + public void run() { + try { + closeUnusedSpanners(SpannerPool.this.closeSpannerAfterMillisecondsUnused); + } catch (Throwable e) { + logger.log(Level.FINE, "Scheduled call to closeUnusedSpanners failed", e); + } + } + } + + static class SpannerPoolKey { + private final String host; + private final String projectId; + private final Credentials credentials; + private final Integer numChannels; + private final boolean usePlainText; + private final String userAgent; + + private static SpannerPoolKey of(ConnectionOptions options) { + return new SpannerPoolKey(options); + } + + private SpannerPoolKey(ConnectionOptions options) { + this.host = options.getHost(); + this.projectId = options.getProjectId(); + this.credentials = options.getCredentials(); + this.numChannels = options.getNumChannels(); + this.usePlainText = options.isUsePlainText(); + this.userAgent = options.getUserAgent(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof SpannerPoolKey)) { + return false; + } + SpannerPoolKey other = (SpannerPoolKey) o; + return Objects.equals(this.host, other.host) + && Objects.equals(this.projectId, other.projectId) + && Objects.equals(this.credentials, other.credentials) + && Objects.equals(this.numChannels, other.numChannels) + && Objects.equals(this.usePlainText, other.usePlainText) + && Objects.equals(this.userAgent, other.userAgent); + } + + @Override + public int hashCode() { + return Objects.hash( + this.host, + this.projectId, + this.credentials, + this.numChannels, + this.usePlainText, + this.userAgent); + } + } + + /** + * The management threads of a {@link SpannerPool} are lazily initialized to prevent unnecessary + * threads to be created when the connection API is not used. + */ + private boolean initialized = false; + /** + * Thread that will be run as a shutdown hook on closing the application. This thread will close + * any Spanner instances opened by the Connection API that are still open. + */ + private Thread shutdownThread = null; + + /** + * Keep unused {@link Spanner} instances open and in the pool for this duration after all its + * {@link Connection}s have been closed. This prevents unnecessary opening and closing of {@link + * Spanner} instances. + */ + private final long closeSpannerAfterMillisecondsUnused; + + /** + * This scheduled task will close all {@link Spanner} objects that have not been used for an open + * connection for at least {@link SpannerPool#DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED} + * milliseconds. + */ + private ScheduledExecutorService closerService; + + @GuardedBy("this") + private final Map spanners = new HashMap<>(); + + @GuardedBy("this") + private final Map> connections = new HashMap<>(); + + /** + * Keep track of the moment that the last connection for a specific {@link SpannerPoolKey} was + * closed, so that we can use this to determine whether a {@link Spanner} instance should be + * closed and removed from the pool. As {@link Spanner} instances are expensive to create and + * close, we do not want to do that unnecessarily. By adding a delay between the moment the last + * {@link Connection} for a {@link Spanner} was closed and the moment we close the {@link Spanner} + * instance, we prevent applications that open one or more connections for a process and close all + * these connections at the end of the process from getting a severe performance penalty from + * opening and closing {@link Spanner} instances all the time. + * + *

{@link Spanner} instances are closed and removed from the pool when the last connection was + * closed more than {@link #closeSpannerAfterMillisecondsUnused} milliseconds ago. + */ + @GuardedBy("this") + private final Map lastConnectionClosedAt = new HashMap<>(); + + @VisibleForTesting + SpannerPool() { + this(0L); + } + + @VisibleForTesting + SpannerPool(long closeSpannerAfterMillisecondsUnused) { + this.closeSpannerAfterMillisecondsUnused = closeSpannerAfterMillisecondsUnused; + } + + /** + * Gets a Spanner object for a connection with the properties specified in the {@link + * ConnectionOptions} object. The {@link SpannerPool} will manage a pool of opened Spanner objects + * for the different connections, and reuse Spanner objects whenever possible. Spanner objects + * will also be closed down when the application is closing. + * + * @param options The specification of the Spanner database to connect to. + * @param connection The {@link ConnectionImpl} that will be created. This {@link ConnectionImpl} + * will be tracked by the pool to know when a {@link Spanner} object can be closed. + * @return an opened {@link Spanner} object that can be used by a connection to communicate with + * the Spanner database. + */ + Spanner getSpanner(ConnectionOptions options, ConnectionImpl connection) { + Preconditions.checkNotNull(options); + Preconditions.checkNotNull(connection); + SpannerPoolKey key = SpannerPoolKey.of(options); + Spanner spanner; + synchronized (this) { + if (!initialized) { + initialize(); + } + if (spanners.get(key) != null) { + spanner = spanners.get(key); + } else { + spanner = createSpanner(key); + spanners.put(key, spanner); + } + List registeredConnectionsForSpanner = connections.get(key); + if (registeredConnectionsForSpanner == null) { + registeredConnectionsForSpanner = new ArrayList<>(); + connections.put(key, registeredConnectionsForSpanner); + } + registeredConnectionsForSpanner.add(connection); + lastConnectionClosedAt.remove(key); + return spanner; + } + } + + private void initialize() { + shutdownThread = new Thread(new CloseSpannerRunnable(), "SpannerPool shutdown hook"); + Runtime.getRuntime().addShutdownHook(shutdownThread); + if (this.closeSpannerAfterMillisecondsUnused > 0) { + this.closerService = + Executors.newSingleThreadScheduledExecutor( + new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "close-unused-spanners-worker"); + thread.setDaemon(true); + return thread; + } + }); + this.closerService.scheduleAtFixedRate( + new CloseUnusedSpannersRunnable(), + this.closeSpannerAfterMillisecondsUnused, + this.closeSpannerAfterMillisecondsUnused, + TimeUnit.MILLISECONDS); + } + initialized = true; + } + + @SuppressWarnings("rawtypes") + @VisibleForTesting + Spanner createSpanner(SpannerPoolKey key) { + SpannerOptions.Builder builder = SpannerOptions.newBuilder(); + builder + .setClientLibToken(MoreObjects.firstNonNull(key.userAgent, JdbcDriver.getClientLibToken())) + .setHost(key.host) + .setProjectId(key.projectId) + .setCredentials(key.credentials); + if (key.numChannels != null) { + builder.setNumChannels(key.numChannels); + } + if (key.usePlainText) { + // Credentials may not be sent over a plain text channel. + builder.setCredentials(NoCredentials.getInstance()); + // Set a custom channel configurator to allow http instead of https. + builder.setChannelConfigurator( + new ApiFunction() { + @Override + public ManagedChannelBuilder apply(ManagedChannelBuilder input) { + input.usePlaintext(); + return input; + } + }); + } + return builder.build().getService(); + } + + /** + * Remove the given {@link ConnectionImpl} from the list of connections that should be monitored + * by this pool. + * + * @param options The {@link ConnectionOptions} that were used to create the connection. + * @param connection The {@link ConnectionImpl} to remove from this pool.. + */ + void removeConnection(ConnectionOptions options, ConnectionImpl connection) { + Preconditions.checkNotNull(options); + Preconditions.checkNotNull(connection); + SpannerPoolKey key = SpannerPoolKey.of(options); + synchronized (this) { + if (spanners.containsKey(key) && connections.containsKey(key)) { + List registeredConnections = connections.get(key); + // Remove the connection from the pool. + if (registeredConnections == null || !registeredConnections.remove(connection)) { + logger.log( + Level.WARNING, + "There are no connections registered for ConnectionOptions " + options.toString()); + } else { + // Check if this was the last connection for this spanner key. + if (registeredConnections.isEmpty()) { + // Register the moment the last connection for this Spanner key was removed, so we know + // which Spanner objects we could close. + lastConnectionClosedAt.put(key, System.currentTimeMillis()); + } + } + } else { + logger.log( + Level.WARNING, + "There is no Spanner registered for ConnectionOptions " + options.toString()); + } + } + } + + /** + * Checks that there are no {@link Connection}s that have been created by this {@link SpannerPool} + * that are still open, and then closes all {@link Spanner} instances in the pool. If there is at + * least one unclosed {@link Connection} left in the pool, the method will throw a {@link + * SpannerException} and no {@link Spanner} instances will be closed. + */ + void checkAndCloseSpanners() { + checkAndCloseSpanners(CheckAndCloseSpannersMode.ERROR); + } + + @VisibleForTesting + void checkAndCloseSpanners(CheckAndCloseSpannersMode mode) { + List keysStillInUse = new ArrayList<>(); + synchronized (this) { + for (Entry entry : spanners.entrySet()) { + if (!lastConnectionClosedAt.containsKey(entry.getKey())) { + keysStillInUse.add(entry.getKey()); + } + } + if (keysStillInUse.isEmpty() || mode == CheckAndCloseSpannersMode.WARN) { + if (!keysStillInUse.isEmpty()) { + logLeakedConnections(keysStillInUse); + logger.log( + Level.WARNING, + "There is/are " + + keysStillInUse.size() + + " connection(s) still open." + + " Close all connections before stopping the application"); + } + // Force close all Spanner instances by passing in a value that will always be less than the + // difference between the current time and the close time of a connection. + closeUnusedSpanners(Long.MIN_VALUE); + } else { + logLeakedConnections(keysStillInUse); + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "There is/are " + + keysStillInUse.size() + + " connection(s) still open. Close all connections before calling closeSpanner()"); + } + } + } + + private void logLeakedConnections(List keysStillInUse) { + synchronized (this) { + for (SpannerPoolKey key : keysStillInUse) { + for (ConnectionImpl con : connections.get(key)) { + if (!con.isClosed() && con.getLeakedException() != null) { + logger.log(Level.WARNING, "Leaked connection", con.getLeakedException()); + } + } + } + } + } + + /** + * Closes Spanner objects that are no longer in use by connections, and where the last connection + * that used it was closed more than closeSpannerAfterMillisecondsUnused seconds ago. + * The delay ensures that Spanner objects are not closed unless there's a good reason for it. + * + * @param closeSpannerAfterMillisecondsUnused The number of milliseconds a {@link Spanner} object + * should not have been used for a {@link Connection} before it is closed by this method. + */ + @VisibleForTesting + void closeUnusedSpanners(long closeSpannerAfterMillisecondsUnused) { + List keysToBeRemoved = new ArrayList<>(); + synchronized (this) { + for (Entry entry : lastConnectionClosedAt.entrySet()) { + Long closedAt = entry.getValue(); + // Check whether the last connection was closed more than + // closeSpannerAfterMillisecondsUnused milliseconds ago. + if (closedAt != null + && ((System.currentTimeMillis() - closedAt.longValue())) + > closeSpannerAfterMillisecondsUnused) { + Spanner spanner = spanners.get(entry.getKey()); + if (spanner != null) { + try { + spanner.close(); + } finally { + // Even if the close operation failed, we should remove the spanner object as it is no + // longer valid. + spanners.remove(entry.getKey()); + keysToBeRemoved.add(entry.getKey()); + } + } + } + } + for (SpannerPoolKey key : keysToBeRemoved) { + lastConnectionClosedAt.remove(key); + } + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java new file mode 100644 index 000000000000..227bc62961c8 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 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.ResultSet; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; + +/** Interface for interceptors that are invoked before a statement is executed. */ +interface StatementExecutionInterceptor { + void intercept(ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction); +} + +/** + * Enum passed in to a {@link StatementExecutionInterceptor} to determine what/why a statement is + * being executed. + */ +enum StatementExecutionStep { + /** The initial execution of a statement (DML/Query). */ + EXECUTE_STATEMENT, + /** A call to {@link ResultSet#next()}. */ + CALL_NEXT_ON_RESULT_SET, + /** Execution of the statement during an internal transaction retry. */ + RETRY_STATEMENT, + /** A call to {@link ResultSet#next()} during internal transaction retry. */ + RETRY_NEXT_ON_RESULT_SET; +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java new file mode 100644 index 000000000000..797599816af4 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java @@ -0,0 +1,189 @@ +/* + * Copyright 2019 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.jdbc.ReadOnlyStalenessUtil.DurationValueGetter; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.protobuf.Duration; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * {@link StatementExecutor} is responsible for executing statements on a {@link Connection}. + * Statements are executed using a separate executor to allow timeouts and cancellation of + * statements. + */ +class StatementExecutor { + + /** Simple holder class for statement timeout that allows us to pass the value by reference. */ + static class StatementTimeout { + /** + * Only {@link TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link + * TimeUnit#MILLISECONDS} and {@link TimeUnit#SECONDS} may be used to specify a statement + * timeout. + */ + static boolean isValidTimeoutUnit(TimeUnit unit) { + return unit == TimeUnit.NANOSECONDS + || unit == TimeUnit.MICROSECONDS + || unit == TimeUnit.MILLISECONDS + || unit == TimeUnit.SECONDS; + } + + /** The statement timeout. */ + private Duration duration = null; + + /** Creates a {@link StatementTimeout} that will never timeout. */ + @VisibleForTesting + static StatementTimeout nullTimeout() { + return new StatementTimeout(); + } + + /** Creates a {@link StatementTimeout} with the given duration. */ + @VisibleForTesting + static StatementTimeout of(long timeout, TimeUnit unit) { + Preconditions.checkArgument(timeout > 0L); + Preconditions.checkArgument(isValidTimeoutUnit(unit)); + StatementTimeout res = new StatementTimeout(); + res.duration = ReadOnlyStalenessUtil.createDuration(timeout, unit); + return res; + } + + /** + * Does this {@link StatementTimeout} have an actual timeout (i.e. it will eventually timeout). + */ + boolean hasTimeout() { + return duration != null; + } + + void clearTimeoutValue() { + this.duration = null; + } + + void setTimeoutValue(long timeout, TimeUnit unit) { + Preconditions.checkArgument(timeout > 0L); + Preconditions.checkArgument(isValidTimeoutUnit(unit)); + this.duration = ReadOnlyStalenessUtil.createDuration(timeout, unit); + } + + long getTimeoutValue(TimeUnit unit) { + Preconditions.checkArgument(isValidTimeoutUnit(unit)); + return duration == null ? 0L : ReadOnlyStalenessUtil.durationToUnits(duration, unit); + } + + /** + * Returns the {@link TimeUnit} with the least precision that could be used to represent this + * {@link StatementTimeout} without loss of precision. + */ + TimeUnit getAppropriateTimeUnit() { + ConnectionPreconditions.checkState( + duration != null, "This StatementTimeout has no timeout value"); + return ReadOnlyStalenessUtil.getAppropriateTimeUnit( + new DurationValueGetter() { + @Override + public long getDuration(TimeUnit unit) { + return StatementTimeout.this.getTimeoutValue(unit); + } + + @Override + public boolean hasDuration() { + return StatementTimeout.this.hasTimeout(); + } + }); + } + } + + /** + * Use a {@link ThreadFactory} that produces daemon threads and sets recognizable name on the + * threads. + */ + private static final ThreadFactory THREAD_FACTORY = + new ThreadFactoryBuilder() + .setDaemon(true) + .setNameFormat("connection-executor-%d") + .setThreadFactory(MoreExecutors.platformThreadFactory()) + .build(); + + /** Creates an {@link ExecutorService} for a {@link StatementExecutor}. */ + private static ExecutorService createExecutorService() { + return MoreExecutors.getExitingExecutorService( + new ThreadPoolExecutor( + 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), THREAD_FACTORY)); + } + + private ExecutorService executor = createExecutorService(); + + /** + * Interceptors that should be invoked before or after a statement is executed can be registered + * for a connection. This are added to this list. The interceptors are intended for test usage. + */ + private final List interceptors; + + @VisibleForTesting + StatementExecutor() { + this.interceptors = Collections.emptyList(); + } + + StatementExecutor(List interceptors) { + this.interceptors = Collections.unmodifiableList(interceptors); + } + + /** + * Recreates this {@link StatementExecutor} and its {@link ExecutorService}. This can be necessary + * if a statement times out or is cancelled, and it cannot be guaranteed that the statement + * execution can be terminated. In order to prevent the single threaded {@link ExecutorService} to + * continue to block on the timed out/cancelled statement, a new {@link ExecutorService} is + * created. + */ + void recreate() { + executor.shutdown(); + executor = createExecutorService(); + } + + /** + * Shutdown this executor now and do not wait for any statement that is being executed to finish. + */ + List shutdownNow() { + return executor.shutdownNow(); + } + + /** Execute a statement on this {@link StatementExecutor}. */ + Future submit(Callable callable) { + return executor.submit(callable); + } + + /** + * Invoke the interceptors that have been registered for this {@link StatementExecutor} for the + * given step. + */ + void invokeInterceptors( + ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction) { + for (StatementExecutionInterceptor interceptor : interceptors) { + interceptor.intercept(statement, step, transaction); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java new file mode 100644 index 000000000000..5587712904cb --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java @@ -0,0 +1,381 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import java.util.Collections; +import java.util.Set; + +/** + * Internal class for the Spanner Connection API. + * + *

Parses {@link ClientSideStatement}s and normal SQL statements. The parser is able to recognize + * the type of statement, allowing the connection API to know which method on Spanner should be + * called. The parser does not validate the validity of statements, except for {@link + * ClientSideStatement}s. This means that an invalid DML statement could be accepted by the {@link + * StatementParser} and sent to Spanner, and Spanner will then reject it with some error message. + */ +class StatementParser { + /** Singleton instance of {@link StatementParser}. */ + public static final StatementParser INSTANCE = new StatementParser(); + + /** The type of statement that has been recognized by the parser. */ + enum StatementType { + CLIENT_SIDE, + DDL, + QUERY, + UPDATE, + UNKNOWN; + } + + /** A statement that has been parsed */ + static class ParsedStatement { + private final StatementType type; + private final ClientSideStatementImpl clientSideStatement; + private final Statement statement; + private final String sqlWithoutComments; + + private static ParsedStatement clientSideStatement( + ClientSideStatementImpl clientSideStatement, + Statement statement, + String sqlWithoutComments) { + return new ParsedStatement(clientSideStatement, statement, sqlWithoutComments); + } + + private static ParsedStatement ddl(Statement statement, String sqlWithoutComments) { + return new ParsedStatement(StatementType.DDL, statement, sqlWithoutComments); + } + + private static ParsedStatement query(Statement statement, String sqlWithoutComments) { + return new ParsedStatement(StatementType.QUERY, statement, sqlWithoutComments); + } + + private static ParsedStatement update(Statement statement, String sqlWithoutComments) { + return new ParsedStatement(StatementType.UPDATE, statement, sqlWithoutComments); + } + + private static ParsedStatement unknown(Statement statement, String sqlWithoutComments) { + return new ParsedStatement(StatementType.UNKNOWN, statement, sqlWithoutComments); + } + + private ParsedStatement( + ClientSideStatementImpl clientSideStatement, + Statement statement, + String sqlWithoutComments) { + Preconditions.checkNotNull(clientSideStatement); + Preconditions.checkNotNull(statement); + this.type = StatementType.CLIENT_SIDE; + this.clientSideStatement = clientSideStatement; + this.statement = statement; + this.sqlWithoutComments = sqlWithoutComments; + } + + private ParsedStatement(StatementType type, Statement statement, String sqlWithoutComments) { + Preconditions.checkNotNull(type); + Preconditions.checkNotNull(statement); + this.type = type; + this.clientSideStatement = null; + this.statement = statement; + this.sqlWithoutComments = sqlWithoutComments; + } + + StatementType getType() { + return type; + } + + boolean isQuery() { + switch (type) { + case CLIENT_SIDE: + return getClientSideStatement().isQuery(); + case QUERY: + return true; + case UPDATE: + case DDL: + case UNKNOWN: + default: + } + return false; + } + + boolean isUpdate() { + switch (type) { + case CLIENT_SIDE: + return getClientSideStatement().isUpdate(); + case UPDATE: + return true; + case QUERY: + case DDL: + case UNKNOWN: + default: + } + return false; + } + + boolean isDdl() { + switch (type) { + case DDL: + return true; + case CLIENT_SIDE: + case UPDATE: + case QUERY: + case UNKNOWN: + default: + } + return false; + } + + Statement getStatement() { + return statement; + } + + String getSqlWithoutComments() { + return sqlWithoutComments; + } + + ClientSideStatement getClientSideStatement() { + Preconditions.checkState( + clientSideStatement != null, + "This ParsedStatement does not contain a ClientSideStatement"); + return clientSideStatement; + } + } + + private final Set ddlStatements = ImmutableSet.of("CREATE", "DROP", "ALTER"); + private final Set selectStatements = ImmutableSet.of("SELECT"); + private final Set dmlStatements = ImmutableSet.of("INSERT", "UPDATE", "DELETE"); + private final Set statements; + + /** Private constructor for singleton instance. */ + private StatementParser() { + try { + statements = + Collections.unmodifiableSet(ClientSideStatements.INSTANCE.getCompiledStatements()); + } catch (CompileException e) { + throw new RuntimeException(e); + } + } + + /** + * Parses the given statement and categorizes it as one of the possible {@link StatementType}s. + * The validity of the statement is not checked, unless it is a client-side statement. + * + * @param statement The statement to parse. + * @return the parsed and categorized statement. + */ + ParsedStatement parse(Statement statement) { + String sql = removeCommentsAndTrim(statement.getSql()); + ClientSideStatementImpl client = parseClientSideStatement(sql); + if (client != null) { + return ParsedStatement.clientSideStatement(client, statement, sql); + } else if (isQuery(sql)) { + return ParsedStatement.query(statement, sql); + } else if (isUpdateStatement(sql)) { + return ParsedStatement.update(statement, sql); + } else if (isDdlStatement(sql)) { + return ParsedStatement.ddl(statement, sql); + } + return ParsedStatement.unknown(statement, sql); + } + + /** + * Parses the given statement as a client-side statement. Client-side statements are statements + * that are never sent to Cloud Spanner, but that are interpreted by the Connection API and then + * translated into some action, such as for example starting a transaction or getting the last + * commit timestamp. + * + * @param sql The statement to try to parse as a client-side statement (without any comments). + * @return a valid {@link ClientSideStatement} or null if the statement is not a client-side + * statement. + */ + @VisibleForTesting + ClientSideStatementImpl parseClientSideStatement(String sql) { + for (ClientSideStatementImpl css : statements) { + if (css.matches(sql)) { + return css; + } + } + return null; + } + + /** + * Checks whether the given statement is (probably) a DDL statement. The method does not check the + * validity of the statement, only if it is a DDL statement based on the first word in the + * statement. + * + * @param sql The statement to check (without any comments). + * @return true if the statement is a DDL statement (i.e. starts with 'CREATE', + * 'ALTER' or 'DROP'). + */ + boolean isDdlStatement(String sql) { + return statementStartsWith(sql, ddlStatements); + } + + /** + * Checks whether the given statement is (probably) a SELECT query. The method does not check the + * validity of the statement, only if it is a SELECT statement based on the first word in the + * statement. + * + * @param sql The statement to check (without any comments). + * @return true if the statement is a SELECT statement (i.e. starts with 'SELECT'). + */ + boolean isQuery(String sql) { + return statementStartsWith(sql, selectStatements); + } + + /** + * Checks whether the given statement is (probably) an update statement. The method does not check + * the validity of the statement, only if it is an update statement based on the first word in the + * statement. + * + * @param sql The statement to check (without any comments). + * @return true if the statement is a DML update statement (i.e. starts with + * 'INSERT', 'UPDATE' or 'DELETE'). + */ + boolean isUpdateStatement(String sql) { + return statementStartsWith(sql, dmlStatements); + } + + private boolean statementStartsWith(String sql, Iterable checkStatements) { + Preconditions.checkNotNull(sql); + String[] tokens = sql.split("\\s+", 2); + if (tokens.length > 0) { + for (String check : checkStatements) { + if (tokens[0].equalsIgnoreCase(check)) { + return true; + } + } + } + return false; + } + + /** + * Removes comments from and trims the given sql statement. Spanner supports three types of + * comments: + * + *

    + *
  • Single line comments starting with '--' + *
  • Single line comments starting with '#' + *
  • Multi line comments between '/*' and '*/' + *
+ * + * Reference: https://cloud.google.com/spanner/docs/lexical#comments + * + * @param sql The sql statement to remove comments from and to trim. + * @return the sql statement without the comments and leading and trailing spaces. + */ + static String removeCommentsAndTrim(String sql) { + Preconditions.checkNotNull(sql); + final char SINGLE_QUOTE = '\''; + final char DOUBLE_QUOTE = '"'; + final char BACKTICK_QUOTE = '`'; + final char HYPHEN = '-'; + final char DASH = '#'; + final char SLASH = '/'; + final char ASTERIKS = '*'; + boolean isInQuoted = false; + boolean isInSingleLineComment = false; + boolean isInMultiLineComment = false; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + boolean isTripleQuoted = false; + StringBuilder res = new StringBuilder(sql.length()); + int index = 0; + while (index < sql.length()) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && !isTripleQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } else if (c == startQuote) { + if (lastCharWasEscapeChar) { + lastCharWasEscapeChar = false; + } else if (isTripleQuoted) { + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isInQuoted = false; + startQuote = 0; + isTripleQuoted = false; + res.append(c).append(c); + index += 2; + } + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + res.append(c); + } else { + // We are not in a quoted string. + if (isInSingleLineComment) { + if (c == '\n') { + isInSingleLineComment = false; + // Include the line feed in the result. + res.append(c); + } + } else if (isInMultiLineComment) { + if (sql.length() > index + 1 && c == ASTERIKS && sql.charAt(index + 1) == SLASH) { + isInMultiLineComment = false; + index++; + } + } else { + if (c == DASH + || (sql.length() > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN)) { + // This is a single line comment. + isInSingleLineComment = true; + } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERIKS) { + isInMultiLineComment = true; + index++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { + isInQuoted = true; + startQuote = c; + // Check whether it is a triple-quote. + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isTripleQuoted = true; + res.append(c).append(c); + index += 2; + } + } + res.append(c); + } + } + } + index++; + } + if (isInQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } + if (res.length() > 0 && res.charAt(res.length() - 1) == ';') { + res.deleteCharAt(res.length() - 1); + } + return res.toString().trim(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java new file mode 100644 index 000000000000..78cde9aca767 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 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.ResultSet; + +/** + * A result of the execution of a statement. Statements that are executed by the {@link + * Connection#execute(com.google.cloud.spanner.Statement)} method could have different types of + * return values. These are wrapped in a {@link StatementResult}. + */ +interface StatementResult { + + /** + * Enum indicating the type of result that was returned by {@link + * Connection#execute(com.google.cloud.spanner.Statement)} + */ + enum ResultType { + /** + * A result set either returned by a query on Cloud Spanner or a local result set generated by a + * client side statement. + */ + RESULT_SET, + /** An update count returned by Cloud Spanner. */ + UPDATE_COUNT, + /** + * DDL statements and client side statements that set the state of a connection return no + * result. + */ + NO_RESULT; + } + + /** The type of client side statement that was executed. */ + enum ClientSideStatementType { + SHOW_AUTOCOMMIT, + SET_AUTOCOMMIT, + SHOW_READONLY, + SET_READONLY, + SHOW_RETRY_ABORTS_INTERNALLY, + SET_RETRY_ABORTS_INTERNALLY, + SHOW_AUTOCOMMIT_DML_MODE, + SET_AUTOCOMMIT_DML_MODE, + SHOW_STATEMENT_TIMEOUT, + SET_STATEMENT_TIMEOUT, + SHOW_READ_TIMESTAMP, + SHOW_COMMIT_TIMESTAMP, + SHOW_READ_ONLY_STALENESS, + SET_READ_ONLY_STALENESS, + BEGIN, + COMMIT, + ROLLBACK, + SET_TRANSACTION_MODE, + START_BATCH_DDL, + START_BATCH_DML, + RUN_BATCH, + ABORT_BATCH; + } + + /** + * Returns the {@link ResultType} of this result. + * + * @return the result type. + */ + ResultType getResultType(); + + /** + * @return the {@link ClientSideStatementType} that was executed, or null if no such statement was + * executed. + */ + ClientSideStatementType getClientSideStatementType(); + + /** + * Returns the {@link ResultSet} held by this result. May only be called if the type of this + * result is {@link ResultType#RESULT_SET}. + * + * @return the {@link ResultSet} held by this result. + */ + ResultSet getResultSet(); + + /** + * Returns the update count held by this result. May only be called if the type of this result is + * {@link ResultType#UPDATE_COUNT}. + * + * @return the update count held by this result. + */ + Long getUpdateCount(); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java new file mode 100644 index 000000000000..6748311e5582 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java @@ -0,0 +1,187 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import java.util.Arrays; + +/** Implementation of {@link StatementResult} */ +class StatementResultImpl implements StatementResult { + + /** {@link StatementResult} containing a {@link ResultSet} returned by Cloud Spanner. */ + static StatementResult of(ResultSet resultSet) { + return new StatementResultImpl(resultSet, null); + } + + /** + * {@link StatementResult} containing a {@link ResultSet} created by a {@link + * ClientSideStatement}. + */ + static StatementResult of(ResultSet resultSet, ClientSideStatementType clientSideStatementType) { + return new StatementResultImpl(resultSet, clientSideStatementType); + } + + /** {@link StatementResult} containing an update count returned by Cloud Spanner. */ + static StatementResult of(Long updateCount) { + return new StatementResultImpl(updateCount); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one BOOL column and one row that is created by a {@link ClientSideStatement}. + */ + static StatementResult resultSet( + String name, Boolean value, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.bool())), + Arrays.asList(Struct.newBuilder().set(name).to(value).build())), + clientSideStatementType); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one INT64 column and one row that is created by a {@link ClientSideStatement}. + */ + static StatementResult resultSet( + String name, Long value, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.int64())), + Arrays.asList(Struct.newBuilder().set(name).to(value).build())), + clientSideStatementType); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one ARRAY column and one row that is created by a {@link ClientSideStatement}. + */ + static StatementResult resultSet( + String name, long[] values, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.array(Type.int64()))), + Arrays.asList(Struct.newBuilder().set(name).toInt64Array(values).build())), + clientSideStatementType); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one STRING column and one row that is created by a {@link ClientSideStatement}. + */ + static StatementResult resultSet( + String name, String value, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.string())), + Arrays.asList(Struct.newBuilder().set(name).to(value).build())), + clientSideStatementType); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one STRING column containing an {@link Enum} value and one row that is created by a {@link + * ClientSideStatement}. + */ + static StatementResult resultSet( + String name, Enum value, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.string())), + Arrays.asList(Struct.newBuilder().set(name).to(value.toString()).build())), + clientSideStatementType); + } + + /** + * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with + * one TIMESTAMP column and one row that is created by a {@link ClientSideStatement}. + */ + static StatementResult resultSet( + String name, Timestamp value, ClientSideStatementType clientSideStatementType) { + return of( + ResultSets.forRows( + Type.struct(StructField.of(name, Type.timestamp())), + Arrays.asList(Struct.newBuilder().set(name).to(value).build())), + clientSideStatementType); + } + + /** {@link StatementResult} containing no results. */ + static StatementResult noResult() { + return new StatementResultImpl((ClientSideStatementType) null); + } + + /** {@link StatementResult} containing no results created by a {@link ClientSideStatement}. */ + static StatementResult noResult(ClientSideStatementType clientSideStatementType) { + return new StatementResultImpl(clientSideStatementType); + } + + private final ResultType type; + private final ClientSideStatementType clientSideStatementType; + private final ResultSet resultSet; + private final Long updateCount; + + private StatementResultImpl( + ResultSet resultSet, ClientSideStatementType clientSideStatementType) { + this.type = ResultType.RESULT_SET; + this.clientSideStatementType = clientSideStatementType; + this.resultSet = resultSet; + this.updateCount = null; + } + + private StatementResultImpl(Long updateCount) { + this.type = ResultType.UPDATE_COUNT; + this.clientSideStatementType = null; + this.resultSet = null; + this.updateCount = updateCount; + } + + private StatementResultImpl(ClientSideStatementType clientSideStatementType) { + this.type = ResultType.NO_RESULT; + this.clientSideStatementType = clientSideStatementType; + this.resultSet = null; + this.updateCount = null; + } + + @Override + public ResultType getResultType() { + return type; + } + + @Override + public ClientSideStatementType getClientSideStatementType() { + return clientSideStatementType; + } + + @Override + public ResultSet getResultSet() { + ConnectionPreconditions.checkState( + resultSet != null, "This result does not contain a ResultSet"); + return resultSet; + } + + @Override + public Long getUpdateCount() { + ConnectionPreconditions.checkState( + updateCount != null, "This result does not contain an update count"); + return updateCount; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java new file mode 100644 index 000000000000..ae98118c1391 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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; + +/** Enum used to define the transaction type of a {@link Connection} */ +enum TransactionMode { + READ_ONLY_TRANSACTION("READ ONLY"), + READ_WRITE_TRANSACTION("READ WRITE"); + + private final String statementString; + + private TransactionMode(String statement) { + this.statementString = statement; + } + + /** + * Use this method to get the correct format for use in a SQL statement. The SQL statement for + * setting the mode to read-only should for example be without the underscore: + * SET TRANSACTION READ ONLY + * + * @return a string representation of this {@link TransactionMode} that can be used in a SQL + * statement to set the transaction mode. + */ + public String getStatementString() { + return statementString; + } + + @Override + public String toString() { + return statementString; + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java new file mode 100644 index 000000000000..546cd4f27d9c --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 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.Timestamp; +import com.google.cloud.spanner.AbortedException; + +/** + * Cloud Spanner can abort any read/write transaction because of potential deadlocks or other + * internal reasons. When a transaction is aborted, the entire transaction should be retried. A + * {@link Connection} can automatically retry a transaction internally and check whether the results + * that are returned during a retry attempt are equal to the results during the original + * transaction. This is done by keeping track of a SHA-256 checksum of all the results that are + * returned by Spanner during both transactions. + * + *

This listener class for internal transaction retries allow client applications to do + * additional testing or logging of transaction retries. Transaction retry listeners of a {@link + * Connection} can be added using {@link + * Connection#addTransactionRetryListener(TransactionRetryListener)}. + */ +public interface TransactionRetryListener { + /** The result of a retry. */ + public enum RetryResult { + /** The retry executed successfully and the transaction will continue. */ + RETRY_SUCCESSFUL, + /** The retry was aborted by Spanner and another retry attempt will be started. */ + RETRY_ABORTED_AND_RESTARTING, + /** + * The retry was aborted by the {@link Connection} because of a concurrent modification. The + * transaction cannot continue and will throw an {@link + * AbortedDueToConcurrentModificationException}. + */ + RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION, + /** + * The retry was aborted by Spanner and the maximum number of retry attempts allowed has been + * exceeded. The transaction cannot continue and will throw an {@link AbortedException}. + */ + RETRY_ABORTED_AND_MAX_ATTEMPTS_EXCEEDED, + /** + * An unexpected error occurred during transaction retry, the transaction cannot continue and + * will throw an exception. + */ + RETRY_ERROR; + } + + /** + * This method is called when a retry is about to start. + * + * @param transactionStarted The start date/time of the transaction that is retrying. + * @param transactionId An internally assigned ID of the transaction (unique during the lifetime + * of the JVM) that can be used to identify the transaction for logging purposes. + * @param retryAttempt The number of retry attempts the current transaction has executed, + * including the current retry attempt. + */ + void retryStarting(Timestamp transactionStarted, long transactionId, int retryAttempt); + + /** + * This method is called when a retry has finished. + * + * @param transactionStarted The start date/time of the transaction that is retrying. + * @param transactionId An internally assigned ID of the transaction (unique during the lifetime + * of the JVM) that can be used to identify the transaction for logging purposes. + * @param retryAttempt The number of retry attempts the current transaction has executed, + * including the current retry attempt. + * @param result The result of the retry indicating whether the retry was successful or not. + */ + void retryFinished( + Timestamp transactionStarted, + long transactionId, + int retryAttempt, + TransactionRetryListener.RetryResult result); +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java new file mode 100644 index 000000000000..4287981dfce5 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java @@ -0,0 +1,182 @@ +/* + * Copyright 2019 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.api.core.InternalApi; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.spanner.v1.ResultSetStats; + +/** Internal interface for transactions and batches on {@link Connection}s. */ +@InternalApi +interface UnitOfWork { + + /** A unit of work can be either a transaction or a DDL/DML batch. */ + enum Type { + TRANSACTION, + BATCH; + } + + enum UnitOfWorkState { + STARTED, + COMMITTED, + COMMIT_FAILED, + ROLLED_BACK, + RAN, + RUN_FAILED, + ABORTED; + + public boolean isActive() { + return this == STARTED; + } + } + + /** Cancel the currently running statement (if any and the statement may be cancelled). */ + void cancel(); + + /** @return the type of unit of work. */ + Type getType(); + + /** @return the current state of this unit of work. */ + UnitOfWorkState getState(); + + /** @return true if this unit of work is still active. */ + boolean isActive(); + + /** + * Commits the changes in this unit of work to the database. For read-only transactions, this only + * closes the {@link ReadContext}. This method will throw a {@link SpannerException} if called for + * a {@link Type#BATCH}. + */ + void commit(); + + /** + * Rollbacks any changes in this unit of work. For read-only transactions, this only closes the + * {@link ReadContext}. This method will throw a {@link SpannerException} if called for a {@link + * Type#BATCH}. + */ + void rollback(); + + /** + * Sends the currently buffered statements in this unit of work to the database and ends the + * batch. This method will throw a {@link SpannerException} if called for a {@link + * Type#TRANSACTION}. + * + * @return the update counts in case of a DML batch. Returns an array containing 1 for each + * successful statement and 0 for each failed statement or statement that was not executed DDL + * in case of a DDL batch. + */ + long[] runBatch(); + + /** + * Clears the currently buffered statements in this unit of work and ends the batch. This method + * will throw a {@link SpannerException} if called for a {@link Type#TRANSACTION}. + */ + void abortBatch(); + + /** @return true if this unit of work is read-only. */ + boolean isReadOnly(); + + /** + * Executes a query with the given options. If {@link AnalyzeMode} is set to {@link + * AnalyzeMode#PLAN} or {@link AnalyzeMode#PROFILE}, the returned {@link ResultSet} will include + * {@link ResultSetStats}. + * + * @param statement The statement to execute. + * @param analyzeMode Indicates whether to include {@link ResultSetStats} in the returned {@link + * ResultSet} or not. Cannot be used in combination with {@link QueryOption}s. + * @param options the options to configure the query. May only be set if analyzeMode is set to + * {@link AnalyzeMode#NONE}. + * @return a {@link ResultSet} with the results of the query. + * @throws SpannerException if the query is not allowed on this {@link UnitOfWork}, or if a + * database error occurs. + */ + ResultSet executeQuery( + ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options); + + /** + * @return the read timestamp of this transaction. Will throw a {@link SpannerException} if there + * is no read timestamp. + */ + Timestamp getReadTimestamp(); + + /** @return the read timestamp of this transaction or null if there is no read timestamp. */ + Timestamp getReadTimestampOrNull(); + + /** + * @return the commit timestamp of this transaction. Will throw a {@link SpannerException} if + * there is no commit timestamp. + */ + Timestamp getCommitTimestamp(); + + /** @return the commit timestamp of this transaction or null if there is no commit timestamp. */ + Timestamp getCommitTimestampOrNull(); + + /** + * Executes the specified DDL statements in this unit of work. For DDL batches, this will mean + * that the statements are buffered locally and will be sent to Spanner when {@link + * UnitOfWork#commit()} is called. For {@link SingleUseTransaction}s, this will execute the DDL + * statement directly on Spanner. + * + * @param ddl The DDL statement to execute. + */ + void executeDdl(ParsedStatement ddl); + + /** + * Execute a DML statement on Spanner. + * + * @param update The DML statement to execute. + * @return the number of records that were inserted/updated/deleted by this statement. + */ + long executeUpdate(ParsedStatement update); + + /** + * Execute a batch of DML statements on Spanner. + * + * @param updates The DML statements to execute. + * @return an array containing the number of records that were inserted/updated/deleted per + * statement. + * @see TransactionContext#batchUpdate(Iterable) + */ + long[] executeBatchUpdate(Iterable updates); + + /** + * Writes a {@link Mutation} to Spanner. For {@link ReadWriteTransaction}s, this means buffering + * the {@link Mutation} locally and writing the {@link Mutation} to Spanner upon {@link + * UnitOfWork#commit()}. For {@link SingleUseTransaction}s, the {@link Mutation} will be sent + * directly to Spanner. + * + * @param mutation The mutation to write. + */ + void write(Mutation mutation); + + /** + * Writes a batch of {@link Mutation}s to Spanner. For {@link ReadWriteTransaction}s, this means + * buffering the {@link Mutation}s locally and writing the {@link Mutation}s to Spanner upon + * {@link UnitOfWork#commit()}. For {@link SingleUseTransaction}s, the {@link Mutation}s will be + * sent directly to Spanner. + * + * @param mutations The mutations to write. + */ + void write(Iterable mutations); +} diff --git a/java-spanner-jdbc/src/main/resources/META-INF/services/java.sql.Driver b/java-spanner-jdbc/src/main/resources/META-INF/services/java.sql.Driver new file mode 100644 index 000000000000..5a8873f221ee --- /dev/null +++ b/java-spanner-jdbc/src/main/resources/META-INF/services/java.sql.Driver @@ -0,0 +1 @@ +com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json new file mode 100644 index 000000000000..28c20a5b419d --- /dev/null +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json @@ -0,0 +1,246 @@ +{ +"statements": + [ + { + "name": "SHOW VARIABLE AUTOCOMMIT", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+autocommit\\s*\\z", + "method": "statementShowAutocommit", + "exampleStatements": ["show variable autocommit"] + }, + { + "name": "SHOW VARIABLE READONLY", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+readonly\\s*\\z", + "method": "statementShowReadOnly", + "exampleStatements": ["show variable readonly"] + }, + { + "name": "SHOW VARIABLE RETRY_ABORTS_INTERNALLY", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+retry_aborts_internally\\s*\\z", + "method": "statementShowRetryAbortsInternally", + "exampleStatements": ["show variable retry_aborts_internally"], + "examplePrerequisiteStatements": ["set readonly=false", "set autocommit=false"] + }, + { + "name": "SHOW VARIABLE AUTOCOMMIT_DML_MODE", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+autocommit_dml_mode\\s*\\z", + "method": "statementShowAutocommitDmlMode", + "exampleStatements": ["show variable autocommit_dml_mode"] + }, + { + "name": "SHOW VARIABLE STATEMENT_TIMEOUT", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+statement_timeout\\s*\\z", + "method": "statementShowStatementTimeout", + "exampleStatements": ["show variable statement_timeout"] + }, + { + "name": "SHOW VARIABLE READ_TIMESTAMP", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+read_timestamp\\s*\\z", + "method": "statementShowReadTimestamp", + "exampleStatements": ["show variable read_timestamp"], + "examplePrerequisiteStatements": ["set readonly = true", "SELECT 1 AS TEST"] + }, + { + "name": "SHOW VARIABLE COMMIT_TIMESTAMP", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+commit_timestamp\\s*\\z", + "method": "statementShowCommitTimestamp", + "exampleStatements": ["show variable commit_timestamp"], + "examplePrerequisiteStatements": ["update foo set bar=1"] + }, + { + "name": "SHOW VARIABLE READ_ONLY_STALENESS", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+read_only_staleness\\s*\\z", + "method": "statementShowReadOnlyStaleness", + "exampleStatements": ["show variable read_only_staleness"] + }, + { + "name": "BEGIN TRANSACTION", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:begin|start)(?:\\s+transaction)?\\s*\\z", + "method": "statementBeginTransaction", + "exampleStatements": ["begin", "start", "begin transaction", "start transaction"] + }, + { + "name": "COMMIT TRANSACTION", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:commit)(?:\\s+transaction)?\\s*\\z", + "method": "statementCommit", + "exampleStatements": ["commit", "commit transaction"], + "examplePrerequisiteStatements": ["begin transaction"] + }, + { + "name": "ROLLBACK TRANSACTION", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:rollback)(?:\\s+transaction)?\\s*\\z", + "method": "statementRollback", + "exampleStatements": ["rollback", "rollback transaction"], + "examplePrerequisiteStatements": ["begin transaction"] + }, + { + "name": "START BATCH DDL", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:start)(?:\\s+batch)(?:\\s+ddl)\\s*\\z", + "method": "statementStartBatchDdl", + "exampleStatements": ["start batch ddl"] + }, + { + "name": "START BATCH DML", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:start)(?:\\s+batch)(?:\\s+dml)\\s*\\z", + "method": "statementStartBatchDml", + "exampleStatements": ["start batch dml"] + }, + { + "name": "RUN BATCH", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:run)(?:\\s+batch)\\s*\\z", + "method": "statementRunBatch", + "exampleStatements": ["run batch"], + "examplePrerequisiteStatements": ["start batch ddl"] + }, + { + "name": "ABORT BATCH", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*(?:abort)(?:\\s+batch)\\s*\\z", + "method": "statementAbortBatch", + "exampleStatements": ["abort batch"], + "examplePrerequisiteStatements": ["start batch ddl"] + }, + { + "name": "SET AUTOCOMMIT = TRUE|FALSE", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+autocommit\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetAutocommit", + "exampleStatements": ["set autocommit = true", "set autocommit = false"], + "setStatement": { + "propertyName": "AUTOCOMMIT", + "separator": "=", + "allowedValues": "(TRUE|FALSE)", + "converterName": "ClientSideStatementValueConverters$BooleanConverter" + } + }, + { + "name": "SET READONLY = TRUE|FALSE", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+readonly\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetReadOnly", + "exampleStatements": ["set readonly = true", "set readonly = false"], + "setStatement": { + "propertyName": "READONLY", + "separator": "=", + "allowedValues": "(TRUE|FALSE)", + "converterName": "ClientSideStatementValueConverters$BooleanConverter" + } + }, + { + "name": "SET RETRY_ABORTS_INTERNALLY = TRUE|FALSE", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+retry_aborts_internally\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetRetryAbortsInternally", + "exampleStatements": ["set retry_aborts_internally = true", "set retry_aborts_internally = false"], + "examplePrerequisiteStatements": ["set readonly = false", "set autocommit = false"], + "setStatement": { + "propertyName": "RETRY_ABORTS_INTERNALLY", + "separator": "=", + "allowedValues": "(TRUE|FALSE)", + "converterName": "ClientSideStatementValueConverters$BooleanConverter" + } + }, + { + "name": "SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+autocommit_dml_mode\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetAutocommitDmlMode", + "exampleStatements": ["set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'", "set autocommit_dml_mode='TRANSACTIONAL'"], + "setStatement": { + "propertyName": "AUTOCOMMIT_DML_MODE", + "separator": "=", + "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL)'", + "converterName": "ClientSideStatementValueConverters$AutocommitDmlModeConverter" + } + }, + { + "name": "SET STATEMENT_TIMEOUT = ''|NULL", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+statement_timeout\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetStatementTimeout", + "exampleStatements": ["set statement_timeout=null", "set statement_timeout='1s'", "set statement_timeout='100ms'", "set statement_timeout='10000us'", "set statement_timeout='9223372036854775807ns'"], + "setStatement": { + "propertyName": "STATEMENT_TIMEOUT", + "separator": "=", + "allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|NULL)", + "converterName": "ClientSideStatementValueConverters$DurationConverter" + } + }, + { + "name": "SET TRANSACTION READ ONLY|READ WRITE", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+transaction\\s*(?:\\s+)\\s*(.*)\\z", + "method": "statementSetTransactionMode", + "exampleStatements": ["set transaction read only", "set transaction read write"], + "examplePrerequisiteStatements": ["set autocommit = false"], + "setStatement": { + "propertyName": "TRANSACTION", + "separator": "\\s+", + "allowedValues": "(READ\\s+ONLY|READ\\s+WRITE)", + "converterName": "ClientSideStatementValueConverters$TransactionModeConverter" + } + }, + { + "name": "SET READ_ONLY_STALENESS = 'STRONG' | 'MIN_READ_TIMESTAMP ' | 'READ_TIMESTAMP ' | 'MAX_STALENESS s|ms|us|ns' | 'EXACT_STALENESS (s|ms|us|ns)'", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+read_only_staleness\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetReadOnlyStaleness", + "exampleStatements": ["set read_only_staleness='STRONG'", + "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'", + "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'", + "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'", + "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'", + "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'", + "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'", + "set read_only_staleness='MAX_STALENESS 12s'", + "set read_only_staleness='MAX_STALENESS 100ms'", + "set read_only_staleness='MAX_STALENESS 99999us'", + "set read_only_staleness='MAX_STALENESS 10ns'", + "set read_only_staleness='EXACT_STALENESS 15s'", + "set read_only_staleness='EXACT_STALENESS 1500ms'", + "set read_only_staleness='EXACT_STALENESS 15000000us'", + "set read_only_staleness='EXACT_STALENESS 9999ns'"], + "setStatement": { + "propertyName": "READ_ONLY_STALENESS", + "separator": "=", + "allowedValues": "'((STRONG)|(MIN_READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(MAX_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns))|(EXACT_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns)))'", + "converterName": "ClientSideStatementValueConverters$ReadOnlyStalenessConverter" + } + } + ] +} \ No newline at end of file diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql new file mode 100644 index 000000000000..40601611e848 --- /dev/null +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -0,0 +1,78 @@ +/* + * Copyright 2019 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. + */ + +SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, + CASE + WHEN SPANNER_TYPE LIKE 'ARRAY%' THEN 2003 + WHEN SPANNER_TYPE = 'BOOL' THEN 16 + WHEN SPANNER_TYPE LIKE 'BYTES%' THEN -2 + WHEN SPANNER_TYPE = 'DATE' THEN 91 + WHEN SPANNER_TYPE = 'FLOAT64' THEN 8 + WHEN SPANNER_TYPE = 'INT64' THEN -5 + WHEN SPANNER_TYPE LIKE 'STRING%' THEN -9 + WHEN SPANNER_TYPE = 'TIMESTAMP' THEN 93 + END AS DATA_TYPE, + SPANNER_TYPE AS TYPE_NAME, + CASE + WHEN STRPOS(SPANNER_TYPE, '(')=0 THEN + CASE + WHEN SPANNER_TYPE = 'INT64' OR SPANNER_TYPE = 'ARRAY' THEN 19 + WHEN SPANNER_TYPE = 'FLOAT64' OR SPANNER_TYPE = 'ARRAY' THEN 15 + WHEN SPANNER_TYPE = 'BOOL' OR SPANNER_TYPE = 'ARRAY' THEN NULL + WHEN SPANNER_TYPE = 'DATE' OR SPANNER_TYPE = 'ARRAY' THEN 10 + WHEN SPANNER_TYPE = 'TIMESTAMP' OR SPANNER_TYPE = 'ARRAY' THEN 35 + ELSE 0 + END + ELSE CAST(REPLACE(SUBSTR(SPANNER_TYPE, STRPOS(SPANNER_TYPE, '(')+1, STRPOS(SPANNER_TYPE, ')')-STRPOS(SPANNER_TYPE, '(')-1), 'MAX', CASE WHEN UPPER(SPANNER_TYPE) LIKE '%STRING%' THEN '2621440' ELSE '10485760' END) AS INT64) + END AS COLUMN_SIZE, + 0 AS BUFFER_LENGTH, + CASE + WHEN SPANNER_TYPE LIKE '%FLOAT64%' THEN 16 + ELSE NULL + END AS DECIMAL_DIGITS, + CASE + WHEN SPANNER_TYPE LIKE '%INT64%' THEN 10 + WHEN SPANNER_TYPE LIKE '%FLOAT64%' THEN 2 + ELSE NULL + END AS NUM_PREC_RADIX, + CASE + WHEN IS_NULLABLE = 'YES' THEN 1 + WHEN IS_NULLABLE = 'NO' THEN 0 + ELSE 2 + END AS NULLABLE, + NULL AS REMARKS, + NULL AS COLUMN_DEF, + 0 AS SQL_DATA_TYPE, + 0 AS SQL_DATETIME_SUB, + CASE + WHEN (SPANNER_TYPE LIKE 'STRING%' OR SPANNER_TYPE LIKE 'ARRAY getTestTimestampBounds() { + return Arrays.asList( + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(Timestamp.now()), + TimestampBound.ofMinReadTimestamp(Timestamp.now()), + TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), + TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS), + TimestampBound.ofExactStaleness(100L, TimeUnit.MICROSECONDS)); + } + + private void testSetReadOnlyStaleness(final TimestampBound staleness) { + try (Connection connection = getConnection()) { + if (isSetReadOnlyStalenessAllowed(staleness.getMode())) { + log( + "SET READ_ONLY_STALENESS='" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "';"); + connection.setReadOnlyStaleness(staleness); + + log( + "@EXPECT RESULT_SET 'READ_ONLY_STALENESS','" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "'"); + log("SHOW VARIABLE READ_ONLY_STALENESS;"); + assertThat(connection.getReadOnlyStaleness(), is(equalTo(staleness))); + } else { + expectSpannerException( + staleness.getMode() + " should not be allowed", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log( + "SET READ_ONLY_STALENESS='" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "';"); + t.setReadOnlyStaleness(staleness); + } + }, + connection); + } + } + } + + abstract boolean isGetReadOnlyStalenessAllowed(); + + @Test + public void testGetReadOnlyStaleness() { + try (Connection connection = getConnection()) { + if (isGetReadOnlyStalenessAllowed()) { + log("@EXPECT RESULT_SET 'READ_ONLY_STALENESS'"); + log("SHOW VARIABLE READ_ONLY_STALENESS;"); + assertThat(connection.getReadOnlyStaleness(), is(notNullValue())); + } else { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log("SHOW VARIABLE READ_ONLY_STALENESS;"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.getReadOnlyStaleness(); + } + } + } + + abstract boolean isCommitAllowed(); + + @Test + public void testCommit() { + try (Connection connection = getConnection()) { + if (!isCommitAllowed()) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + log("COMMIT;"); + connection.commit(); + } + } + + abstract boolean isRollbackAllowed(); + + @Test + public void testRollback() { + try (Connection connection = getConnection()) { + if (!isRollbackAllowed()) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + log("ROLLBACK;"); + connection.rollback(); + } + } + + abstract boolean expectedIsInTransaction(); + + @Test + public void testIsInTransaction() { + try (Connection connection = getConnection()) { + assertThat(connection.isInTransaction(), is(expectedIsInTransaction())); + } + } + + abstract boolean expectedIsTransactionStarted(); + + @Test + public void testIsTransactionStarted() { + try (Connection connection = getConnection()) { + assertThat(connection.isTransactionStarted(), is(expectedIsTransactionStarted())); + } + } + + abstract boolean isGetReadTimestampAllowed(); + + @Test + public void testGetReadTimestamp() { + try (Connection connection = getConnection()) { + if (isGetReadTimestampAllowed()) { + log("@EXPECT RESULT_SET 'READ_TIMESTAMP'"); + log("SHOW VARIABLE READ_TIMESTAMP;"); + assertThat(connection.getReadTimestamp(), is(notNullValue())); + } else { + log("@EXPECT RESULT_SET 'READ_TIMESTAMP',null"); + log("SHOW VARIABLE READ_TIMESTAMP;"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.getReadTimestamp(); + } + } + } + + abstract boolean isGetCommitTimestampAllowed(); + + @Test + public void testGetCommitTimestamp() { + try (Connection connection = getConnection()) { + if (isGetCommitTimestampAllowed()) { + log("@EXPECT RESULT_SET 'COMMIT_TIMESTAMP'"); + log("SHOW VARIABLE COMMIT_TIMESTAMP;"); + assertThat(connection.getCommitTimestamp(), is(notNullValue())); + } else { + log("@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null"); + log("SHOW VARIABLE COMMIT_TIMESTAMP;"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.getCommitTimestamp(); + } + } + } + + abstract boolean isExecuteAllowed(StatementType type); + + @Test + public void testExecute() { + for (StatementType type : + new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { + testExecute(type); + } + } + + private void testExecute(final StatementType type) { + try (Connection connection = getConnection()) { + if (isExecuteAllowed(type)) { + log(getTestStatement(type).getSql() + ";"); + assertThat(connection.execute(getTestStatement(type)), is(notNullValue())); + } else { + expectSpannerException( + type + " should not be allowed", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log(getTestStatement(type).getSql() + ";"); + t.execute(getTestStatement(type)); + } + }, + connection); + } + } + } + + private Statement getTestStatement(StatementType type) { + switch (type) { + case QUERY: + return Statement.of(SELECT); + case UPDATE: + return Statement.of(UPDATE); + case DDL: + return Statement.of(DDL); + case CLIENT_SIDE: + case UNKNOWN: + default: + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + + @Test + public void testExecuteQuery() { + for (StatementType type : + new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { + testExecuteQuery(type); + } + } + + private void testExecuteQuery(final StatementType type) { + try (Connection connection = getConnection()) { + if (type == StatementType.QUERY && isExecuteAllowed(StatementType.QUERY)) { + log("@EXPECT RESULT_SET 'TEST',1"); + log(getTestStatement(type).getSql() + ";"); + ResultSet rs = connection.executeQuery(getTestStatement(type)); + assertThat(rs, is(notNullValue())); + assertThat(rs.getStats(), is(nullValue())); + } else if (type == StatementType.QUERY) { + // it is a query, but queries are not allowed for this connection state + expectSpannerException( + type + " should not be allowed", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log(getTestStatement(type).getSql() + ";"); + t.executeQuery(getTestStatement(type)); + } + }, + connection, + ErrorCode.FAILED_PRECONDITION); + } else { + expectSpannerException( + type + " should be an invalid argument", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.executeQuery(getTestStatement(type)); + } + }, + connection, + ErrorCode.INVALID_ARGUMENT); + } + } + } + + @Test + public void testAnalyzeQuery() { + for (StatementType type : + new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { + testAnalyzeQuery(type); + } + } + + private void testAnalyzeQuery(final StatementType type) { + // TODO: add log statements when ANALYZE ... sql statements are supported + try (Connection connection = getConnection()) { + for (QueryAnalyzeMode mode : QueryAnalyzeMode.values()) { + final QueryAnalyzeMode currentMode = mode; + if (type == StatementType.QUERY && isExecuteAllowed(StatementType.QUERY)) { + ResultSet rs = connection.analyzeQuery(getTestStatement(type), currentMode); + assertThat(rs, is(notNullValue())); + while (rs.next()) {} + assertThat(rs.getStats(), is(notNullValue())); + } else if (type == StatementType.QUERY) { + // it is a query, but queries are not allowed for this connection state + expectSpannerException( + type + " should not be allowed", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.analyzeQuery(getTestStatement(type), currentMode); + } + }, + connection, + ErrorCode.FAILED_PRECONDITION); + } else { + expectSpannerException( + type + " should be an invalid argument", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.analyzeQuery(getTestStatement(type), currentMode); + } + }, + connection, + ErrorCode.INVALID_ARGUMENT); + } + } + } + } + + @Test + public void testExecuteUpdate() { + for (StatementType type : + new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { + testExecuteUpdate(type); + } + } + + private void testExecuteUpdate(final StatementType type) { + try (Connection connection = getConnection()) { + if (type == StatementType.UPDATE && isExecuteAllowed(StatementType.UPDATE)) { + log("@EXPECT UPDATE_COUNT 1"); + log(getTestStatement(type).getSql() + ";"); + assertThat(connection.executeUpdate(getTestStatement(type)), is(notNullValue())); + } else if (type == StatementType.UPDATE) { + // it is an update statement, but updates are not allowed for this connection state + expectSpannerException( + type + "should not be allowed", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log(getTestStatement(type).getSql() + ";"); + t.executeUpdate(getTestStatement(type)); + } + }, + connection, + ErrorCode.FAILED_PRECONDITION); + } else { + expectSpannerException( + type + " should be an invalid argument", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.executeUpdate(getTestStatement(type)); + } + }, + connection, + ErrorCode.INVALID_ARGUMENT); + } + } + } + + abstract boolean isWriteAllowed(); + + @Test + public void testWrite() { + try (Connection connection = getConnection()) { + if (!isWriteAllowed() || !connection.isAutocommit()) { + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + connection.write(createTestMutation()); + } + } + + @Test + public void testWriteIterable() { + try (Connection connection = getConnection()) { + if (!isWriteAllowed() || !connection.isAutocommit()) { + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + connection.write(Arrays.asList(createTestMutation())); + } + } + + @Test + public void testBufferedWrite() { + try (Connection connection = getConnection()) { + if (!isWriteAllowed() || connection.isAutocommit()) { + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + connection.bufferedWrite(createTestMutation()); + } + } + + @Test + public void testBufferedWriteIterable() { + try (Connection connection = getConnection()) { + if (!isWriteAllowed() || connection.isAutocommit()) { + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + } + connection.bufferedWrite(Arrays.asList(createTestMutation())); + } + } + + private Mutation createTestMutation() { + return Mutation.newInsertBuilder("foo").set("id").to(1L).set("name").to("bar").build(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java new file mode 100644 index 000000000000..1a391dfb24f5 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2019 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 com.google.common.truth.Truth.assertThat; + +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AbstractJdbcWrapperTest { + /** Create a concrete sub class to use for testing. */ + private static class TestWrapper extends AbstractJdbcWrapper { + @Override + public boolean isClosed() throws SQLException { + return false; + } + } + + /** Add a sub class for the test class for testing wrapping. */ + private static class SubTestWrapper extends TestWrapper {} + + @Test + public void testIsWrapperFor() throws SQLException { + TestWrapper subject = new TestWrapper(); + assertThat(subject.isWrapperFor(TestWrapper.class)).isTrue(); + assertThat(subject.isWrapperFor(SubTestWrapper.class)).isFalse(); + assertThat(subject.isWrapperFor(Object.class)).isTrue(); + assertThat(subject.isWrapperFor(getClass())).isFalse(); + + subject = new SubTestWrapper(); + assertThat(subject.isWrapperFor(TestWrapper.class)).isTrue(); + assertThat(subject.isWrapperFor(SubTestWrapper.class)).isTrue(); + assertThat(subject.isWrapperFor(Object.class)).isTrue(); + assertThat(subject.isWrapperFor(getClass())).isFalse(); + } + + @Test + public void testUnwrap() throws SQLException { + TestWrapper subject = new TestWrapper(); + assertThat(unwrapSucceeds(subject, TestWrapper.class)).isTrue(); + assertThat(unwrapSucceeds(subject, SubTestWrapper.class)).isFalse(); + assertThat(unwrapSucceeds(subject, Object.class)).isTrue(); + assertThat(unwrapSucceeds(subject, getClass())).isFalse(); + } + + private static interface CheckedCastChecker { + boolean cast(V val); + } + + private static final class CheckedCastToByteChecker implements CheckedCastChecker { + @Override + public boolean cast(Long val) { + try { + AbstractJdbcWrapper.checkedCastToByte(val); + return true; + } catch (SQLException e) { + return false; + } + } + } + + @Test + public void testCheckedCastToByte() throws SQLException { + CheckedCastToByteChecker checker = new CheckedCastToByteChecker(); + assertThat(checker.cast(0L)).isTrue(); + assertThat(checker.cast(1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Byte.MAX_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Byte.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); + assertThat(checker.cast(-1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Byte.MIN_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Byte.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); + } + + private static final class CheckedCastToShortChecker implements CheckedCastChecker { + @Override + public boolean cast(Long val) { + try { + AbstractJdbcWrapper.checkedCastToShort(val); + return true; + } catch (SQLException e) { + return false; + } + } + } + + @Test + public void testCheckedCastToShort() throws SQLException { + CheckedCastToShortChecker checker = new CheckedCastToShortChecker(); + assertThat(checker.cast(0L)).isTrue(); + assertThat(checker.cast(1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Short.MAX_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Short.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); + assertThat(checker.cast(-1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Short.MIN_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Short.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); + } + + private static final class CheckedCastToIntChecker implements CheckedCastChecker { + @Override + public boolean cast(Long val) { + try { + AbstractJdbcWrapper.checkedCastToInt(val); + return true; + } catch (SQLException e) { + return false; + } + } + } + + @Test + public void testCheckedCastToInt() throws SQLException { + CheckedCastToIntChecker checker = new CheckedCastToIntChecker(); + assertThat(checker.cast(0L)).isTrue(); + assertThat(checker.cast(1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Integer.MAX_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Integer.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); + assertThat(checker.cast(-1L)).isTrue(); + assertThat(checker.cast(Long.valueOf(Integer.MIN_VALUE))).isTrue(); + assertThat(checker.cast(Long.valueOf(Integer.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); + } + + private static final class CheckedCastToFloatChecker implements CheckedCastChecker { + @Override + public boolean cast(Double val) { + try { + AbstractJdbcWrapper.checkedCastToFloat(val); + return true; + } catch (SQLException e) { + return false; + } + } + } + + @Test + public void testCheckedCastToFloat() throws SQLException { + CheckedCastToFloatChecker checker = new CheckedCastToFloatChecker(); + assertThat(checker.cast(0D)).isTrue(); + assertThat(checker.cast(1D)).isTrue(); + assertThat(checker.cast(Double.valueOf(Float.MAX_VALUE))).isTrue(); + assertThat(checker.cast(Double.valueOf(Float.MAX_VALUE) * 2.0D)).isFalse(); + assertThat(checker.cast(Double.MAX_VALUE)).isFalse(); + assertThat(checker.cast(-1D)).isTrue(); + assertThat(checker.cast(Double.valueOf(Float.MIN_VALUE))).isTrue(); + assertThat(checker.cast(Double.valueOf(-Float.MAX_VALUE * 2))).isFalse(); + assertThat(checker.cast(-Double.MAX_VALUE)).isFalse(); + } + + private boolean unwrapSucceeds(AbstractJdbcWrapper subject, Class iface) { + try { + subject.unwrap(iface); + return true; + } catch (SQLException e) { + return false; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java new file mode 100644 index 000000000000..489370364945 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java @@ -0,0 +1,456 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Base class for SQL Script verifiers for both the generic Connection API and JDBC connections + * + *

Simple parser/verifier for sql statements. This verifier is able to parse additional @EXPECT + * statements that defines the expected behavior of a sql statement. Possible uses are: + * + *

    + *
  • @EXPECT NO_RESULT: The following statement should not return a result (no {@link ResultSet} + * and no update count) + *
  • @EXPECT UPDATE_COUNT count: The following statement should return the specified + * update count + *
  • @EXPECT RESULT_SET: The following statement should return a {@link ResultSet} with two + * columns with the names ACTUAL and EXPECTED and containing at least one row. For each row, + * the values of ACTUAL and EXPECTED must be equal + *
  • @EXPECT RESULT_SET 'columnName': The following statement should return a {@link ResultSet} + * with a column with the specified name and containing at least one row (additional columns + * in the {@link ResultSet} are allowed). For each row, the value of the column must be not + * null + *
  • @EXPECT RESULT_SET 'columnName',value: The following statement should return a {@link + * ResultSet} with a column with the specified name and containing at least one row + * (additional columns in the {@link ResultSet} are allowed). For each row, the value of the + * column must be equal to the specified value + *
  • @EXPECT EXCEPTION code ['messagePrefix']: The following statement should throw a {@link + * SpannerException} with the specified code and starting with the (optional) message prefix + *
  • @EXPECT EQUAL 'variable1','variable2': The values of the two given variables should be + * equal. The value of a variable can be set using a @PUT statement. + *
+ * + * The parser can set a temporary variable value using a @PUT statement: + * @PUT 'variable_name'\nSQL statement The SQL statement must be a statement that returns a + * {@link ResultSet} containing exactly one row and one column. + * + *

In addition the verifier can create new connections if the script contains NEW_CONNECTION; + * statements and the verifier has been created with a {@link GenericConnectionProvider}. See {@link + * ConnectionImplGeneratedSqlScriptTest} for an example for this. + */ +public abstract class AbstractSqlScriptVerifier { + private static final Pattern VERIFY_PATTERN = + Pattern.compile( + "(?is)\\s*(?:@EXPECT)\\s+" + + "(?NO_RESULT" + + "|RESULT_SET\\s*(?'.*?'(?,.*?)?)?" + + "|UPDATE_COUNT\\s*(?-?\\d{1,19})" + + "|EXCEPTION\\s*(?(?CANCELLED|UNKNOWN|INVALID_ARGUMENT|DEADLINE_EXCEEDED|NOT_FOUND|ALREADY_EXISTS|PERMISSION_DENIED|UNAUTHENTICATED|RESOURCE_EXHAUSTED|FAILED_PRECONDITION|ABORTED|OUT_OF_RANGE|UNIMPLEMENTED|INTERNAL|UNAVAILABLE|DATA_LOSS)(?:\\s*)(?'.*?')?)" + + "|EQUAL\\s+(?'.+?')\\s*,\\s*(?'.+?')" + + ")" + + "(\\n(?.*))?"); + + private static final String PUT_CONDITION = + "@PUT can only be used in combination with a statement that returns a" + + " result set containing exactly one row and one column"; + private static final Pattern PUT_PATTERN = + Pattern.compile("(?is)\\s*(?:@PUT)\\s+(?'.*?')" + "\\n(?.*)"); + + protected enum ExpectedResultType { + RESULT_SET, + UPDATE_COUNT, + NO_RESULT, + EXCEPTION, + EQUAL; + + StatementResult.ResultType getStatementResultType() { + switch (this) { + case NO_RESULT: + return StatementResult.ResultType.NO_RESULT; + case RESULT_SET: + return StatementResult.ResultType.RESULT_SET; + case UPDATE_COUNT: + return StatementResult.ResultType.UPDATE_COUNT; + case EXCEPTION: + case EQUAL: + default: + throw new IllegalArgumentException("not supported"); + } + } + } + + /** Result of an executed statement */ + protected abstract static class GenericStatementResult { + protected abstract StatementResult.ResultType getResultType(); + + protected abstract GenericResultSet getResultSet(); + + protected abstract long getUpdateCount(); + } + + /** + * Generic wrapper around a connection to a database. The underlying connection could be a Spanner + * {@link com.google.cloud.spanner.jdbc.Connection} or a JDBC {@link java.sql.Connection} + */ + public abstract static class GenericConnection implements AutoCloseable { + protected abstract GenericStatementResult execute(String sql) throws Exception; + + @Override + public abstract void close() throws Exception; + } + + /** + * Generic wrapper around a result set. The underlying result set could be a Spanner {@link + * ResultSet} or a JDBC {@link java.sql.ResultSet} + */ + protected abstract static class GenericResultSet { + protected abstract boolean next() throws Exception; + + protected abstract Object getValue(String col) throws Exception; + + protected abstract int getColumnCount() throws Exception; + + protected abstract Object getFirstValue() throws Exception; + } + + public static interface GenericConnectionProvider { + public GenericConnection getConnection(); + } + + /** Reads SQL statements from a file. Any copyright header in the file will be stripped away. */ + public static List readStatementsFromFile(String filename, Class resourceClass) { + File file = new File(resourceClass.getResource(filename).getFile()); + StringBuilder builder = new StringBuilder(); + try (Scanner scanner = new Scanner(file)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + builder.append(line).append("\n"); + } + scanner.close(); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + String script = builder.toString().replaceAll(StatementParserTest.COPYRIGHT_PATTERN, ""); + String[] array = script.split(";"); + List res = new ArrayList<>(array.length); + for (String statement : array) { + if (statement != null && statement.trim().length() > 0) { + res.add(statement); + } + } + return res; + } + + private final GenericConnectionProvider connectionProvider; + + private final Map variables = new HashMap<>(); + + /** + * Constructor for a verifier that will take a {@link GenericConnection} as a parameter to the + * {@link AbstractSqlScriptVerifier#verifyStatementsInFile(GenericConnection, String, Class, + * boolean)} + */ + public AbstractSqlScriptVerifier() { + this(null); + } + + /** Constructor for a verifier that will use a connection provider for connections */ + public AbstractSqlScriptVerifier(GenericConnectionProvider provider) { + this.connectionProvider = provider; + } + + /** + * Reads sql statements from the specified file name and executes and verifies these. Statements + * that are preceeded by an @EXPECT statement are verified against the @EXPECT specification. + * Statements without an @EXPECT statement will be executed and its result will be ignored, unless + * the statement throws an exception, which will fail the test case. + * + *

The {@link com.google.cloud.spanner.jdbc.Connection}s that the statements are executed on + * must be created by a {@link GenericConnectionProvider} + * + * @param filename The file name containing the statements. Statements must be separated by a + * semicolon (;) + * @param resourceClass The class that should be used to locate the resource specified by the file + * name + * @param logStatements Should the verifier log each statement that is executed and verified to + * standard out + * @throws Exception + */ + public void verifyStatementsInFile(String filename, Class resourceClass, boolean logStatements) + throws Exception { + verifyStatementsInFile( + connectionProvider.getConnection(), filename, resourceClass, logStatements); + } + + /** + * Reads sql statements from the specified file name and executes and verifies these. Statements + * that are preceeded by an @EXPECT statement are verified against the @EXPECT specification. + * Statements without an @EXPECT statement will be executed and its result will be ignored, unless + * the statement throws an exception, which will fail the test case. + * + * @param connection The {@link com.google.cloud.spanner.jdbc.Connection} to execute the + * statements against + * @param filename The file name containing the statements. Statements must be separated by a + * semicolon (;) + * @param resourceClass The class that defines the package where to find the input file + * @param logStatements Should all statements be logged to standard out? + */ + public void verifyStatementsInFile( + GenericConnection connection, String filename, Class resourceClass, boolean logStatements) + throws Exception { + try { + List statements = readStatementsFromFile(filename, resourceClass); + for (String statement : statements) { + String sql = statement.trim(); + if (logStatements) { + System.out.println( + "\n------------------------------------------------------\n" + + new Date() + + " ---- verifying statement:"); + System.out.println(sql); + } + if (sql.equalsIgnoreCase("NEW_CONNECTION")) { + connection.close(); + connection = connectionProvider.getConnection(); + variables.clear(); + } else { + verifyStatement(connection, sql); + } + } + } finally { + if (connection != null) { + connection.close(); + } + } + } + + private void verifyStatement(GenericConnection connection, String statement) throws Exception { + statement = replaceVariables(statement); + String statementWithoutComments = StatementParser.removeCommentsAndTrim(statement); + Matcher verifyMatcher = VERIFY_PATTERN.matcher(statementWithoutComments); + Matcher putMatcher = PUT_PATTERN.matcher(statementWithoutComments); + if (verifyMatcher.matches()) { + String sql = verifyMatcher.group("statement"); + String typeName = verifyMatcher.group("type"); + int endIndex = getFirstSpaceChar(typeName); + ExpectedResultType type = ExpectedResultType.valueOf(typeName.substring(0, endIndex)); + if (type == ExpectedResultType.EXCEPTION) { + String code = verifyMatcher.group("code"); + String messagePrefix = verifyMatcher.group("messagePrefix"); + try { + connection.execute(sql); + fail("expected exception: " + sql); + } catch (Exception e) { + verifyExpectedException(statementWithoutComments, e, code, messagePrefix); + } + } else if (type == ExpectedResultType.EQUAL) { + String variable1 = verifyMatcher.group("variable1"); + String variable2 = verifyMatcher.group("variable2"); + // get rid of the single quotes + variable1 = variable1.substring(1, variable1.length() - 1); + variable2 = variable2.substring(1, variable2.length() - 1); + assertThat( + "No variable with name " + variable1, variables.containsKey(variable1), is(true)); + assertThat( + "No variable with name " + variable2, variables.containsKey(variable2), is(true)); + Object value1 = variables.get(variable1); + Object value2 = variables.get(variable2); + if ((value1 instanceof Timestamp) && (value2 instanceof Timestamp)) { + // read timestamps are rounded + Timestamp ts1 = (Timestamp) value1; + Timestamp ts2 = (Timestamp) value2; + value1 = + Timestamp.ofTimeSecondsAndNanos(ts1.getSeconds(), (ts1.getNanos() / 1000) * 1000); + value2 = + Timestamp.ofTimeSecondsAndNanos(ts2.getSeconds(), (ts2.getNanos() / 1000) * 1000); + } + assertThat(value1, is(equalTo(value2))); + } else { + GenericStatementResult result = connection.execute(sql); + assertThat(statement, result.getResultType(), is(equalTo(type.getStatementResultType()))); + switch (type.getStatementResultType()) { + case NO_RESULT: + break; + case RESULT_SET: + String column = verifyMatcher.group("column"); + if (column == null) { + verifyActualVsExpectedResultSet(statement, result.getResultSet()); + } else { + String value = verifyMatcher.group("value"); + if (value != null) { + String parts[] = column.split(",", 2); + column = parts[0].trim(); + value = parts[1].trim(); + column = column.substring(1, column.length() - 1); + verifyResultSetValue(statement, result.getResultSet(), column, parseValue(value)); + } else { + // get rid of the quotation marks + column = column.substring(1, column.length() - 1); + verifyResultSetColumnNotNull(statement, result.getResultSet(), column); + } + } + break; + case UPDATE_COUNT: + long expectedUpdateCount = Long.valueOf(verifyMatcher.group("count").trim()); + assertThat(statement, result.getUpdateCount(), is(equalTo(expectedUpdateCount))); + break; + } + } + } else if (putMatcher.matches()) { + String sql = putMatcher.group("statement"); + String variable = putMatcher.group("variable"); + // get rid of the single quotes + variable = variable.substring(1, variable.length() - 1); + GenericStatementResult result = connection.execute(sql); + assertThat( + PUT_CONDITION, + result.getResultType(), + is(equalTo(com.google.cloud.spanner.jdbc.StatementResult.ResultType.RESULT_SET))); + GenericResultSet rs = result.getResultSet(); + assertThat(PUT_CONDITION, rs.next(), is(true)); + assertThat(PUT_CONDITION, rs.getColumnCount(), is(equalTo(1))); + variables.put(variable, rs.getFirstValue()); + assertThat(PUT_CONDITION, rs.next(), is(false)); + } else { + // just execute the statement + connection.execute(statement); + } + } + + private String replaceVariables(String sql) { + for (String key : variables.keySet()) { + sql = sql.replaceAll("%%" + key + "%%", variables.get(key).toString()); + } + return sql; + } + + protected abstract void verifyExpectedException( + String statement, Exception e, String code, String messagePrefix); + + private static final Pattern INT64_PATTERN = Pattern.compile("\\d{1,19}"); + private static final Pattern ARRAY_INT64_PATTERN = + Pattern.compile("\\[\\s*\\d{1,19}(\\s*,\\s*\\d{1,19})*\\s*\\]"); + private static final Pattern FLOAT64_PATTERN = Pattern.compile("\\d{1,19}.\\d{1,19}"); + private static final String TS_PREFIX = "ts'"; + private static final String TS_SUFFIX = "'"; + private static final Pattern BOOLEAN_PATTERN = Pattern.compile("(?is)true|false"); + + private Object parseValue(String valueString) { + if (valueString == null || "".equals(valueString) || "null".equalsIgnoreCase(valueString)) { + return null; + } + if (valueString.startsWith("'") && valueString.endsWith("'")) { + return valueString.substring(1, valueString.length() - 1); + } + if (INT64_PATTERN.matcher(valueString).matches()) { + return Long.valueOf(valueString); + } + if (ARRAY_INT64_PATTERN.matcher(valueString).matches()) { + String[] stringArray = valueString.substring(1, valueString.length() - 1).split(","); + List res = new ArrayList<>(); + for (int i = 0; i < stringArray.length; i++) { + res.add(Long.valueOf(stringArray[i])); + } + return res; + } + if (FLOAT64_PATTERN.matcher(valueString).matches()) { + return Double.valueOf(valueString); + } + if (valueString.startsWith(TS_PREFIX) && valueString.endsWith(TS_SUFFIX)) { + try { + return ReadOnlyStalenessUtil.parseRfc3339( + valueString.substring(TS_PREFIX.length(), valueString.length() - TS_SUFFIX.length())); + } catch (IllegalArgumentException e) { + // ignore, apparently not a valid a timestamp after all. + } + } + if (BOOLEAN_PATTERN.matcher(valueString).matches()) { + return Boolean.valueOf(valueString); + } + return valueString; + } + + private int getFirstSpaceChar(String input) { + for (int index = 0; index < input.length(); index++) { + if (Character.isWhitespace(input.charAt(index))) { + return index; + } + } + return input.length(); + } + + private void verifyResultSetColumnNotNull(String statement, GenericResultSet rs, String column) + throws Exception { + int count = 0; + while (rs.next()) { + assertThat(statement, getValue(rs, column), is(notNullValue())); + count++; + } + assertThat(count, is(not(equalTo(0)))); + } + + private void verifyResultSetValue( + String statement, GenericResultSet rs, String column, Object value) throws Exception { + int count = 0; + while (rs.next()) { + if (value == null) { + assertThat(statement, getValue(rs, column), is(nullValue())); + } else { + assertEquals(statement, getValue(rs, column), value); + } + count++; + } + assertThat(count, is(not(equalTo(0)))); + } + + private void verifyActualVsExpectedResultSet(String statement, GenericResultSet rs) + throws Exception { + int count = 0; + while (rs.next()) { + assertThat(statement, getValue(rs, "ACTUAL"), is(equalTo(getValue(rs, "EXPECTED")))); + count++; + } + assertThat(count, is(not(equalTo(0)))); + } + + private Object getValue(GenericResultSet rs, String col) throws Exception { + return rs.getValue(col); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java new file mode 100644 index 000000000000..91b54a961a87 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.AutocommitDmlModeConverter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AutocommitDmlModeConverterTest { + + @Test + public void testConvert() throws CompileException { + String allowedValues = + ReadOnlyStalenessConverterTest.getAllowedValues(AutocommitDmlModeConverter.class); + assertThat(allowedValues, is(notNullValue())); + AutocommitDmlModeConverter converter = new AutocommitDmlModeConverter(allowedValues); + assertThat(converter.convert("transactional"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + assertThat(converter.convert("TRANSACTIONAL"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + assertThat(converter.convert("Transactional"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + + assertThat( + converter.convert("partitioned_non_atomic"), + is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); + assertThat( + converter.convert("Partitioned_Non_Atomic"), + is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); + assertThat( + converter.convert("PARTITIONED_NON_ATOMIC"), + is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); + + assertThat(converter.convert(""), is(nullValue())); + assertThat(converter.convert(" "), is(nullValue())); + assertThat(converter.convert("random string"), is(nullValue())); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java new file mode 100644 index 000000000000..cf7ba02e33cf --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionRunner; +import com.google.cloud.spanner.TransactionRunner.TransactionCallable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class AutocommitDmlModeTest { + private static final String UPDATE = "UPDATE foo SET bar=1"; + private static final String URI = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + + private DatabaseClient dbClient; + private TransactionContext txContext; + + @SuppressWarnings("unchecked") + private ConnectionImpl createConnection(ConnectionOptions options) { + dbClient = mock(DatabaseClient.class); + txContext = mock(TransactionContext.class); + Spanner spanner = mock(Spanner.class); + SpannerPool spannerPool = mock(SpannerPool.class); + when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) + .thenReturn(spanner); + DdlClient ddlClient = mock(DdlClient.class); + TransactionRunner txRunner = mock(TransactionRunner.class); + when(dbClient.readWriteTransaction()).thenReturn(txRunner); + when(txRunner.run(any(TransactionCallable.class))) + .thenAnswer( + new Answer() { + @Override + public Long answer(InvocationOnMock invocation) throws Throwable { + TransactionCallable callable = + (TransactionCallable) invocation.getArguments()[0]; + return callable.run(txContext); + } + }); + + TransactionManager txManager = mock(TransactionManager.class); + when(txManager.begin()).thenReturn(txContext); + when(dbClient.transactionManager()).thenReturn(txManager); + + return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); + } + + @Test + public void testAutocommitDmlModeTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(connection.isAutocommit(), is(true)); + assertThat(connection.isReadOnly(), is(false)); + assertThat(connection.getAutocommitDmlMode(), is(AutocommitDmlMode.TRANSACTIONAL)); + + connection.execute(Statement.of(UPDATE)); + verify(txContext).executeUpdate(Statement.of(UPDATE)); + verify(dbClient, never()).executePartitionedUpdate(Statement.of(UPDATE)); + } + } + + @Test + public void testAutocommitDmlModePartitioned() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(connection.isAutocommit(), is(true)); + assertThat(connection.isReadOnly(), is(false)); + connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + assertThat(connection.getAutocommitDmlMode(), is(AutocommitDmlMode.PARTITIONED_NON_ATOMIC)); + + connection.execute(Statement.of(UPDATE)); + verify(txContext, never()).executeUpdate(Statement.of(UPDATE)); + verify(dbClient).executePartitionedUpdate(Statement.of(UPDATE)); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java new file mode 100644 index 000000000000..4c9447fb198a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.BooleanConverter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class BooleanConverterTest { + + @Test + public void testConvert() throws CompileException { + String allowedValues = ReadOnlyStalenessConverterTest.getAllowedValues(BooleanConverter.class); + assertThat(allowedValues, is(notNullValue())); + BooleanConverter converter = new BooleanConverter(allowedValues); + assertThat(converter.convert("true"), is(equalTo(Boolean.TRUE))); + assertThat(converter.convert("TRUE"), is(equalTo(Boolean.TRUE))); + assertThat(converter.convert("True"), is(equalTo(Boolean.TRUE))); + + assertThat(converter.convert("false"), is(equalTo(Boolean.FALSE))); + assertThat(converter.convert("FALSE"), is(equalTo(Boolean.FALSE))); + assertThat(converter.convert("False"), is(equalTo(Boolean.FALSE))); + + assertThat(converter.convert(""), is(nullValue())); + assertThat(converter.convert(" "), is(nullValue())); + assertThat(converter.convert("random string"), is(nullValue())); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java new file mode 100644 index 000000000000..18a13017ff43 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java @@ -0,0 +1,241 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test that runs a pre-generated sql script for {@link ClientSideStatement}s. The sql script can be + * generated by running mvn -P generate-test-sql-scripts compile It is only necessary + * to generate a new test script if a new {@link ClientSideStatement} has been added, or the + * behavior of an existing {@link ClientSideStatement} has changed. + * + *

This class does not need to be implemented for the client libraries of other programming + * languages. All test cases are covered by the sql file ClientSideStatementsTest.sql. + */ +@RunWith(JUnit4.class) +public class ClientSideStatementsTest { + + @Test + public void testExecuteClientSideStatementsScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile("ClientSideStatementsTest.sql", getClass(), false); + } + + private static final String SCRIPT_FILE = + "src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql"; + private static PrintWriter writer; + + /** Generates the test script file */ + static void generateTestScript() throws Exception { + try { + openLog(); + ClientSideStatements statements = ClientSideStatements.INSTANCE; + for (ClientSideStatementImpl statement : statements.getCompiledStatements()) { + generateTestStatements(statement); + } + } finally { + closeLog(); + } + } + + /** Writes the prerequisite statements + the given sql statement to a script file */ + private static void log(List pre, String sql) { + writeLog("NEW_CONNECTION"); + for (String prerequisite : pre) { + writeLog(prerequisite); + } + writeLog(sql); + } + + /** + * Writes the prerequisite statements + the given sql statement to a script file preceded by + * an @EXPECT EXCEPTION error statement + */ + private static void log(List pre, String statement, ErrorCode error) { + log(pre, "@EXPECT EXCEPTION " + error.name() + "\n" + statement); + } + + /** Writes the actual statement to the script file */ + private static void writeLog(String statement) { + writer.println(statement + ";"); + } + + private static void openLog() { + try { + writer = + new PrintWriter( + new OutputStreamWriter(new FileOutputStream(SCRIPT_FILE, false), "UTF8"), true); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @AfterClass + public static void closeLog() { + if (writer != null) { + writer.close(); + } + } + + static class TestConnectionProvider implements GenericConnectionProvider { + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of( + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build())); + } + } + + /** Generates test statements for all {@link ClientSideStatement}s */ + private static void generateTestStatements(ClientSideStatementImpl statement) { + for (String sql : statement.getExampleStatements()) { + log(statement.getExamplePrerequisiteStatements(), sql); + log(statement.getExamplePrerequisiteStatements(), upper(sql)); + log(statement.getExamplePrerequisiteStatements(), lower(sql)); + log(statement.getExamplePrerequisiteStatements(), withLeadingSpaces(sql)); + log(statement.getExamplePrerequisiteStatements(), withLeadingTabs(sql)); + log(statement.getExamplePrerequisiteStatements(), withLeadingLinefeeds(sql)); + log(statement.getExamplePrerequisiteStatements(), withTrailingSpaces(sql)); + log(statement.getExamplePrerequisiteStatements(), withTrailingTabs(sql)); + log(statement.getExamplePrerequisiteStatements(), withTrailingLinefeeds(sql)); + log(statement.getExamplePrerequisiteStatements(), withSpaces(sql)); + log(statement.getExamplePrerequisiteStatements(), withTabs(sql)); + log(statement.getExamplePrerequisiteStatements(), withLinefeeds(sql)); + + log( + statement.getExamplePrerequisiteStatements(), + withInvalidPrefix(sql), + ErrorCode.INVALID_ARGUMENT); + log( + statement.getExamplePrerequisiteStatements(), + withInvalidSuffix(sql), + ErrorCode.INVALID_ARGUMENT); + + final String[] replacements = { + "%", "_", "&", "$", "@", "!", "*", "(", ")", "-", "+", "-#", "/", "\\", "?", "-/", "/#", + "/-" + }; + for (String replacement : replacements) { + log( + statement.getExamplePrerequisiteStatements(), + withPrefix(replacement, sql), + ErrorCode.INVALID_ARGUMENT); + log( + statement.getExamplePrerequisiteStatements(), + withSuffix(replacement, sql), + ErrorCode.INVALID_ARGUMENT); + log( + statement.getExamplePrerequisiteStatements(), + replaceLastSpaceWith(replacement, sql), + ErrorCode.INVALID_ARGUMENT); + } + } + } + + private static String upper(String statement) { + return statement.toUpperCase(); + } + + private static String lower(String statement) { + return statement.toLowerCase(); + } + + private static String withLeadingSpaces(String statement) { + return " " + statement; + } + + private static String withLeadingTabs(String statement) { + return "\t\t\t" + statement; + } + + private static String withLeadingLinefeeds(String statement) { + return "\n\n\n" + statement; + } + + private static String withTrailingSpaces(String statement) { + return statement + " "; + } + + private static String withTrailingTabs(String statement) { + return statement + "\t\t"; + } + + private static String withTrailingLinefeeds(String statement) { + return statement + "\n\n"; + } + + private static String withSpaces(String statement) { + return statement.replaceAll(" ", " "); + } + + private static String withTabs(String statement) { + return statement.replaceAll(" ", "\t"); + } + + private static String withLinefeeds(String statement) { + // Do not replace spaces inside quotes + Matcher matcher = Pattern.compile("(.*)('.*')").matcher(statement); + if (matcher.matches()) { + return matcher.group(1).replaceAll(" ", "\n") + matcher.group(2); + } + return statement.replaceAll(" ", "\n"); + } + + private static String withInvalidPrefix(String statement) { + return "foo " + statement; + } + + private static String withInvalidSuffix(String statement) { + return statement + " bar"; + } + + private static String withPrefix(String prefix, String statement) { + return prefix + statement; + } + + private static String withSuffix(String suffix, String statement) { + return statement + suffix; + } + + private static String replaceLastSpaceWith(String replacement, String statement) { + if (statement.lastIndexOf(' ') > -1) { + return statement.substring(0, statement.lastIndexOf(' ')) + + replacement + + statement.substring(statement.lastIndexOf(' ') + 1); + } + return statement + replacement; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java new file mode 100644 index 000000000000..3cfd42d7e100 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java @@ -0,0 +1,914 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import java.util.concurrent.TimeUnit; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +/** + * The tests in this class do not need to be implemented for client libraries in other programming + * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql + */ +@RunWith(Enclosed.class) +public class ConnectionImplAutocommitReadOnlyTest { + + public static class ConnectionImplAutocommitReadOnlyNoActionsTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query has been executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadOnlyAfterSelectTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + // no call to next() on ResultSet + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last statement was a query, next() has not yet been called, but as the connection api + // returns a directly executed resultset, the read timestamp is already available + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadOnlyAfterSelectAndResultSetNextTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)).next(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last statement was a query + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadOnlyAfterBeginTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // connection is in read-only mode + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // in a transaction, only exact allowed + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadOnlyAfterTemporaryTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + // readonly + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last action was a transaction that ended with a select query + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadOnlyAfterSetReadOnlyMaxStalenessTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + TimestampBound staleness = TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS); + log( + "SET READ_ONLY_STALENESS='" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "';"); + connection.setReadOnlyStaleness(staleness); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + // readonly + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java new file mode 100644 index 000000000000..304bf8f539d7 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java @@ -0,0 +1,1325 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +/** + * The tests in this class do not need to be implemented for client libraries in other programming + * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql + */ +@RunWith(Enclosed.class) +public class ConnectionImplAutocommitReadWriteTest { + + public static class ConnectionImplAutocommitReadWriteNoActionsTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query has been executed + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterSelectTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + // no next() called + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last statement was a query, next() has not yet been called, but as the connection api + // returns a directly executed resultset, the read timestamp is already available + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterSelectAndResultSetNextTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + // the @expect ensures next() is called + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // the last action was a query that has retrieved data + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterUpdateTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log(UPDATE + ";"); + connection.execute(Statement.of(UPDATE)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return true; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterDdlTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log(DDL + ";"); + connection.execute(Statement.of(DDL)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // there is no transaction + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterBeginTransactionTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // in temporary transaction + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + // default is a read-write transaction + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterTemporaryTransactionTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log(UPDATE + ";"); + connection.execute(Statement.of(UPDATE)); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return true; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return true; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return true; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterBeginReadOnlyTransactionTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log("SET TRANSACTION READ ONLY;"); + connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // in temporary transaction + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + // it's a read-only transaction + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplAutocommitReadWriteAfterStartDdlBatchTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=TRUE;"); + connection.setAutocommit(true); + log("START BATCH DDL;"); + connection.startBatchDdl(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return false; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + // it's a DDL batch + return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return true; + } + + @Override + boolean isAbortBatchAllowed() { + return true; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java new file mode 100644 index 000000000000..6a56250a8785 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2019 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.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * This test executes a SQL script that has been generated from the log of all the subclasses of + * {@link AbstractConnectionImplTest} and covers the same test cases. Its aim is to verify that the + * connection reacts correctly in all possible states (i.e. DML statements should not be allowed + * when the connection is in read-only mode, or when a read-only transaction has started etc.) + * + *

A new test script can be generated by running: mvn -P generate-test-sql-scripts compile + * It is only necessary to generate a new test script if the behavior of {@link + * com.google.cloud.spanner.jdbc.Connection} has changed (for example calling COMMIT is currently + * not allowed in AUTOCOMMIT mode, but this has changed to be a no-op). A new test script must also + * be generated if additional test cases have been added to {@link AbstractConnectionImplTest}. + */ +@RunWith(JUnit4.class) +public class ConnectionImplGeneratedSqlScriptTest { + + static class TestConnectionProvider implements GenericConnectionProvider { + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of( + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder().setUri(ConnectionImplTest.URI).build())); + } + } + + @Test + public void testGeneratedScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile("ConnectionImplGeneratedSqlScriptTest.sql", getClass(), false); + } + + /** + * Generates the test SQL script. It should be noted that running this method multiple times + * without having changed anything in the underlying code, could still yield different script + * files, as the script is generated by running a number of JUnit test cases. The order in which + * these test cases are run is non-deterministic. That means that the generated sql script will + * still contain exactly the same test cases after each generation, but the order of the test + * cases in the script file is equal to the order in which the test cases were run the last time + * the script was generated. It is therefore also not recommended to include this generation in an + * automatic build, but to generate the script only when there has been some fundamental change in + * the code. + * + *

The sql test scripts can be generated by running + * mvn -P generate-test-sql-scripts compile + */ + static void generateTestScript() throws ClassNotFoundException, IOException { + // first make the current script file empty + AbstractConnectionImplTest.emptyScript(); + JUnitCore junit = new JUnitCore(); + Class[] testClasses = getAbstractConnectionImplTestSubclasses(); + Result result = junit.run(testClasses); + if (!result.wasSuccessful()) { + throw new RuntimeException("Generating test script failed!"); + } + } + + private static Class[] getAbstractConnectionImplTestSubclasses() + throws IOException, ClassNotFoundException { + List> list = new ArrayList<>(); + ClassPath cp = ClassPath.from(ConnectionImplGeneratedSqlScriptTest.class.getClassLoader()); + ImmutableSet classes = + cp.getTopLevelClassesRecursive( + ConnectionImplGeneratedSqlScriptTest.class.getPackage().getName()); + for (ClassInfo c : classes) { + Class clazz = + ConnectionImplGeneratedSqlScriptTest.class.getClassLoader().loadClass(c.getName()); + addAbstractConnectionImplTestSubclassesToList(list, clazz); + } + Class[] res = new Class[list.size()]; + for (int i = 0; i < list.size(); i++) { + res[i] = list.get(i); + } + return res; + } + + private static void addAbstractConnectionImplTestSubclassesToList( + List> list, Class clazz) { + for (Class innerClass : clazz.getDeclaredClasses()) { + addAbstractConnectionImplTestSubclassesToList(list, innerClass); + } + if (!clazz.isInterface() + && !Modifier.isAbstract(clazz.getModifiers()) + && AbstractConnectionImplTest.class.isAssignableFrom(clazz)) { + list.add(clazz); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java new file mode 100644 index 000000000000..87190f715d0b --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java @@ -0,0 +1,1117 @@ +/* + * Copyright 2019 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 com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.DDL; +import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.SELECT; +import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.UPDATE; +import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.expectSpannerException; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.NoCredentials; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ForwardingResultSet; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionRunner; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.ConnectionConsumer; +import com.google.cloud.spanner.jdbc.ConnectionImpl.UnitOfWorkType; +import com.google.cloud.spanner.jdbc.ConnectionStatementExecutorImpl.StatementTimeoutGetter; +import com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.GetExactStaleness; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.v1.ResultSetStats; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Matchers; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class ConnectionImplTest { + public static final String URI = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + + static class SimpleTransactionManager implements TransactionManager { + private TransactionState state; + private Timestamp commitTimestamp; + private TransactionContext txContext; + + private SimpleTransactionManager(TransactionContext txContext) { + this.txContext = txContext; + } + + @Override + public TransactionContext begin() { + state = TransactionState.STARTED; + return txContext; + } + + @Override + public void commit() { + commitTimestamp = Timestamp.now(); + state = TransactionState.COMMITTED; + } + + @Override + public void rollback() { + state = TransactionState.ROLLED_BACK; + } + + @Override + public TransactionContext resetForRetry() { + return txContext; + } + + @Override + public Timestamp getCommitTimestamp() { + return commitTimestamp; + } + + @Override + public TransactionState getState() { + return state; + } + + @Override + public void close() { + if (state != TransactionState.COMMITTED) { + state = TransactionState.ROLLED_BACK; + } + } + } + + private static class SimpleResultSet extends ForwardingResultSet { + private boolean nextCalled = false; + private boolean onValidRow = false; + private boolean hasNextReturnedFalse = false; + + SimpleResultSet(ResultSet delegate) { + super(delegate); + } + + @Override + public boolean next() { + nextCalled = true; + onValidRow = super.next(); + hasNextReturnedFalse = !onValidRow; + return onValidRow; + } + + boolean isNextCalled() { + return nextCalled; + } + + @Override + public ResultSetStats getStats() { + if (hasNextReturnedFalse) { + return super.getStats(); + } + return null; + } + + @Override + public long getLong(int columnIndex) { + if (onValidRow) { + return super.getLong(columnIndex); + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "ResultSet is not positioned on a valid row"); + } + } + + private static ResultSet createSelect1MockResultSet() { + ResultSet mockResultSet = mock(ResultSet.class); + when(mockResultSet.next()).thenReturn(true, false); + when(mockResultSet.getLong(0)).thenReturn(1L); + when(mockResultSet.getLong("TEST")).thenReturn(1L); + when(mockResultSet.getColumnType(0)).thenReturn(Type.int64()); + when(mockResultSet.getColumnType("TEST")).thenReturn(Type.int64()); + return mockResultSet; + } + + private static DdlClient createDefaultMockDdlClient() { + try { + DdlClient ddlClient = mock(DdlClient.class); + @SuppressWarnings("unchecked") + final OperationFuture operation = + mock(OperationFuture.class); + when(operation.get()).thenReturn(null); + UpdateDatabaseDdlMetadata metadata = UpdateDatabaseDdlMetadata.getDefaultInstance(); + ApiFuture futureMetadata = ApiFutures.immediateFuture(metadata); + when(operation.getMetadata()).thenReturn(futureMetadata); + when(ddlClient.executeDdl(anyString())).thenCallRealMethod(); + when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); + return ddlClient; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static ConnectionImpl createConnection(ConnectionOptions options) { + Spanner spanner = mock(Spanner.class); + SpannerPool spannerPool = mock(SpannerPool.class); + when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) + .thenReturn(spanner); + DdlClient ddlClient = createDefaultMockDdlClient(); + DatabaseClient dbClient = mock(DatabaseClient.class); + ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); + + ResultSet mockResultSetWithStats = createSelect1MockResultSet(); + when(mockResultSetWithStats.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); + + final SimpleResultSet select1ResultSet = new SimpleResultSet(createSelect1MockResultSet()); + final SimpleResultSet select1ResultSetWithStats = new SimpleResultSet(mockResultSetWithStats); + when(singleUseReadOnlyTx.executeQuery(Statement.of(SELECT))) + .thenAnswer( + new Answer() { + @Override + public ResultSet answer(InvocationOnMock invocation) throws Throwable { + if (select1ResultSet.nextCalled) { + // create a new mock + return new SimpleResultSet(createSelect1MockResultSet()); + } + return select1ResultSet; + } + }); + when(singleUseReadOnlyTx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) + .thenReturn(select1ResultSetWithStats); + when(singleUseReadOnlyTx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) + .thenReturn(select1ResultSetWithStats); + when(singleUseReadOnlyTx.getReadTimestamp()) + .then( + new Answer() { + @Override + public Timestamp answer(InvocationOnMock invocation) throws Throwable { + if (select1ResultSet.isNextCalled() || select1ResultSetWithStats.isNextCalled()) { + return Timestamp.now(); + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "No query has returned with any data yet"); + } + }); + when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) + .thenReturn(singleUseReadOnlyTx); + + when(dbClient.transactionManager()) + .thenAnswer( + new Answer() { + @Override + public TransactionManager answer(InvocationOnMock invocation) throws Throwable { + TransactionContext txContext = mock(TransactionContext.class); + when(txContext.executeQuery(Statement.of(SELECT))) + .thenAnswer( + new Answer() { + @Override + public ResultSet answer(InvocationOnMock invocation) throws Throwable { + if (select1ResultSet.nextCalled) { + // create a new mock + return new SimpleResultSet(createSelect1MockResultSet()); + } + return select1ResultSet; + } + }); + when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) + .thenReturn(select1ResultSetWithStats); + when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) + .thenReturn(select1ResultSetWithStats); + when(txContext.executeUpdate(Statement.of(UPDATE))).thenReturn(1L); + return new SimpleTransactionManager(txContext); + } + }); + + when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))) + .thenAnswer( + new Answer() { + @Override + public ReadOnlyTransaction answer(InvocationOnMock invocation) throws Throwable { + ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class); + when(tx.executeQuery(Statement.of(SELECT))) + .thenAnswer( + new Answer() { + @Override + public ResultSet answer(InvocationOnMock invocation) throws Throwable { + if (select1ResultSet.nextCalled) { + // create a new mock + return new SimpleResultSet(createSelect1MockResultSet()); + } + return select1ResultSet; + } + }); + when(tx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) + .thenReturn(select1ResultSetWithStats); + when(tx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) + .thenReturn(select1ResultSetWithStats); + when(tx.getReadTimestamp()) + .then( + new Answer() { + @Override + public Timestamp answer(InvocationOnMock invocation) throws Throwable { + if (select1ResultSet.isNextCalled() + || select1ResultSetWithStats.isNextCalled()) { + return Timestamp.now(); + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, + "No query has returned with any data yet"); + } + }); + return tx; + } + }); + + when(dbClient.readWriteTransaction()) + .thenAnswer( + new Answer() { + @Override + public TransactionRunner answer(InvocationOnMock invocation) throws Throwable { + TransactionRunner runner = + new TransactionRunner() { + private Timestamp commitTimestamp; + + @SuppressWarnings("unchecked") + @Override + public T run(TransactionCallable callable) { + this.commitTimestamp = Timestamp.now(); + return (T) Long.valueOf(1L); + } + + @Override + public Timestamp getCommitTimestamp() { + return commitTimestamp; + } + + @Override + public TransactionRunner allowNestedTransaction() { + return this; + } + }; + return runner; + } + }); + return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); + } + + @Test + public void testExecuteSetAutocommitOn() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI + ";autocommit=false") + .build())) { + assertThat(subject.isAutocommit(), is(false)); + + StatementResult res = subject.execute(Statement.of("set autocommit = true")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isAutocommit(), is(true)); + } + } + + @Test + public void testExecuteSetAutocommitOff() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + + StatementResult res = subject.execute(Statement.of("set autocommit = false")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isAutocommit(), is(false)); + } + } + + @Test + public void testExecuteGetAutocommit() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + + // assert that autocommit is true (default) + assertThat(subject.isAutocommit(), is(true)); + StatementResult res = subject.execute(Statement.of("show variable autocommit")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getBoolean("AUTOCOMMIT"), is(true)); + + // set autocommit to false and assert that autocommit is false + res = subject.execute(Statement.of("set autocommit = false")); + assertThat(subject.isAutocommit(), is(false)); + res = subject.execute(Statement.of("show variable autocommit")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getBoolean("AUTOCOMMIT"), is(false)); + } + } + + @Test + public void testExecuteSetReadOnlyOn() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isReadOnly(), is(false)); + + StatementResult res = subject.execute(Statement.of("set readonly = true")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isReadOnly(), is(true)); + } + } + + @Test + public void testExecuteSetReadOnlyOff() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI + ";readonly=true") + .build())) { + assertThat(subject.isReadOnly(), is(true)); + + StatementResult res = subject.execute(Statement.of("set readonly = false")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isReadOnly(), is(false)); + } + } + + @Test + public void testExecuteGetReadOnly() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + + // assert that read only is false (default) + assertThat(subject.isReadOnly(), is(false)); + StatementResult res = subject.execute(Statement.of("show variable readonly")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getBoolean("READONLY"), is(false)); + + // set read only to true and assert that read only is true + res = subject.execute(Statement.of("set readonly = true")); + assertThat(subject.isReadOnly(), is(true)); + res = subject.execute(Statement.of("show variable readonly")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getBoolean("READONLY"), is(true)); + } + } + + @Test + public void testExecuteSetAutocommitDmlMode() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + + StatementResult res = + subject.execute(Statement.of("set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat( + subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); + + res = subject.execute(Statement.of("set autocommit_dml_mode='TRANSACTIONAL'")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + } + } + + @Test + public void testExecuteSetAutocommitDmlModeInvalidValue() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + + ErrorCode expected = null; + try { + subject.execute(Statement.of("set autocommit_dml_mode='NON_EXISTENT_VALUE'")); + } catch (SpannerException e) { + expected = e.getErrorCode(); + } + assertThat(expected, is(equalTo(ErrorCode.INVALID_ARGUMENT))); + } + } + + @Test + public void testExecuteGetAutocommitDmlMode() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); + + StatementResult res = subject.execute(Statement.of("show variable autocommit_dml_mode")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat( + res.getResultSet().getString("AUTOCOMMIT_DML_MODE"), + is(equalTo(AutocommitDmlMode.TRANSACTIONAL.toString()))); + + subject.execute(Statement.of("set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'")); + res = subject.execute(Statement.of("show variable autocommit_dml_mode")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat( + res.getResultSet().getString("AUTOCOMMIT_DML_MODE"), + is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC.toString()))); + } + } + + @Test + public void testExecuteSetStatementTimeout() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); + + for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { + for (Long timeout : new Long[] {1L, 100L, 10000L, 315576000000L}) { + StatementResult res = + subject.execute( + Statement.of( + String.format( + "set statement_timeout='%d%s'", + timeout, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getStatementTimeout(unit), is(equalTo(timeout))); + assertThat(subject.hasStatementTimeout(), is(true)); + + StatementResult resNoTimeout = + subject.execute(Statement.of("set statement_timeout=null")); + assertThat(resNoTimeout.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getStatementTimeout(unit), is(equalTo(0L))); + assertThat(subject.hasStatementTimeout(), is(false)); + } + } + } + } + + @Test + public void testExecuteSetStatementTimeoutInvalidValue() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); + + ErrorCode expected = null; + try { + subject.execute(Statement.of("set statement_timeout=-1")); + } catch (SpannerException e) { + expected = e.getErrorCode(); + } + assertThat(expected, is(equalTo(ErrorCode.INVALID_ARGUMENT))); + } + } + + @Test + public void testExecuteGetStatementTimeout() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); + + for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { + for (Long timeout : new Long[] {1L, 100L, 10000L, 315576000000L}) { + subject.execute( + Statement.of( + String.format( + "set statement_timeout='%d%s'", + timeout, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); + StatementResult res = subject.execute(Statement.of("show variable statement_timeout")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + TimeUnit appropriateUnit = + ReadOnlyStalenessUtil.getAppropriateTimeUnit(new StatementTimeoutGetter(subject)); + assertThat( + res.getResultSet().getString("STATEMENT_TIMEOUT"), + is( + equalTo( + subject.getStatementTimeout(appropriateUnit) + + ReadOnlyStalenessUtil.getTimeUnitAbbreviation(appropriateUnit)))); + + subject.execute(Statement.of("set statement_timeout=null")); + StatementResult resNoTimeout = + subject.execute(Statement.of("show variable statement_timeout")); + assertThat(resNoTimeout.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(resNoTimeout.getResultSet().next(), is(true)); + assertThat(resNoTimeout.getResultSet().isNull("STATEMENT_TIMEOUT"), is(true)); + } + } + } + } + + @Test + public void testExecuteGetReadTimestamp() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.beginTransaction(); + subject.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + subject.executeQuery(Statement.of(AbstractConnectionImplTest.SELECT)); + StatementResult res = subject.execute(Statement.of("show variable read_timestamp")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getTimestamp("READ_TIMESTAMP"), is(notNullValue())); + subject.commit(); + } + } + + @Test + public void testExecuteGetCommitTimestamp() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.beginTransaction(); + subject.executeQuery(Statement.of(AbstractConnectionImplTest.SELECT)).next(); + subject.commit(); + StatementResult res = subject.execute(Statement.of("show variable commit_timestamp")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getTimestamp("COMMIT_TIMESTAMP"), is(notNullValue())); + } + } + + private static final class StalenessDuration { + private final long duration; + private final TimeUnit unit; + + private StalenessDuration(long duration, TimeUnit unit) { + this.duration = duration; + this.unit = unit; + } + + @Override + public String toString() { + GetExactStaleness getExactStalenessFunction = + new GetExactStaleness(TimestampBound.ofExactStaleness(duration, unit)); + return ReadOnlyStalenessUtil.durationToString(getExactStalenessFunction); + } + } + + @Test + public void testExecuteGetReadOnlyStaleness() { + Map timestamps = new HashMap<>(); + timestamps.put(Mode.READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:05:10Z")); + timestamps.put( + Mode.MIN_READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:05:10.12345Z")); + Map durations = new HashMap<>(); + durations.put(Mode.EXACT_STALENESS, new StalenessDuration(1000L, TimeUnit.MILLISECONDS)); + durations.put(Mode.MAX_STALENESS, new StalenessDuration(1234567L, TimeUnit.MICROSECONDS)); + List stalenesses = + Arrays.asList( + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(timestamps.get(Mode.READ_TIMESTAMP)), + TimestampBound.ofMinReadTimestamp(timestamps.get(Mode.MIN_READ_TIMESTAMP)), + TimestampBound.ofExactStaleness( + durations.get(Mode.EXACT_STALENESS).duration, + durations.get(Mode.EXACT_STALENESS).unit), + TimestampBound.ofMaxStaleness( + durations.get(Mode.MAX_STALENESS).duration, + durations.get(Mode.MAX_STALENESS).unit)); + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + for (TimestampBound staleness : stalenesses) { + subject.setReadOnlyStaleness(staleness); + StatementResult res = subject.execute(Statement.of("show variable read_only_staleness")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat( + res.getResultSet().getString("READ_ONLY_STALENESS"), + is(equalTo(ReadOnlyStalenessUtil.timestampBoundToString(staleness)))); + } + } + } + + @Test + public void testExecuteSetReadOnlyStaleness() { + Map timestamps = new HashMap<>(); + timestamps.put(Mode.READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T12:13:14Z")); + timestamps.put( + Mode.MIN_READ_TIMESTAMP, + ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:13:14.1234+02:00")); + Map durations = new HashMap<>(); + durations.put(Mode.EXACT_STALENESS, new StalenessDuration(1000L, TimeUnit.MILLISECONDS)); + durations.put(Mode.MAX_STALENESS, new StalenessDuration(1234567L, TimeUnit.MICROSECONDS)); + List stalenesses = + Arrays.asList( + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(timestamps.get(Mode.READ_TIMESTAMP)), + TimestampBound.ofMinReadTimestamp(timestamps.get(Mode.MIN_READ_TIMESTAMP)), + TimestampBound.ofExactStaleness( + durations.get(Mode.EXACT_STALENESS).duration, + durations.get(Mode.EXACT_STALENESS).unit), + TimestampBound.ofMaxStaleness( + durations.get(Mode.MAX_STALENESS).duration, + durations.get(Mode.MAX_STALENESS).unit)); + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + for (TimestampBound staleness : stalenesses) { + StatementResult res = + subject.execute( + Statement.of( + String.format( + "set read_only_staleness='%s'", + ReadOnlyStalenessUtil.timestampBoundToString(staleness)))); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getReadOnlyStaleness(), is(equalTo(staleness))); + } + } + } + + @Test + public void testExecuteBeginTransaction() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isInTransaction(), is(false)); + + StatementResult res = subject.execute(Statement.of("begin transaction")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isInTransaction(), is(true)); + } + } + + @Test + public void testExecuteCommitTransaction() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.execute(Statement.of("begin transaction")); + assertThat(subject.isInTransaction(), is(true)); + + StatementResult res = subject.execute(Statement.of("commit")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isInTransaction(), is(false)); + } + } + + @Test + public void testExecuteRollbackTransaction() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.execute(Statement.of("begin")); + assertThat(subject.isInTransaction(), is(true)); + + StatementResult res = subject.execute(Statement.of("rollback")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.isInTransaction(), is(false)); + } + } + + @Test + public void testExecuteSetTransactionReadOnly() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.execute(Statement.of("begin")); + assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat(subject.isInTransaction(), is(true)); + + StatementResult res = subject.execute(Statement.of("set transaction read only")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + } + } + + @Test + public void testExecuteSetTransactionReadWrite() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI + ";readonly=true") + .build())) { + subject.execute(Statement.of("begin")); + assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat(subject.isInTransaction(), is(true)); + + // end the current temporary transaction and turn off read-only mode + subject.execute(Statement.of("commit")); + subject.execute(Statement.of("set readonly = false")); + + subject.execute(Statement.of("begin")); + StatementResult res = subject.execute(Statement.of("set transaction read only")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + res = subject.execute(Statement.of("set transaction read write")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + } + } + + @Test + public void testExecuteStartDdlBatch() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + StatementResult res = subject.execute(Statement.of("start batch ddl")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getUnitOfWorkType(), is(equalTo(UnitOfWorkType.DDL_BATCH))); + assertThat(subject.isInTransaction(), is(false)); + } + } + + @Test + public void testDefaultIsAutocommit() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + assertThat(subject.isInTransaction(), is(false)); + } + } + + @Test + public void testDefaultIsReadWrite() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isReadOnly(), is(false)); + } + } + + @Test + public void testDefaultTransactionIsReadWrite() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + for (boolean autocommit : new Boolean[] {true, false}) { + subject.setAutocommit(autocommit); + subject.execute(Statement.of("begin")); + assertThat( + subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + subject.commit(); + + subject.execute(Statement.of("begin")); + subject.execute(Statement.of("set transaction read only")); + assertThat( + subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + subject.commit(); + + subject.execute(Statement.of("begin")); + assertThat( + subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + subject.commit(); + + subject.execute(Statement.of("start batch ddl")); + assertThat(subject.getUnitOfWorkType(), is(equalTo(UnitOfWorkType.DDL_BATCH))); + subject.runBatch(); + + subject.execute(Statement.of("begin")); + assertThat( + subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + subject.commit(); + } + } + } + + @Test + public void testDefaultTransactionIsReadOnly() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI + ";readOnly=true") + .build())) { + for (boolean autocommit : new Boolean[] {true, false}) { + subject.setAutocommit(autocommit); + subject.execute(Statement.of("begin")); + assertThat( + subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + subject.commit(); + } + } + } + + /** + * ReadOnlyStaleness is a session setting for a connection. However, certain settings are only + * allowed when the connection is in autocommit mode. The setting therefore must be reset to its + * default {@link TimestampBound#strong()} when the current setting is not compatible with + * transactional mode. + */ + @Test + public void testResetReadOnlyStaleness() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.isAutocommit(), is(true)); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + + // the following values are always allowed + subject.setReadOnlyStaleness(TimestampBound.strong()); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + subject.setAutocommit(false); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + subject.setAutocommit(true); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + + subject.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)); + subject.setAutocommit(false); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)))); + subject.setAutocommit(true); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)))); + + subject.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + subject.setAutocommit(false); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); + subject.setAutocommit(true); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); + + // the following values are only allowed in autocommit mode. Turning off autocommit will + // return the setting to its default + subject.setReadOnlyStaleness(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)))); + subject.setAutocommit(false); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + subject.setAutocommit(true); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + + subject.setReadOnlyStaleness(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)); + assertThat( + subject.getReadOnlyStaleness(), + is(equalTo(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)))); + subject.setAutocommit(false); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + subject.setAutocommit(true); + assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); + } + } + + @Test + public void testChangeReadOnlyModeInAutocommit() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.execute(Statement.of(UPDATE)); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + + // change to read-only + subject.setReadOnly(true); + expectSpannerException( + "Updates should not be allowed in read-only mode", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.execute(Statement.of(UPDATE)); + } + }, + subject); + assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); + + // change back to read-write + subject.setReadOnly(false); + subject.execute(Statement.of(UPDATE)); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + + // and back to read-only + subject.setReadOnly(true); + expectSpannerException( + "DDL should not be allowed in read-only mode", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.execute(Statement.of(DDL)); + } + }, + subject); + assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); + } + } + + @Test + public void testChangeReadOnlyModeInTransactionalMode() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + subject.setAutocommit(false); + + subject.execute(Statement.of(UPDATE)); + subject.commit(); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + + // change to read-only + subject.setReadOnly(true); + expectSpannerException( + "Updates should not be allowed in read-only mode", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.execute(Statement.of(UPDATE)); + } + }, + subject); + assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); + subject.commit(); + + // change back to read-write + subject.setReadOnly(false); + subject.execute(Statement.of(UPDATE)); + subject.commit(); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + + // and back to read-only + subject.setReadOnly(true); + expectSpannerException( + "DDL should not be allowed in read-only mode", + new ConnectionConsumer() { + @Override + public void accept(Connection t) { + t.execute(Statement.of(DDL)); + } + }, + subject); + assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); + } + } + + @Test + public void testAddRemoveTransactionRetryListener() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getTransactionRetryListeners().hasNext(), is(false)); + TransactionRetryListener listener = mock(TransactionRetryListener.class); + subject.addTransactionRetryListener(listener); + assertThat(subject.getTransactionRetryListeners().hasNext(), is(true)); + assertThat(subject.removeTransactionRetryListener(listener), is(true)); + assertThat(subject.getTransactionRetryListeners().hasNext(), is(false)); + assertThat(subject.removeTransactionRetryListener(listener), is(false)); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java new file mode 100644 index 000000000000..99c959083cd3 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java @@ -0,0 +1,1204 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import java.util.concurrent.TimeUnit; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +/** + * The tests in this class do not need to be implemented for client libraries in other programming + * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql + */ +@RunWith(Enclosed.class) +public class ConnectionImplTransactionalReadOnlyTest { + + public static class ConnectionImplTransactionalReadOnlyNoActionsTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query has been executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterSelectTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + // no call to next() on ResultSet + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // transaction has started + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return true; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last statement was a query, next() has not yet been called, but as the connection api + // returns a directly executed resultset, the read timestamp is already available + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterSelectAndResultSetNextTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)).next(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // transaction is running + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // transaction has started + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return true; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last statement was a query + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterBeginTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // connection is in read-only mode + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // in a transaction, only exact allowed + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last action was a transaction that ended with a select query + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterRollbackTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("ROLLBACK;"); + connection.rollback(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // transaction was rolled back + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterSetReadOnlyMaxStalenessTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + TimestampBound staleness = TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS); + log( + "SET READ_ONLY_STALENESS='" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "';"); + connection.setReadOnlyStaleness(staleness); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadOnlyAfterEmptyCommitTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=TRUE;"); + connection.setReadOnly(true); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return mode == TransactionMode.READ_ONLY_TRANSACTION; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last commit was empty + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // read-only + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java new file mode 100644 index 000000000000..ff58828eae3d --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java @@ -0,0 +1,1945 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import java.util.concurrent.TimeUnit; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +/** + * The tests in this class do not need to be implemented for client libraries in other programming + * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql + */ +@RunWith(Enclosed.class) +public class ConnectionImplTransactionalReadWriteTest { + + public static class ConnectionImplTransactionalReadWriteNoActionsTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query has been executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterSelectTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + // no call to next() on ResultSet + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // transaction has started + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return true; + } + + @Override + boolean isGetReadTimestampAllowed() { + // read-write transactions never have a read-timestamp + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterSelectAndResultSetNextTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.executeQuery(Statement.of(SELECT)).next(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + // transaction is running + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // transaction has started + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return true; + } + + @Override + boolean isGetReadTimestampAllowed() { + // read-write transactions never have a read-timestamp + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterBeginTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalArgumentException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + // in a transaction, only exact allowed + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // read-write transaction never have a read-timestamp + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // last action was a read-write transaction + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return true; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterRollbackTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("BEGIN TRANSACTION;"); + connection.beginTransaction(); + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("ROLLBACK;"); + connection.rollback(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // transaction was rolled back + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterSetReadOnlyMaxStalenessTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + TimestampBound staleness = TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS); + log( + "SET READ_ONLY_STALENESS='" + + ReadOnlyStalenessUtil.timestampBoundToString(staleness) + + "';"); + connection.setReadOnlyStaleness(staleness); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterSetTransactionReadOnlyTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("SET TRANSACTION READ ONLY;"); + connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterCommittedReadOnlyTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("SET TRANSACTION READ ONLY;"); + connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + // ensure there will be a read-timestamp available by calling next() + log("@EXPECT RESULT_SET 'TEST',1"); + log(SELECT + ";"); + connection.execute(Statement.of(SELECT)).getResultSet().next(); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return true; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // last transaction was a read-only transaction + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterStartDdlBatchTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("START BATCH DDL;"); + connection.startBatchDdl(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return false; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // no commit yet + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return true; + } + + @Override + boolean isAbortBatchAllowed() { + return true; + } + } + + public static class ConnectionImplTransactionalReadWriteInDdlBatchTransactionTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("START BATCH DDL;"); + connection.startBatchDdl(); + log(DDL + ";"); + connection.execute(Statement.of(DDL)); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + throw new IllegalStateException(); + } + + @Override + boolean isSetAutocommitAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyAllowed() { + return false; + } + + @Override + boolean isBeginTransactionAllowed() { + return false; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return false; + } + + @Override + boolean isGetTransactionModeAllowed() { + return false; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return false; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return false; + } + + @Override + boolean isCommitAllowed() { + return false; + } + + @Override + boolean isRollbackAllowed() { + return false; + } + + @Override + boolean expectedIsInTransaction() { + return false; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; + } + + @Override + boolean isWriteAllowed() { + return false; + } + + @Override + boolean isStartBatchDmlAllowed() { + return false; + } + + @Override + boolean isStartBatchDdlAllowed() { + return false; + } + + @Override + boolean isRunBatchAllowed() { + return true; + } + + @Override + boolean isAbortBatchAllowed() { + return true; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterRanDdlBatchTest + extends AbstractConnectionImplTest { + + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("START BATCH DDL;"); + connection.startBatchDdl(); + log(DDL + ";"); + connection.execute(Statement.of(DDL)); + log("RUN BATCH;"); + connection.runBatch(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // ddl-batch has no commit timestamp + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } + + public static class ConnectionImplTransactionalReadWriteAfterEmptyCommitTest + extends AbstractConnectionImplTest { + @Override + Connection getConnection() { + log("NEW_CONNECTION;"); + Connection connection = + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build()); + log("SET READONLY=FALSE;"); + connection.setReadOnly(false); + log("SET AUTOCOMMIT=FALSE;"); + connection.setAutocommit(false); + log("COMMIT;"); + connection.commit(); + return connection; + } + + @Override + boolean isSelectAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDmlAllowedAfterBeginTransaction() { + return true; + } + + @Override + boolean isDdlAllowedAfterBeginTransaction() { + return false; + } + + @Override + boolean isSetAutocommitAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyAllowed() { + return true; + } + + @Override + boolean isBeginTransactionAllowed() { + return true; + } + + @Override + boolean isSetTransactionModeAllowed(TransactionMode mode) { + return true; + } + + @Override + boolean isGetTransactionModeAllowed() { + return true; + } + + @Override + boolean isSetAutocommitDmlModeAllowed() { + return false; + } + + @Override + boolean isGetAutocommitDmlModeAllowed() { + return true; + } + + @Override + boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { + return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; + } + + @Override + boolean isGetReadOnlyStalenessAllowed() { + return true; + } + + @Override + boolean isCommitAllowed() { + return true; + } + + @Override + boolean isRollbackAllowed() { + return true; + } + + @Override + boolean expectedIsInTransaction() { + return true; + } + + @Override + boolean expectedIsTransactionStarted() { + return false; + } + + @Override + boolean isGetReadTimestampAllowed() { + // no query has been executed yet + return false; + } + + @Override + boolean isGetCommitTimestampAllowed() { + // empty commit + return false; + } + + @Override + boolean isExecuteAllowed(StatementType type) { + return type == StatementType.CLIENT_SIDE + || type == StatementType.QUERY + || type == StatementType.UPDATE; + } + + @Override + boolean isWriteAllowed() { + return true; + } + + @Override + boolean isStartBatchDmlAllowed() { + return true; + } + + @Override + boolean isStartBatchDdlAllowed() { + return true; + } + + @Override + boolean isRunBatchAllowed() { + return false; + } + + @Override + boolean isAbortBatchAllowed() { + return false; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java new file mode 100644 index 000000000000..1435cd1d9ca6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java @@ -0,0 +1,334 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.spanner.SpannerOptions; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ConnectionOptionsTest { + private static final String FILE_TEST_PATH = + ConnectionOptionsTest.class.getResource("test-key.json").getFile(); + private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; + + @Test + public void testBuildWithValidURIAndCredentialsFileURL() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); + assertThat(options.getProjectId(), is(equalTo("test-project-123"))); + assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); + assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); + assertThat( + (GoogleCredentials) options.getCredentials(), + is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); + assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); + assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + } + + @Test + public void testBuildWithValidURIAndProperties() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123?autocommit=false;readonly=true"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); + assertThat(options.getProjectId(), is(equalTo("test-project-123"))); + assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); + assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); + assertThat( + (GoogleCredentials) options.getCredentials(), + is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); + assertThat(options.isAutocommit(), is(equalTo(false))); + assertThat(options.isReadOnly(), is(equalTo(true))); + } + + @Test + public void testBuildWithHostAndValidURI() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner://test-spanner.googleapis.com/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost(), is(equalTo("https://test-spanner.googleapis.com"))); + assertThat(options.getProjectId(), is(equalTo("test-project-123"))); + assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); + assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); + assertThat( + (GoogleCredentials) options.getCredentials(), + is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); + assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); + assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + } + + @Test + public void testBuildWithLocalhostPortAndValidURI() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner://localhost:8443/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost(), is(equalTo("https://localhost:8443"))); + assertThat(options.getProjectId(), is(equalTo("test-project-123"))); + assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); + assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); + assertThat( + (GoogleCredentials) options.getCredentials(), + is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); + assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); + assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + } + + @Test + public void testBuildWithDefaultProjectPlaceholder() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner:/projects/default_project_id/instances/test-instance-123/databases/test-database-123"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); + String projectId = SpannerOptions.getDefaultProjectId(); + if (projectId == null) { + projectId = + ((ServiceAccountCredentials) new CredentialsService().createCredentials(FILE_TEST_PATH)) + .getProjectId(); + } + assertThat(options.getProjectId(), is(equalTo(projectId))); + assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); + assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); + assertThat( + (GoogleCredentials) options.getCredentials(), + is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); + assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); + assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + } + + @Test + public void testBuilderSetUri() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + + // set valid uri's + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"); + builder.setUri("cloudspanner:/projects/test-project-123/instances/test-instance"); + builder.setUri("cloudspanner:/projects/test-project-123"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance"); + builder.setUri("cloudspanner://spanner.googleapis.com/projects/test-project-123"); + + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true"); + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance?autocommit=true"); + builder.setUri("cloudspanner:/projects/test-project-123?autocommit=true"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance?autocommit=true"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123?autocommit=true"); + + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true;readonly=false"); + builder.setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance?autocommit=true;readonly=false"); + builder.setUri("cloudspanner:/projects/test-project-123?autocommit=true;readonly=false"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true;readonly=false"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance?autocommit=true;readonly=false"); + builder.setUri( + "cloudspanner://spanner.googleapis.com/projects/test-project-123?autocommit=true;readonly=false"); + + // set invalid uri's + setInvalidUri( + builder, "/projects/test-project-123/instances/test-instance/databases/test-database"); + setInvalidUri(builder, "cloudspanner:/test-project-123/test-instance/test-database"); + setInvalidUri( + builder, + "cloudspanner:spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database"); + setInvalidUri( + builder, + "cloudspanner://spanner.googleapis.com/projects/test-project-$$$/instances/test-instance/databases/test-database"); + setInvalidUri( + builder, + "cloudspanner://spanner.googleapis.com/projects/test-project-123/databases/test-database"); + setInvalidUri( + builder, + "cloudspanner:/projects/test_project_123/instances/test-instance/databases/test-database"); + + // Set URI's that are valid, but that contain unknown properties. + setInvalidProperty( + builder, + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false", + "read"); + setInvalidProperty( + builder, + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false;autocommit=true", + "read"); + setInvalidProperty( + builder, + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false;auto=true", + "read, auto"); + } + + private void setInvalidUri(ConnectionOptions.Builder builder, String uri) { + boolean invalid = false; + try { + builder.setUri(uri); + } catch (IllegalArgumentException e) { + invalid = true; + } + assertThat(uri + " should be considered an invalid uri", invalid, is(true)); + } + + private void setInvalidProperty( + ConnectionOptions.Builder builder, String uri, String expectedInvalidProperties) { + boolean invalid = false; + try { + builder.setUri(uri); + } catch (IllegalArgumentException e) { + invalid = e.getMessage().contains(expectedInvalidProperties); + } + assertThat(uri + " should contain invalid properties", invalid, is(true)); + } + + @Test + public void testParseUriProperty() { + final String baseUri = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + + assertThat(ConnectionOptions.parseUriProperty(baseUri, "autocommit"), is(nullValue())); + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false", "autocommit"), + is(equalTo("false"))); + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true;", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false;", "autocommit"), + is(equalTo("false"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=true;readOnly=false", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=false;readOnly=false", "autocommit"), + is(equalTo("false"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=true", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=false", "autocommit"), + is(equalTo("false"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=true;foo=bar", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=false;foo=bar", "autocommit"), + is(equalTo("false"))); + + // case insensitive + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=true", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=false", "autocommit"), + is(equalTo("false"))); + + // ; instead of ? before the properties is ok + assertThat( + ConnectionOptions.parseUriProperty(baseUri + ";autocommit=true", "autocommit"), + is(equalTo("true"))); + + // forgot the ? or ; before the properties + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "autocommit=true", "autocommit"), + is(nullValue())); + // substring is not ok + assertThat( + ConnectionOptions.parseUriProperty(baseUri + "?isautocommit=true", "autocommit"), + is(nullValue())); + } + + @Test + public void testParseProperties() { + final String baseUri = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + assertThat( + ConnectionOptions.parseProperties(baseUri + "?autocommit=true"), + is(equalTo(Arrays.asList("autocommit")))); + assertThat( + ConnectionOptions.parseProperties(baseUri + "?autocommit=true;readonly=false"), + is(equalTo(Arrays.asList("autocommit", "readonly")))); + assertThat( + ConnectionOptions.parseProperties(baseUri + "?autocommit=true;READONLY=false"), + is(equalTo(Arrays.asList("autocommit", "READONLY")))); + assertThat( + ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false"), + is(equalTo(Arrays.asList("autocommit", "readonly")))); + assertThat( + ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false;"), + is(equalTo(Arrays.asList("autocommit", "readonly")))); + } + + @Test + public void testParsePropertiesSpecifiedMultipleTimes() { + final String baseUri = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=true;autocommit=false", "autocommit"), + is(equalTo("true"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=false;autocommit=true", "autocommit"), + is(equalTo("false"))); + assertThat( + ConnectionOptions.parseUriProperty( + baseUri + ";autocommit=false;readonly=false;autocommit=true", "autocommit"), + is(equalTo("false"))); + ConnectionOptions.newBuilder() + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" + + ";autocommit=false;readonly=false;autocommit=true"); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java new file mode 100644 index 000000000000..1709ca4080aa --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java @@ -0,0 +1,183 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.TimestampBound; +import com.google.protobuf.Duration; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ConnectionStatementExecutorTest { + + private ConnectionImpl connection; + private ConnectionStatementExecutorImpl subject; + + @Before + public void createSubject() { + connection = mock(ConnectionImpl.class); + when(connection.getAutocommitDmlMode()).thenReturn(AutocommitDmlMode.TRANSACTIONAL); + when(connection.getReadOnlyStaleness()).thenReturn(TimestampBound.strong()); + subject = new ConnectionStatementExecutorImpl(connection); + } + + @Test + public void testGetConnection() { + assertThat(subject.getConnection(), is(equalTo(connection))); + } + + @Test + public void testStatementBeginTransaction() { + subject.statementBeginTransaction(); + verify(connection).beginTransaction(); + } + + @Test + public void testStatementCommit() { + subject.statementCommit(); + verify(connection).commit(); + } + + @Test + public void testStatementGetAutocommit() { + subject.statementShowAutocommit(); + verify(connection).isAutocommit(); + } + + @Test + public void testStatementGetAutocommitDmlMode() { + subject.statementShowAutocommitDmlMode(); + verify(connection).getAutocommitDmlMode(); + } + + @Test + public void testStatementGetCommitTimestamp() { + subject.statementShowCommitTimestamp(); + verify(connection).getCommitTimestampOrNull(); + } + + @Test + public void testStatementGetReadOnly() { + subject.statementShowReadOnly(); + verify(connection).isReadOnly(); + } + + @Test + public void testStatementGetReadOnlyStaleness() { + subject.statementShowReadOnlyStaleness(); + verify(connection).getReadOnlyStaleness(); + } + + @Test + public void testStatementGetReadTimestamp() { + subject.statementShowReadTimestamp(); + verify(connection).getReadTimestampOrNull(); + } + + @Test + public void testStatementGetStatementTimeout() { + subject.statementSetStatementTimeout(Duration.newBuilder().setSeconds(1L).build()); + when(connection.hasStatementTimeout()).thenReturn(true); + subject.statementShowStatementTimeout(); + verify(connection, atLeastOnce()).getStatementTimeout(any(TimeUnit.class)); + subject.statementSetStatementTimeout(Duration.getDefaultInstance()); + when(connection.hasStatementTimeout()).thenReturn(false); + } + + @Test + public void testStatementRollback() { + subject.statementRollback(); + verify(connection).rollback(); + } + + @Test + public void testStatementSetAutocommit() { + subject.statementSetAutocommit(Boolean.TRUE); + verify(connection).setAutocommit(true); + subject.statementSetAutocommit(Boolean.FALSE); + verify(connection).setAutocommit(false); + } + + @Test + public void testStatementSetAutocommitDmlMode() { + subject.statementSetAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + verify(connection).setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + subject.statementSetAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL); + verify(connection).setAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL); + } + + @Test + public void testStatementSetReadOnly() { + subject.statementSetReadOnly(Boolean.TRUE); + verify(connection).setReadOnly(true); + subject.statementSetReadOnly(Boolean.FALSE); + verify(connection).setReadOnly(false); + } + + @Test + public void testStatementSetReadOnlyStaleness() { + subject.statementSetReadOnlyStaleness(TimestampBound.strong()); + verify(connection).setReadOnlyStaleness(TimestampBound.strong()); + + subject.statementSetReadOnlyStaleness( + TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); + verify(connection) + .setReadOnlyStaleness( + TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); + + subject.statementSetReadOnlyStaleness( + TimestampBound.ofMinReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); + verify(connection) + .setReadOnlyStaleness( + TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); + + subject.statementSetReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + verify(connection).setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + + subject.statementSetReadOnlyStaleness( + TimestampBound.ofMaxStaleness(20L, TimeUnit.MILLISECONDS)); + verify(connection) + .setReadOnlyStaleness(TimestampBound.ofMaxStaleness(20L, TimeUnit.MILLISECONDS)); + } + + @Test + public void testStatementSetStatementTimeout() { + subject.statementSetStatementTimeout(Duration.newBuilder().setNanos(100).build()); + verify(connection).setStatementTimeout(100L, TimeUnit.NANOSECONDS); + } + + @Test + public void testStatementSetTransactionMode() { + subject.statementSetTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + verify(connection).setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); + subject.statementSetTransactionMode(TransactionMode.READ_WRITE_TRANSACTION); + verify(connection).setTransactionMode(TransactionMode.READ_WRITE_TRANSACTION); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java new file mode 100644 index 000000000000..e106bcd69467 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2019 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.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import java.util.concurrent.TimeUnit; +import org.junit.Test; + +public class ConnectionStatementWithNoParametersTest { + private final StatementParser parser = StatementParser.INSTANCE; + + @Test + public void testExecuteGetAutocommit() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable autocommit")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowAutocommit()).thenCallRealMethod(); + statement.getClientSideStatement().execute(executor, "show variable autocommit"); + verify(connection, times(1)).isAutocommit(); + } + + @Test + public void testExecuteGetReadOnly() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable readonly")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowReadOnly()).thenCallRealMethod(); + statement.getClientSideStatement().execute(executor, "show variable readonly"); + verify(connection, times(1)).isReadOnly(); + } + + @Test + public void testExecuteGetAutocommitDmlMode() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable autocommit_dml_mode")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowAutocommitDmlMode()).thenCallRealMethod(); + when(connection.getAutocommitDmlMode()).thenReturn(AutocommitDmlMode.TRANSACTIONAL); + statement.getClientSideStatement().execute(executor, "show variable autocommit_dml_mode"); + verify(connection, times(1)).getAutocommitDmlMode(); + } + + @Test + public void testExecuteGetStatementTimeout() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable statement_timeout")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowStatementTimeout()).thenCallRealMethod(); + when(connection.hasStatementTimeout()).thenReturn(true); + when(connection.getStatementTimeout(TimeUnit.NANOSECONDS)).thenReturn(1L); + statement.getClientSideStatement().execute(executor, "show variable statement_timeout"); + verify(connection, times(2)).getStatementTimeout(TimeUnit.NANOSECONDS); + } + + @Test + public void testExecuteGetReadTimestamp() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable read_timestamp")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowReadTimestamp()).thenCallRealMethod(); + when(connection.getReadTimestampOrNull()).thenReturn(Timestamp.now()); + statement.getClientSideStatement().execute(executor, "show variable read_timestamp"); + verify(connection, times(1)).getReadTimestampOrNull(); + } + + @Test + public void testExecuteGetCommitTimestamp() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable commit_timestamp")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowCommitTimestamp()).thenCallRealMethod(); + when(connection.getCommitTimestampOrNull()).thenReturn(Timestamp.now()); + statement.getClientSideStatement().execute(executor, "show variable commit_timestamp"); + verify(connection, times(1)).getCommitTimestampOrNull(); + } + + @Test + public void testExecuteGetReadOnlyStaleness() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable read_only_staleness")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowReadOnlyStaleness()).thenCallRealMethod(); + when(connection.getReadOnlyStaleness()).thenReturn(TimestampBound.strong()); + statement.getClientSideStatement().execute(executor, "show variable read_only_staleness"); + verify(connection, times(1)).getReadOnlyStaleness(); + } + + @Test + public void testExecuteBegin() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("begin")); + for (String statement : subject.getClientSideStatement().getExampleStatements()) { + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementBeginTransaction()).thenCallRealMethod(); + subject.getClientSideStatement().execute(executor, statement); + verify(connection, times(1)).beginTransaction(); + } + } + + @Test + public void testExecuteCommit() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("commit")); + for (String statement : subject.getClientSideStatement().getExampleStatements()) { + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementCommit()).thenCallRealMethod(); + subject.getClientSideStatement().execute(executor, statement); + verify(connection, times(1)).commit(); + } + } + + @Test + public void testExecuteRollback() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("rollback")); + for (String statement : subject.getClientSideStatement().getExampleStatements()) { + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementRollback()).thenCallRealMethod(); + subject.getClientSideStatement().execute(executor, statement); + verify(connection, times(1)).rollback(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java new file mode 100644 index 000000000000..de5354fc66b3 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java @@ -0,0 +1,165 @@ +/* + * Copyright 2019 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.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.protobuf.Duration; +import java.util.concurrent.TimeUnit; +import org.junit.Test; + +public class ConnectionStatementWithOneParameterTest { + private final StatementParser parser = StatementParser.INSTANCE; + + @Test + public void testExecuteSetAutcommit() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set autocommit = true")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetAutocommit(any(Boolean.class))).thenCallRealMethod(); + for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { + subject + .getClientSideStatement() + .execute(executor, String.format("set autocommit = %s", mode)); + verify(connection, times(1)).setAutocommit(mode); + } + } + + @Test + public void testExecuteSetReadOnly() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set readonly = true")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetReadOnly(any(Boolean.class))).thenCallRealMethod(); + for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { + subject + .getClientSideStatement() + .execute(executor, String.format("set readonly = %s", Boolean.toString(mode))); + verify(connection, times(1)).setReadOnly(mode); + } + } + + @Test + public void testExecuteSetAutcommitDmlMode() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set autocommit_dml_mode='foo'")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetAutocommitDmlMode(any(AutocommitDmlMode.class))).thenCallRealMethod(); + for (AutocommitDmlMode mode : AutocommitDmlMode.values()) { + subject + .getClientSideStatement() + .execute(executor, String.format("set autocommit_dml_mode='%s'", mode.name())); + verify(connection, times(1)).setAutocommitDmlMode(mode); + } + } + + @Test + public void testExecuteSetStatementTimeout() throws Exception { + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.statementSetStatementTimeout(any(Duration.class))).thenCallRealMethod(); + ConnectionImpl connection = mock(ConnectionImpl.class); + when(executor.getConnection()).thenReturn(connection); + for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { + for (Long val : new Long[] {1L, 100L, 999L}) { + ParsedStatement subject = + parser.parse( + Statement.of( + String.format( + "set statement_timeout='%d%s'", + val, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); + subject + .getClientSideStatement() + .execute( + executor, + String.format( + "set statement_timeout='%d%s'", + val, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit))); + verify(connection, times(1)).setStatementTimeout(val, unit); + } + } + ParsedStatement subject = + parser.parse(Statement.of(String.format("set statement_timeout=null"))); + subject.getClientSideStatement().execute(executor, String.format("set statement_timeout=null")); + verify(connection, times(1)).clearStatementTimeout(); + } + + @Test + public void testExecuteSetReadOnlyStaleness() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set read_only_staleness='foo'")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetReadOnlyStaleness(any(TimestampBound.class))).thenCallRealMethod(); + for (TimestampBound val : + new TimestampBound[] { + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(Timestamp.now()), + TimestampBound.ofMinReadTimestamp(Timestamp.now()), + TimestampBound.ofExactStaleness(1000L, TimeUnit.SECONDS), + TimestampBound.ofMaxStaleness(2000L, TimeUnit.MICROSECONDS) + }) { + subject + .getClientSideStatement() + .execute( + executor, String.format("set read_only_staleness='%s'", timestampBoundToString(val))); + verify(connection, times(1)).setReadOnlyStaleness(val); + } + } + + private String timestampBoundToString(TimestampBound staleness) { + switch (staleness.getMode()) { + case STRONG: + return "strong"; + case READ_TIMESTAMP: + return "read_timestamp " + staleness.getReadTimestamp().toString(); + case MIN_READ_TIMESTAMP: + return "min_read_timestamp " + staleness.getMinReadTimestamp().toString(); + case EXACT_STALENESS: + return "exact_staleness " + staleness.getExactStaleness(TimeUnit.SECONDS) + "s"; + case MAX_STALENESS: + return "max_staleness " + staleness.getMaxStaleness(TimeUnit.MICROSECONDS) + "us"; + default: + throw new IllegalStateException("Unknown mode: " + staleness.getMode()); + } + } + + @Test + public void testExecuteSetTransaction() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set transaction read_only")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetTransactionMode(any(TransactionMode.class))).thenCallRealMethod(); + for (TransactionMode mode : TransactionMode.values()) { + subject + .getClientSideStatement() + .execute(executor, String.format("set transaction %s", mode.getStatementString())); + verify(connection, times(1)).setTransactionMode(mode); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java new file mode 100644 index 000000000000..d38ac23da9ee --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.storage.Blob; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageException; +import com.google.rpc.Code; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for reading and parsing test key files and getting service accounts. */ +@RunWith(JUnit4.class) +public class CredentialsServiceTest { + private static final String FILE_TEST_PATH = + CredentialsServiceTest.class.getResource("test-key.json").getFile(); + private static final String APP_DEFAULT_FILE_TEST_PATH = + CredentialsServiceTest.class.getResource("test-key-app-default.json").getFile(); + private static final String CLOUD_FILE_TEST_PATH = + CredentialsServiceTest.class.getResource("test-key-cloud-storage.json").getFile(); + private static final String GS_TEST_PATH = "gs://test-bucket/test-key-cloud-storage.json"; + private static final String GS_INVALID_TEST_PATH = "gs://test-bucket/non-existing-key.json"; + + private static final String TEST_PROJECT_ID = "test-project"; + private static final String APP_DEFAULT_PROJECT_ID = "app-default-test-project"; + private static final String GS_PROJECT_ID = "gs-test-project"; + + private final CredentialsService service = + new CredentialsService() { + @Override + Storage internalCreateStorage() { + Storage storage = mock(Storage.class); + when(storage.get("test-bucket", "test-key-cloud-storage.json")) + .thenReturn(mock(Blob.class)); + when(storage.get("test-bucket", "non-existing-key.json")) + .thenThrow(new StorageException(Code.NOT_FOUND_VALUE, "Unknown blob")); + return storage; + } + + @Override + InputStream internalCreateInputStream(Blob blob) { + try { + return new FileInputStream(CLOUD_FILE_TEST_PATH); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + GoogleCredentials internalGetApplicationDefault() throws IOException { + // Read application default credentials directly from a specific file instead of actually + // fetching the default from the environment. + return GoogleCredentials.fromStream(new FileInputStream(APP_DEFAULT_FILE_TEST_PATH)); + } + }; + + @Test + public void testCreateCredentialsDefault() throws Exception { + ServiceAccountCredentials credentials = + (ServiceAccountCredentials) service.createCredentials(null); + assertThat(credentials.getProjectId(), is(equalTo(APP_DEFAULT_PROJECT_ID))); + } + + @Test + public void testCreateCredentialsFile() throws IOException { + ServiceAccountCredentials credentials = + (ServiceAccountCredentials) service.createCredentials(FILE_TEST_PATH); + assertThat(credentials.getProjectId(), is(equalTo(TEST_PROJECT_ID))); + } + + @Test + public void testCreateCredentialsCloudStorage() throws IOException { + ServiceAccountCredentials credentials = + (ServiceAccountCredentials) service.createCredentials(GS_TEST_PATH); + assertThat(credentials.getProjectId(), is(equalTo(GS_PROJECT_ID))); + } + + @Test(expected = SpannerException.class) + public void testCreateCredentialsInvalidFile() { + service.createCredentials("invalid_file_path.json"); + } + + @Test(expected = SpannerException.class) + public void testCreateCredentialsInvalidCloudStorage() { + service.createCredentials(GS_INVALID_TEST_PATH); + } + + @Test + public void testGetBlob() { + assertThat(service.internalGetBlob("gs://test-bucket/test-blob"), is(equalTo("test-blob"))); + assertThat(service.internalGetBlob("gs://test-bucket/blob-test"), is(equalTo("blob-test"))); + } + + @Test + public void testGetBucket() { + assertThat(service.internalGetBucket("gs://test-bucket/test-blob"), is(equalTo("test-bucket"))); + assertThat(service.internalGetBucket("gs://bucket-test/blob-test"), is(equalTo("bucket-test"))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java new file mode 100644 index 000000000000..68234b599188 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java @@ -0,0 +1,514 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; +import com.google.protobuf.Timestamp; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import io.grpc.Status; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.ArgumentMatcher; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class DdlBatchTest { + + @Rule public ExpectedException exception = ExpectedException.none(); + + private DdlClient createDefaultMockDdlClient() { + return createDefaultMockDdlClient(false, 0L); + } + + private DdlClient createDefaultMockDdlClient(boolean exceptionOnGetResult) { + return createDefaultMockDdlClient(exceptionOnGetResult, 0L); + } + + private DdlClient createDefaultMockDdlClient(long waitForMillis) { + return createDefaultMockDdlClient(false, waitForMillis); + } + + private DdlClient createDefaultMockDdlClient( + boolean exceptionOnGetResult, final long waitForMillis) { + try { + DdlClient ddlClient = mock(DdlClient.class); + @SuppressWarnings("unchecked") + final OperationFuture operation = + mock(OperationFuture.class); + if (waitForMillis > 0L) { + when(operation.get()) + .thenAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(waitForMillis); + return null; + } + }); + } else if (exceptionOnGetResult) { + when(operation.get()) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.UNKNOWN, "ddl statement failed")); + } else { + when(operation.get()).thenReturn(null); + } + UpdateDatabaseDdlMetadata.Builder metadataBuilder = UpdateDatabaseDdlMetadata.newBuilder(); + if (!exceptionOnGetResult) { + metadataBuilder.addCommitTimestamps( + Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L)); + } + ApiFuture metadataFuture = + ApiFutures.immediateFuture(metadataBuilder.build()); + when(operation.getMetadata()).thenReturn(metadataFuture); + when(ddlClient.executeDdl(anyString())).thenReturn(operation); + when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); + return ddlClient; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private DdlBatch createSubject() { + return createSubject(createDefaultMockDdlClient()); + } + + private DdlBatch createSubject(DdlClient ddlClient) { + return DdlBatch.newBuilder() + .setDdlClient(ddlClient) + .withStatementExecutor(new StatementExecutor()) + .build(); + } + + @Test + public void testExecuteQuery() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.executeQuery(mock(ParsedStatement.class), AnalyzeMode.NONE); + } + + @Test + public void testExecuteUpdate() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.executeUpdate(mock(ParsedStatement.class)); + } + + @Test + public void testGetCommitTimestamp() { + DdlBatch batch = createSubject(); + batch.runBatch(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.getCommitTimestamp(); + } + + @Test + public void testGetReadTimestamp() { + DdlBatch batch = createSubject(); + batch.runBatch(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.getReadTimestamp(); + } + + @Test + public void testWrite() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.write(Mutation.newInsertBuilder("foo").build()); + } + + @Test + public void testWriteIterable() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.write(Arrays.asList(Mutation.newInsertBuilder("foo").build())); + } + + @Test + public void testIsReadOnly() { + DdlBatch batch = createSubject(); + assertThat(batch.isReadOnly(), is(false)); + } + + @Test + public void testGetStateAndIsActive() { + DdlBatch batch = createSubject(); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + batch.runBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.RAN)); + assertThat(batch.isActive(), is(false)); + + batch = createSubject(); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + batch.abortBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); + assertThat(batch.isActive(), is(false)); + + DdlClient client = mock(DdlClient.class); + doThrow(SpannerException.class).when(client).executeDdl(anyListOf(String.class)); + batch = createSubject(client); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); + when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + when(statement.getType()).thenReturn(StatementType.DDL); + batch.executeDdl(statement); + boolean exception = false; + try { + batch.runBatch(); + } catch (SpannerException e) { + exception = true; + } + assertThat(exception, is(true)); + assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); + assertThat(batch.isActive(), is(false)); + } + + private static IsListOfStringsWithSize isEmptyListOfStrings() { + return new IsListOfStringsWithSize(0); + } + + private static IsListOfStringsWithSize isListOfStringsWithSize(int size) { + return new IsListOfStringsWithSize(size); + } + + private static class IsListOfStringsWithSize extends ArgumentMatcher> { + private final int size; + + private IsListOfStringsWithSize(int size) { + this.size = size; + } + + @SuppressWarnings("unchecked") + @Override + public boolean matches(Object list) { + return ((List) list).size() == size; + } + } + + @Test + public void testRunBatch() { + DdlClient client = createDefaultMockDdlClient(); + DdlBatch batch = createSubject(client); + batch.runBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.RAN)); + verify(client, never()).executeDdl(anyString()); + verify(client, never()).executeDdl(argThat(isEmptyListOfStrings())); + + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.DDL); + when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); + when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + + client = createDefaultMockDdlClient(); + batch = createSubject(client); + batch.executeDdl(statement); + batch.runBatch(); + verify(client).executeDdl(argThat(isListOfStringsWithSize(1))); + + client = createDefaultMockDdlClient(); + batch = createSubject(client); + batch.executeDdl(statement); + batch.executeDdl(statement); + batch.runBatch(); + verify(client).executeDdl(argThat(isListOfStringsWithSize(2))); + assertThat(batch.getState(), is(UnitOfWorkState.RAN)); + boolean exception = false; + try { + batch.runBatch(); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { + throw e; + } + exception = true; + } + assertThat(exception, is(true)); + assertThat(batch.getState(), is(UnitOfWorkState.RAN)); + exception = false; + try { + batch.executeDdl(statement); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { + throw e; + } + exception = true; + } + assertThat(exception, is(true)); + exception = false; + try { + batch.executeDdl(statement); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { + throw e; + } + exception = true; + } + assertThat(exception, is(true)); + + client = createDefaultMockDdlClient(true); + batch = createSubject(client); + batch.executeDdl(statement); + batch.executeDdl(statement); + exception = false; + try { + batch.runBatch(); + } catch (SpannerException e) { + exception = true; + } + assertThat(exception, is(true)); + assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); + verify(client).executeDdl(argThat(isListOfStringsWithSize(2))); + } + + @Test + public void testUpdateCount() throws InterruptedException, ExecutionException { + DdlClient client = mock(DdlClient.class); + UpdateDatabaseDdlMetadata metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps( + Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L - 1L)) + .addCommitTimestamps( + Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L)) + .addAllStatements(Arrays.asList("CREATE TABLE FOO", "CREATE TABLE BAR")) + .build(); + ApiFuture metadataFuture = ApiFutures.immediateFuture(metadata); + @SuppressWarnings("unchecked") + OperationFuture operationFuture = mock(OperationFuture.class); + when(operationFuture.get()).thenReturn(null); + when(operationFuture.getMetadata()).thenReturn(metadataFuture); + when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture); + DdlBatch batch = + DdlBatch.newBuilder() + .withStatementExecutor(new StatementExecutor()) + .setDdlClient(client) + .build(); + batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); + batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE BAR"))); + long[] updateCounts = batch.runBatch(); + assertThat(updateCounts.length, is(equalTo(2))); + assertThat(updateCounts[0], is(equalTo(1L))); + assertThat(updateCounts[1], is(equalTo(1L))); + } + + @Test + public void testFailedUpdateCount() throws InterruptedException, ExecutionException { + DdlClient client = mock(DdlClient.class); + UpdateDatabaseDdlMetadata metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps( + Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L - 1L)) + .addAllStatements(Arrays.asList("CREATE TABLE FOO", "CREATE TABLE INVALID_TABLE")) + .build(); + ApiFuture metadataFuture = ApiFutures.immediateFuture(metadata); + @SuppressWarnings("unchecked") + OperationFuture operationFuture = mock(OperationFuture.class); + when(operationFuture.get()) + .thenThrow( + new ExecutionException( + "ddl statement failed", Status.INVALID_ARGUMENT.asRuntimeException())); + when(operationFuture.getMetadata()).thenReturn(metadataFuture); + when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture); + DdlBatch batch = + DdlBatch.newBuilder() + .withStatementExecutor(new StatementExecutor()) + .setDdlClient(client) + .build(); + batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); + batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE INVALID_TABLE"))); + try { + batch.runBatch(); + fail("missing expected exception"); + } catch (SpannerBatchUpdateException e) { + assertThat(e.getUpdateCounts().length, is(equalTo(2))); + assertThat(e.getUpdateCounts()[0], is(equalTo(1L))); + assertThat(e.getUpdateCounts()[1], is(equalTo(0L))); + } + } + + @Test + public void testAbort() { + DdlClient client = createDefaultMockDdlClient(); + DdlBatch batch = createSubject(client); + batch.abortBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); + verify(client, never()).executeDdl(anyString()); + verify(client, never()).executeDdl(anyListOf(String.class)); + + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.DDL); + when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); + when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + + client = createDefaultMockDdlClient(); + batch = createSubject(client); + batch.executeDdl(statement); + batch.abortBatch(); + verify(client, never()).executeDdl(anyListOf(String.class)); + + client = createDefaultMockDdlClient(); + batch = createSubject(client); + batch.executeDdl(statement); + batch.executeDdl(statement); + batch.abortBatch(); + verify(client, never()).executeDdl(anyListOf(String.class)); + + client = createDefaultMockDdlClient(); + batch = createSubject(client); + batch.executeDdl(statement); + batch.executeDdl(statement); + batch.abortBatch(); + verify(client, never()).executeDdl(anyListOf(String.class)); + boolean exception = false; + try { + batch.runBatch(); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { + throw e; + } + exception = true; + } + assertThat(exception, is(true)); + verify(client, never()).executeDdl(anyListOf(String.class)); + } + + @Test + public void testCancel() { + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.DDL); + when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); + when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + + DdlClient client = createDefaultMockDdlClient(10000L); + final DdlBatch batch = createSubject(client); + batch.executeDdl(statement); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + batch.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + batch.runBatch(); + } + + @Test + public void testCommit() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.commit(); + } + + @Test + public void testRollback() { + DdlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.rollback(); + } + + @Test + public void testExtractUpdateCounts() { + DdlBatch batch = createSubject(); + UpdateDatabaseDdlMetadata metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) + .addStatements("CREATE TABLE FOO") + .addStatements("CREATE TABLE BAR") + .addStatements("CREATE TABLE BAZ") + .build(); + long[] updateCounts = batch.extractUpdateCounts(metadata); + assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 0L}))); + + metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) + .addStatements("CREATE TABLE FOO") + .addStatements("CREATE TABLE BAR") + .addStatements("CREATE TABLE BAZ") + .build(); + updateCounts = batch.extractUpdateCounts(metadata); + assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); + + metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) + .addStatements("CREATE TABLE FOO") + .addStatements("CREATE TABLE BAR") + .addStatements("CREATE TABLE BAZ") + .build(); + updateCounts = batch.extractUpdateCounts(metadata); + assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); + + // This is not something Cloud Spanner should return, but the method can handle it. + metadata = + UpdateDatabaseDdlMetadata.newBuilder() + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) + .addCommitTimestamps(Timestamp.newBuilder().setSeconds(4000L).build()) + .addStatements("CREATE TABLE FOO") + .addStatements("CREATE TABLE BAR") + .addStatements("CREATE TABLE BAZ") + .build(); + updateCounts = batch.extractUpdateCounts(metadata); + assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java new file mode 100644 index 000000000000..8ec9f600d31b --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 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.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DdlClientTest { + + private final String instanceId = "test-instance"; + private final String databaseId = "test-database"; + + private DdlClient createSubject(DatabaseAdminClient client) { + return DdlClient.newBuilder() + .setInstanceId(instanceId) + .setDatabaseName(databaseId) + .setDatabaseAdminClient(client) + .build(); + } + + @Test + public void testExecuteDdl() throws InterruptedException, ExecutionException { + DatabaseAdminClient client = mock(DatabaseAdminClient.class); + @SuppressWarnings("unchecked") + OperationFuture operation = mock(OperationFuture.class); + when(operation.get()).thenReturn(null); + when(client.updateDatabaseDdl( + eq(instanceId), eq(databaseId), anyListOf(String.class), isNull(String.class))) + .thenReturn(operation); + DdlClient subject = createSubject(client); + String ddl = "CREATE TABLE FOO"; + subject.executeDdl(ddl); + verify(client).updateDatabaseDdl(instanceId, databaseId, Arrays.asList(ddl), null); + + subject = createSubject(client); + List ddlList = Arrays.asList("CREATE TABLE FOO", "DROP TABLE FOO"); + subject.executeDdl(ddlList); + verify(client).updateDatabaseDdl(instanceId, databaseId, ddlList, null); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java new file mode 100644 index 000000000000..b138b1e62510 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java @@ -0,0 +1,255 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DirectExecuteResultSetTest { + + private DirectExecuteResultSet createSubject() { + ResultSet delegate = + ResultSets.forRows( + Type.struct(StructField.of("test", Type.int64())), + Arrays.asList(Struct.newBuilder().set("test").to(1L).build())); + return DirectExecuteResultSet.ofResultSet(delegate); + } + + @Test + public void testMethodCallBeforeNext() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = + Arrays.asList("getStats", "next", "close", "ofResultSet", "equals", "hashCode"); + DirectExecuteResultSet subject = createSubject(); + callMethods(subject, excludedMethods, IllegalStateException.class); + } + + @Test + public void testMethodCallAfterClose() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = + Arrays.asList( + "getStats", + "next", + "close", + "getType", + "getColumnCount", + "getColumnIndex", + "getColumnType", + "ofResultSet", + "equals", + "hashCode"); + DirectExecuteResultSet subject = createSubject(); + subject.next(); + subject.close(); + callMethods(subject, excludedMethods, IllegalStateException.class); + } + + @Test + public void testMethodCallAfterNextHasReturnedFalse() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = + Arrays.asList( + "getStats", + "next", + "close", + "getType", + "getColumnCount", + "getColumnIndex", + "getColumnType", + "ofResultSet", + "equals", + "hashCode"); + DirectExecuteResultSet subject = createSubject(); + subject.next(); + subject.next(); + callMethods(subject, excludedMethods, IndexOutOfBoundsException.class); + } + + private void callMethods( + DirectExecuteResultSet subject, + List excludedMethods, + Class expectedException) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for (Method method : DirectExecuteResultSet.class.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers()) && !excludedMethods.contains(method.getName())) { + boolean exception = false; + int numberOfParameters = method.getParameterTypes().length; + Class firstParameterType = null; + if (numberOfParameters == 1) { + firstParameterType = method.getParameterTypes()[0]; + } + try { + switch (numberOfParameters) { + case 0: + method.invoke(subject); + break; + case 1: + if (firstParameterType == String.class) { + method.invoke(subject, "test"); + } else if (firstParameterType == int.class) { + method.invoke(subject, 0); + } else { + fail("unknown parameter type"); + } + break; + default: + fail("method with more than 1 parameter is unknown"); + } + } catch (InvocationTargetException e) { + if (e.getCause().getClass().equals(expectedException)) { + // expected + exception = true; + } else { + throw e; + } + } + assertThat( + method.getName() + " did not throw an IllegalStateException", exception, is(true)); + } + } + } + + @Test + public void testValidMethodCall() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + ResultSet delegate = mock(ResultSet.class); + when(delegate.next()).thenReturn(true, true, false); + DirectExecuteResultSet subject = DirectExecuteResultSet.ofResultSet(delegate); + subject.next(); + + subject.getBoolean(0); + verify(delegate).getBoolean(0); + subject.getBoolean("test0"); + verify(delegate).getBoolean("test0"); + subject.getBooleanArray(1); + verify(delegate).getBooleanArray(1); + subject.getBooleanArray("test1"); + verify(delegate).getBooleanArray("test1"); + subject.getBooleanList(2); + verify(delegate).getBooleanList(2); + subject.getBooleanList("test2"); + verify(delegate).getBooleanList("test2"); + + subject.getBytes(0); + verify(delegate).getBytes(0); + subject.getBytes("test0"); + verify(delegate).getBytes("test0"); + subject.getBytesList(2); + verify(delegate).getBytesList(2); + subject.getBytesList("test2"); + verify(delegate).getBytesList("test2"); + + subject.getDate(0); + verify(delegate).getDate(0); + subject.getDate("test0"); + verify(delegate).getDate("test0"); + subject.getDateList(2); + verify(delegate).getDateList(2); + subject.getDateList("test2"); + verify(delegate).getDateList("test2"); + + subject.getDouble(0); + verify(delegate).getDouble(0); + subject.getDouble("test0"); + verify(delegate).getDouble("test0"); + subject.getDoubleArray(1); + verify(delegate).getDoubleArray(1); + subject.getDoubleArray("test1"); + verify(delegate).getDoubleArray("test1"); + subject.getDoubleList(2); + verify(delegate).getDoubleList(2); + subject.getDoubleList("test2"); + verify(delegate).getDoubleList("test2"); + + subject.getLong(0); + verify(delegate).getLong(0); + subject.getLong("test0"); + verify(delegate).getLong("test0"); + subject.getLongArray(1); + verify(delegate).getLongArray(1); + subject.getLongArray("test1"); + verify(delegate).getLongArray("test1"); + subject.getLongList(2); + verify(delegate).getLongList(2); + subject.getLongList("test2"); + verify(delegate).getLongList("test2"); + + subject.getString(0); + verify(delegate).getString(0); + subject.getString("test0"); + verify(delegate).getString("test0"); + subject.getStringList(2); + verify(delegate).getStringList(2); + subject.getStringList("test2"); + verify(delegate).getStringList("test2"); + + subject.getStructList(0); + subject.getStructList("test0"); + + subject.getTimestamp(0); + verify(delegate).getTimestamp(0); + subject.getTimestamp("test0"); + verify(delegate).getTimestamp("test0"); + subject.getTimestampList(2); + verify(delegate).getTimestampList(2); + subject.getTimestampList("test2"); + verify(delegate).getTimestampList("test2"); + + subject.getColumnCount(); + verify(delegate).getColumnCount(); + subject.getColumnIndex("test"); + verify(delegate).getColumnIndex("test"); + subject.getColumnType(100); + verify(delegate).getColumnType(100); + subject.getColumnType("test"); + verify(delegate).getColumnType("test"); + subject.getCurrentRowAsStruct(); + verify(delegate).getCurrentRowAsStruct(); + subject.getType(); + verify(delegate).getType(); + subject.isNull(50); + verify(delegate).isNull(50); + subject.isNull("test"); + verify(delegate).isNull("test"); + + while (subject.next()) { + // ignore + } + subject.getStats(); + verify(delegate).getStats(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java new file mode 100644 index 000000000000..e6c54d115b14 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java @@ -0,0 +1,163 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DmlBatchTest { + private final ParsedStatement statement1 = + StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2")); + private final ParsedStatement statement2 = + StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=2 WHERE BAZ=3")); + + @Rule public ExpectedException exception = ExpectedException.none(); + + private DmlBatch createSubject() { + UnitOfWork transaction = mock(UnitOfWork.class); + when(transaction.executeBatchUpdate(Arrays.asList(statement1, statement2))) + .thenReturn(new long[] {3L, 5L}); + return createSubject(transaction); + } + + private DmlBatch createSubject(UnitOfWork transaction) { + return DmlBatch.newBuilder() + .setTransaction(transaction) + .withStatementExecutor(new StatementExecutor()) + .build(); + } + + @Test + public void testExecuteQuery() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.executeQuery(mock(ParsedStatement.class), AnalyzeMode.NONE); + } + + @Test + public void testExecuteDdl() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.executeDdl(mock(ParsedStatement.class)); + } + + @Test + public void testGetReadTimestamp() { + DmlBatch batch = createSubject(); + batch.runBatch(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.getReadTimestamp(); + } + + @Test + public void testIsReadOnly() { + DmlBatch batch = createSubject(); + assertThat(batch.isReadOnly(), is(false)); + } + + @Test + public void testGetCommitTimestamp() { + DmlBatch batch = createSubject(); + batch.runBatch(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.getCommitTimestamp(); + } + + @Test + public void testWrite() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.write(Mutation.newInsertBuilder("foo").build()); + } + + @Test + public void testWriteIterable() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.write(Arrays.asList(Mutation.newInsertBuilder("foo").build())); + } + + @Test + public void testGetStateAndIsActive() { + DmlBatch batch = createSubject(); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + batch.runBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.RAN)); + assertThat(batch.isActive(), is(false)); + + batch = createSubject(); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + batch.abortBatch(); + assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); + assertThat(batch.isActive(), is(false)); + + UnitOfWork tx = mock(UnitOfWork.class); + doThrow(SpannerException.class).when(tx).executeBatchUpdate(anyListOf(ParsedStatement.class)); + batch = createSubject(tx); + assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); + assertThat(batch.isActive(), is(true)); + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getStatement()).thenReturn(Statement.of("UPDATE TEST SET COL1=2")); + when(statement.getSqlWithoutComments()).thenReturn("UPDATE TEST SET COL1=2"); + when(statement.getType()).thenReturn(StatementType.UPDATE); + batch.executeUpdate(statement); + boolean exception = false; + try { + batch.runBatch(); + } catch (SpannerException e) { + exception = true; + } + assertThat(exception, is(true)); + assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); + assertThat(batch.isActive(), is(false)); + } + + @Test + public void testCommit() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.commit(); + } + + @Test + public void testRollback() { + DmlBatch batch = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + batch.rollback(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java new file mode 100644 index 000000000000..073f33f31d66 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.DurationConverter; +import com.google.protobuf.Duration; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DurationConverterTest { + + @Test + public void testConvert() throws CompileException { + String allowedValues = ReadOnlyStalenessConverterTest.getAllowedValues(DurationConverter.class); + assertThat(allowedValues, is(notNullValue())); + DurationConverter converter = new DurationConverter(allowedValues); + assertThat( + converter.convert("'100ms'"), + is( + equalTo( + Duration.newBuilder() + .setNanos((int) TimeUnit.MILLISECONDS.toNanos(100L)) + .build()))); + assertThat(converter.convert("'0ms'"), is(nullValue())); + assertThat(converter.convert("'-100ms'"), is(nullValue())); + assertThat( + converter.convert("'315576000000000ms'"), + is(equalTo(Duration.newBuilder().setSeconds(315576000000L).build()))); + assertThat( + converter.convert("'1000ms'"), is(equalTo(Duration.newBuilder().setSeconds(1L).build()))); + assertThat( + converter.convert("'1001ms'"), + is( + equalTo( + Duration.newBuilder() + .setSeconds(1L) + .setNanos((int) TimeUnit.MILLISECONDS.toNanos(1L)) + .build()))); + + assertThat(converter.convert("'1ns'"), is(equalTo(Duration.newBuilder().setNanos(1).build()))); + assertThat( + converter.convert("'1us'"), is(equalTo(Duration.newBuilder().setNanos(1000).build()))); + assertThat( + converter.convert("'1ms'"), is(equalTo(Duration.newBuilder().setNanos(1000000).build()))); + assertThat( + converter.convert("'999999999ns'"), + is(equalTo(Duration.newBuilder().setNanos(999999999).build()))); + assertThat( + converter.convert("'1s'"), is(equalTo(Duration.newBuilder().setSeconds(1L).build()))); + + assertThat(converter.convert("''"), is(nullValue())); + assertThat(converter.convert("' '"), is(nullValue())); + assertThat(converter.convert("'random string'"), is(nullValue())); + + assertThat(converter.convert("null"), is(equalTo(Duration.getDefaultInstance()))); + assertThat(converter.convert("NULL"), is(equalTo(Duration.getDefaultInstance()))); + assertThat(converter.convert("Null"), is(equalTo(Duration.getDefaultInstance()))); + assertThat(converter.convert("'null'"), is(nullValue())); + assertThat(converter.convert("'NULL'"), is(nullValue())); + assertThat(converter.convert("'Null'"), is(nullValue())); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java new file mode 100644 index 000000000000..1793a618e878 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -0,0 +1,182 @@ +/* + * Copyright 2019 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.Database; +import com.google.cloud.spanner.GceTestEnvConfig; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.experimental.categories.Category; + +/** Base class for all JDBC integration tests. */ +@Category(IntegrationTest.class) +public class ITAbstractJdbcTest { + protected class ITJdbcConnectionProvider implements GenericConnectionProvider { + public ITJdbcConnectionProvider() {} + + @Override + public JdbcGenericConnection getConnection() { + try { + return JdbcGenericConnection.of(createConnection()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static final String DEFAULT_KEY_FILE = null; + private static Database database; + + protected static String getKeyFile() { + return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); + } + + protected static boolean hasValidKeyFile() { + return getKeyFile() != null && Files.exists(Paths.get(getKeyFile())); + } + + protected static IntegrationTestEnv getTestEnv() { + return env; + } + + protected static Database getDatabase() { + return database; + } + + @BeforeClass + public static void setup() throws IOException, InterruptedException, ExecutionException { + database = env.getTestHelper().createTestDatabase(); + } + + /** + * Creates a new default JDBC connection to a test database. Use the method {@link + * ITAbstractJdbcTest#appendConnectionUri(StringBuilder)} to append additional connection options + * to the connection URI. + * + * @return The newly opened JDBC connection. + */ + public CloudSpannerJdbcConnection createConnection() throws SQLException { + StringBuilder url = + new StringBuilder("jdbc:cloudspanner:/").append(getDatabase().getId().getName()); + if (hasValidKeyFile()) { + url.append(";credentials=").append(getKeyFile()); + } + appendConnectionUri(url); + + return DriverManager.getConnection(url.toString()).unwrap(CloudSpannerJdbcConnection.class); + } + + protected void appendConnectionUri(StringBuilder uri) {} + + /** + * Override this method to instruct the test to create a default test table in the form: + * + *

+   * CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)
+   * 
+ * + * Note that the table is not re-created for each test case, but is preserved between test cases. + * It is the responsibility of the test class to either empty the table at the end of each test + * case, or keep track of the state of the test table and execute the test cases in a specific + * order. + * + * @return true if the default test table should be created. + */ + protected boolean doCreateDefaultTestTable() { + return false; + } + + protected boolean doCreateMusicTables() { + return false; + } + + @Before + public void createTestTable() throws SQLException { + if (doCreateDefaultTestTable()) { + try (Connection connection = createConnection()) { + connection.setAutoCommit(true); + if (!tableExists(connection, "TEST")) { + connection.setAutoCommit(false); + connection.createStatement().execute("START BATCH DDL"); + connection + .createStatement() + .execute( + "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)"); + connection.createStatement().execute("RUN BATCH"); + } + } + } + } + + @Before + public void createMusicTables() throws SQLException { + if (doCreateMusicTables()) { + try (Connection connection = createConnection()) { + connection.setAutoCommit(true); + if (!tableExists(connection, "Singers")) { + for (String statement : + AbstractSqlScriptVerifier.readStatementsFromFile( + "CreateMusicTables.sql", getClass())) { + connection.createStatement().execute(statement); + } + } + } + } + } + + protected boolean tableExists(Connection connection, String table) throws SQLException { + try (ResultSet rs = connection.getMetaData().getTables("", "", table, null)) { + if (rs.next()) { + if (rs.getString("TABLE_NAME").equalsIgnoreCase(table)) { + return true; + } + } + } + return false; + } + + protected boolean indexExists(Connection connection, String table, String index) + throws SQLException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(index)); + try (PreparedStatement ps = + connection.prepareStatement( + "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE UPPER(TABLE_NAME)=? AND UPPER(INDEX_NAME)=?")) { + ps.setString(1, table); + ps.setString(2, index); + try (ResultSet rs = ps.executeQuery()) { + return rs.next(); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java new file mode 100644 index 000000000000..affb025134a0 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java @@ -0,0 +1,301 @@ +/* + * Copyright 2019 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.Database; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.GceTestEnvConfig; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionManager.TransactionState; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.experimental.categories.Category; + +/** + * Base class for integration tests. This class is located in this package to be able to access + * package-private methods of the Connection API + */ +@Category(IntegrationTest.class) +public abstract class ITAbstractSpannerTest { + protected class ITConnectionProvider implements GenericConnectionProvider { + public ITConnectionProvider() {} + + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of(createConnection()); + } + } + + protected interface ITConnection extends Connection {} + + private ITConnection createITConnection(ConnectionOptions options) { + return new ITConnectionImpl(options); + } + + protected void closeSpanner() { + ConnectionOptions.closeSpanner(); + } + + public static class AbortInterceptor implements StatementExecutionInterceptor { + /** We need to replicate the enum here as it is not visibible outside the connection package */ + public enum ExecutionStep { + /** The initial execution of a statement (DML/Query) */ + EXECUTE_STATEMENT, + /** A call to {@link ResultSet#next()} */ + CALL_NEXT_ON_RESULT_SET, + /** Execution of the statement during a transaction retry */ + RETRY_STATEMENT, + /** A call to {@link ResultSet#next()} during transaction retry */ + RETRY_NEXT_ON_RESULT_SET; + + static ExecutionStep of(StatementExecutionStep step) { + return ExecutionStep.valueOf(step.name()); + } + } + + private double probability; + private boolean onlyInjectOnce = false; + private final Random random = new Random(); + + public AbortInterceptor(double probability) { + Preconditions.checkArgument(probability >= 0.0D && probability <= 1.0D); + this.probability = probability; + } + + public void setProbability(double probability) { + Preconditions.checkArgument(probability >= 0.0D && probability <= 1.0D); + this.probability = probability; + } + + /** Set this value to true to automatically set the probability to zero after an abort */ + public void setOnlyInjectOnce(boolean value) { + this.onlyInjectOnce = value; + } + + protected boolean shouldAbort(String statement, ExecutionStep step) { + return probability > random.nextDouble(); + } + + @Override + public void intercept( + ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction) { + if (shouldAbort(statement.getSqlWithoutComments(), ExecutionStep.of(step))) { + // ugly hack warning: inject the aborted state into the transaction manager to simulate an + // abort + if (transaction instanceof ReadWriteTransaction) { + try { + Field field = ReadWriteTransaction.class.getDeclaredField("txManager"); + field.setAccessible(true); + TransactionManager tx = (TransactionManager) field.get(transaction); + Class cls = Class.forName("com.google.cloud.spanner.TransactionManagerImpl"); + Class cls2 = + Class.forName("com.google.cloud.spanner.SessionPool$AutoClosingTransactionManager"); + Field delegateField = cls2.getDeclaredField("delegate"); + delegateField.setAccessible(true); + TransactionManager delegate = (TransactionManager) delegateField.get(tx); + Field stateField = cls.getDeclaredField("txnState"); + stateField.setAccessible(true); + + // first rollback, and then pretend it aborted + tx.rollback(); + stateField.set(delegate, TransactionState.ABORTED); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (onlyInjectOnce) { + probability = 0; + } + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.ABORTED, "Transaction was aborted by interceptor"); + } + } + } + } + + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static final String DEFAULT_KEY_FILE = null; + private static Database database; + + protected static String getKeyFile() { + return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); + } + + protected static boolean hasValidKeyFile() { + return getKeyFile() != null && Files.exists(Paths.get(getKeyFile())); + } + + protected static IntegrationTestEnv getTestEnv() { + return env; + } + + protected static Database getDatabase() { + return database; + } + + @BeforeClass + public static void setup() throws IOException, InterruptedException, ExecutionException { + database = env.getTestHelper().createTestDatabase(); + } + + /** + * Creates a new default connection to a test database. Use the method {@link + * ITAbstractSpannerTest#appendConnectionUri(StringBuilder)} to append additional connection + * options to the connection URI. + * + * @return the newly opened connection. + */ + public ITConnection createConnection() { + return createConnection( + Collections.emptyList(), + Collections.emptyList()); + } + + public ITConnection createConnection(AbortInterceptor interceptor) { + return createConnection( + Arrays.asList(interceptor), + Collections.emptyList()); + } + + public ITConnection createConnection( + AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { + return createConnection( + Arrays.asList(interceptor), + Arrays.asList(transactionRetryListener)); + } + + /** + * Creates a new default connection to a test database. Use the method {@link + * ITAbstractSpannerTest#appendConnectionUri(StringBuilder)} to append additional connection + * options to the connection URI. + * + * @param interceptors Interceptors that should be executed after each statement + * @param transactionRetryListeners Transaction retry listeners that should be added to the {@link + * Connection} + * @return the newly opened connection. + */ + public ITConnection createConnection( + List interceptors, + List transactionRetryListeners) { + StringBuilder url = new StringBuilder("cloudspanner:/").append(getDatabase().getId().getName()); + appendConnectionUri(url); + ConnectionOptions.Builder builder = + ConnectionOptions.newBuilder() + .setUri(url.toString()) + .setStatementExecutionInterceptors(interceptors); + if (hasValidKeyFile()) { + builder.setCredentialsUrl(getKeyFile()); + } + ConnectionOptions options = builder.build(); + ITConnection connection = createITConnection(options); + for (TransactionRetryListener listener : transactionRetryListeners) { + connection.addTransactionRetryListener(listener); + } + return connection; + } + + protected void appendConnectionUri(StringBuilder uri) {} + + /** + * Override this method to instruct the test to create a default test table in the form: + * + *
+   * CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)
+   * 
+ * + * Note that the table is not re-created for each test case, but is preserved between test cases. + * It is the responsibility of the test class to either empty the table at the end of each test + * case, or keep track of the state of the test table and execute the test cases in a specific + * order. + * + * @return true if the default test table should be created. + */ + protected boolean doCreateDefaultTestTable() { + return false; + } + + @Before + public void createTestTable() throws Exception { + if (doCreateDefaultTestTable()) { + try (Connection connection = createConnection()) { + connection.setAutocommit(true); + if (!tableExists(connection, "TEST")) { + connection.setAutocommit(false); + connection.startBatchDdl(); + connection.execute( + Statement.of( + "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)")); + connection.runBatch(); + } + } + } + } + + protected boolean tableExists(Connection connection, String table) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(table)); + try (ResultSet rs = + connection.executeQuery( + Statement.newBuilder( + "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE UPPER(TABLE_NAME)=@table_name") + .bind("table_name") + .to(table.toUpperCase()) + .build())) { + while (rs.next()) { + return true; + } + } + return false; + } + + protected boolean indexExists(Connection connection, String table, String index) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(index)); + try (ResultSet rs = + connection.executeQuery( + Statement.newBuilder( + "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE UPPER(TABLE_NAME)=@table_name AND UPPER(INDEX_NAME)=@index_name") + .bind("table_name") + .to(table) + .bind("index_name") + .to(index.toUpperCase()) + .build())) { + while (rs.next()) { + return true; + } + } + return false; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java new file mode 100644 index 000000000000..c6361d0fd04d --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java @@ -0,0 +1,25 @@ +/* + * Copyright 2019 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.jdbc.ITAbstractSpannerTest.ITConnection; + +/** Implementation of {@link ITConnection} for Spanner generic (not JDBC) connections. */ +class ITConnectionImpl extends ConnectionImpl implements ITConnection { + ITConnectionImpl(ConnectionOptions options) { + super(options); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java new file mode 100644 index 000000000000..acefaf2087e9 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -0,0 +1,380 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; +import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedException; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +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 io.grpc.Server; +import io.grpc.Status; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +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 JdbcAbortedTransactionTest { + private static final class TransactionRetryCounter implements TransactionRetryListener { + private int retriesFinished; + + @Override + public void retryStarting(Timestamp transactionStarted, long transactionId, int retryAttempt) {} + + @Override + public void retryFinished( + Timestamp transactionStarted, long transactionId, int retryAttempt, RetryResult result) { + retriesFinished++; + } + } + + private static final Statement SELECT1 = Statement.of("SELECT 1 AS COL1"); + private static final ResultSetMetadata SELECT1_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("COL1") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build(); + private static final com.google.spanner.v1.ResultSet SELECT1_RESULTSET = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .setMetadata(SELECT1_METADATA) + .build(); + private static final Statement SELECT_RANDOM = Statement.of("SELECT * FROM RANDOM"); + private static final Statement UPDATE_STATEMENT = + Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2"); + private static final int UPDATE_COUNT = 1; + + private static MockSpannerServiceImpl mockSpanner; + private static MockInstanceAdminImpl mockInstanceAdmin; + private static MockDatabaseAdminImpl mockDatabaseAdmin; + private static Server server; + private static InetSocketAddress address; + + @Parameter(0) + public boolean retryAbortsInternally; + + @Rule public ExpectedException expected = ExpectedException.none(); + + @Parameters(name = "retryAbortsInternally = {0}") + public static Collection data() { + List params = new ArrayList<>(); + params.add(new Object[] {Boolean.TRUE}); + params.add(new Object[] {Boolean.FALSE}); + return params; + } + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. + mockSpanner.putStatementResult(StatementResult.query(SELECT1, SELECT1_RESULTSET)); + mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT)); + mockInstanceAdmin = new MockInstanceAdminImpl(); + mockDatabaseAdmin = new MockDatabaseAdminImpl(); + address = new InetSocketAddress("localhost", 0); + server = + NettyServerBuilder.forAddress(address) + .addService(mockSpanner) + .addService(mockInstanceAdmin) + .addService(mockDatabaseAdmin) + .build() + .start(); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;retryAbortsInternally=%s", + server.getPort(), "proj", "inst", "db", Boolean.toString(retryAbortsInternally)); + } + + private Connection createConnection() throws SQLException { + Connection connection = DriverManager.getConnection(createUrl()); + CloudSpannerJdbcConnection cs = connection.unwrap(CloudSpannerJdbcConnection.class); + cs.addTransactionRetryListener(new TransactionRetryCounter()); + return connection; + } + + private int getRetryCount(Connection connection) throws SQLException { + return ((TransactionRetryCounter) + connection + .unwrap(CloudSpannerJdbcConnection.class) + .getTransactionRetryListeners() + .next()) + .retriesFinished; + } + + @Test + public void testAutocommitUpdateAborted() throws SQLException { + // Updates in autocommit are always automatically retried. + // These retries are not picked up by the transaction retry listener, as that is only done for + // actual JDBC transactions that are retried. + try (java.sql.Connection connection = createConnection()) { + mockSpanner.abortNextTransaction(); + int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + assertThat(updateCount, is(equalTo(UPDATE_COUNT))); + } + } + + @Test + public void testTransactionalUpdateAborted() throws SQLException { + // Updates in transactional mode are automatically retried by default, but this can be switched + // off. + if (!retryAbortsInternally) { + expected.expect(JdbcAbortedException.class); + } + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + mockSpanner.abortNextTransaction(); + int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + assertThat(updateCount, is(equalTo(UPDATE_COUNT))); + assertThat(getRetryCount(connection), is(equalTo(1))); + } + } + + @Test + public void testAutocommitBatchUpdateAborted() throws SQLException { + try (java.sql.Connection connection = createConnection()) { + mockSpanner.abortNextTransaction(); + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.addBatch(UPDATE_STATEMENT.getSql()); + int[] updateCounts = statement.executeBatch(); + assertThat(updateCounts, is(equalTo(new int[] {UPDATE_COUNT, UPDATE_COUNT}))); + } + } + } + + @Test + public void testTransactionalBatchUpdateAborted() throws SQLException { + if (!retryAbortsInternally) { + expected.expect(JdbcAbortedException.class); + } + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + mockSpanner.abortNextTransaction(); + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.addBatch(UPDATE_STATEMENT.getSql()); + int[] updateCounts = statement.executeBatch(); + assertThat(updateCounts, is(equalTo(new int[] {UPDATE_COUNT, UPDATE_COUNT}))); + assertThat(getRetryCount(connection), is(equalTo(1))); + } + } + } + + @Test + public void testAutocommitSelectAborted() throws SQLException { + // Selects in autocommit are executed using a singleUse read-only transaction and cannot abort. + try (java.sql.Connection connection = createConnection()) { + mockSpanner.abortNextTransaction(); + try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + while (rs.next()) { + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + } + } + + @Test + public void testTransactionalSelectAborted() throws SQLException { + if (!retryAbortsInternally) { + expected.expect(JdbcAbortedException.class); + } + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + mockSpanner.abortNextTransaction(); + try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + while (rs.next()) { + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + assertThat(getRetryCount(connection), is(equalTo(1))); + } + } + + @Test + public void testTransactionalUpdateWithConcurrentModificationsAborted() throws SQLException { + if (retryAbortsInternally) { + // As the transaction does a random select, the retry will always see different data than the + // original attempt. + expected.expect(JdbcAbortedDueToConcurrentModificationException.class); + } else { + expected.expect(JdbcAbortedException.class); + } + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + // Set a random answer. + mockSpanner.putStatementResult( + StatementResult.query(SELECT_RANDOM, new RandomResultSetGenerator(25).generate())); + try (ResultSet rs = connection.createStatement().executeQuery(SELECT_RANDOM.getSql())) { + while (rs.next()) {} + } + // Set a new random answer that will be returned during the retry. + mockSpanner.putStatementResult( + StatementResult.query(SELECT_RANDOM, new RandomResultSetGenerator(25).generate())); + // Abort all transactions (including the current one). + mockSpanner.abortAllTransactions(); + // This will abort and start an internal retry. + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected aborted exception"); + } + } + + @Test + public void testTransactionalUpdateWithErrorOnOriginalAndRetry() throws SQLException { + if (!retryAbortsInternally) { + expected.expect(JdbcAbortedException.class); + } + final String sql = "UPDATE SOMETHING SET OTHER=1"; + mockSpanner.putStatementResult( + StatementResult.exception( + Statement.of(sql), + Status.INVALID_ARGUMENT.withDescription("test").asRuntimeException())); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + while (rs.next()) { + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + try { + connection.createStatement().executeUpdate(sql); + fail("missing 'test' exception"); + } catch (SQLException e) { + // ignore + } + mockSpanner.abortAllTransactions(); + connection.commit(); + } + } + + @Test + public void testTransactionalUpdateWithErrorOnRetryAndNotOnOriginal() throws SQLException { + if (retryAbortsInternally) { + expected.expect(JdbcAbortedDueToConcurrentModificationException.class); + } else { + expected.expect(JdbcAbortedException.class); + } + final String sql = "UPDATE SOMETHING SET OTHER=1"; + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + // Set a normal response to the update statement. + mockSpanner.putStatementResult(StatementResult.update(Statement.of(sql), 1L)); + connection.createStatement().executeUpdate(sql); + // Set an error as response for the same update statement that will be used during the retry. + // This will cause the retry to fail. + mockSpanner.putStatementResult( + StatementResult.exception( + Statement.of(sql), + Status.INVALID_ARGUMENT.withDescription("test").asRuntimeException())); + mockSpanner.abortAllTransactions(); + connection.commit(); + fail("missing expected aborted exception"); + } catch (JdbcAbortedDueToConcurrentModificationException e) { + assertThat( + e.getDatabaseErrorDuringRetry().getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); + assertThat(e.getDatabaseErrorDuringRetry().getMessage(), endsWith("test")); + throw e; + } + } + + @Test + public void testTransactionalUpdateWithErrorOnOriginalAndNotOnRetry() throws SQLException { + if (retryAbortsInternally) { + expected.expect(JdbcAbortedDueToConcurrentModificationException.class); + } else { + expected.expect(JdbcAbortedException.class); + } + final String sql = "UPDATE SOMETHING SET OTHER=1"; + mockSpanner.putStatementResult( + StatementResult.exception( + Statement.of(sql), + Status.INVALID_ARGUMENT.withDescription("test").asRuntimeException())); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + while (rs.next()) { + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + try { + connection.createStatement().executeUpdate(sql); + fail("missing 'test' exception"); + } catch (SQLException e) { + // ignore + } + // Set the update statement to return a result next time (i.e. during retry). + mockSpanner.putStatementResult(StatementResult.update(Statement.of(sql), 1L)); + mockSpanner.abortAllTransactions(); + connection.commit(); + fail("missing expected aborted exception"); + } catch (JdbcAbortedDueToConcurrentModificationException e) { + assertThat(e.getDatabaseErrorDuringRetry(), is(nullValue())); + throw e; + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java new file mode 100644 index 000000000000..50a696fa5122 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 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 java.sql.Date; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcArrayTest { + + @Test + public void testCreateArrayTypeName() throws SQLException { + // Note that JDBC array indices start at 1. + JdbcArray array; + array = JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}); + assertEquals(array.getBaseType(), Types.BOOLEAN); + assertEquals(((Boolean[]) array.getArray(1, 1))[0], Boolean.TRUE); + + array = JdbcArray.createArray("BYTES", new byte[][] {new byte[] {1, 2}, new byte[] {3, 4}}); + assertEquals(array.getBaseType(), Types.BINARY); + assertEquals(((byte[][]) array.getArray(1, 1))[0][1], (byte) 2); + + array = + JdbcArray.createArray("DATE", new Date[] {new Date(1L), new Date(100L), new Date(1000L)}); + assertEquals(array.getBaseType(), Types.DATE); + assertEquals(((Date[]) array.getArray(1, 1))[0], new Date(1L)); + + array = JdbcArray.createArray("FLOAT64", new Double[] {1.1D, 2.2D, Math.PI}); + assertEquals(array.getBaseType(), Types.DOUBLE); + assertEquals(((Double[]) array.getArray(1, 3))[2], Double.valueOf(Math.PI)); + + array = JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}); + assertEquals(array.getBaseType(), Types.BIGINT); + assertEquals(((Long[]) array.getArray(1, 1))[0], Long.valueOf(1L)); + + array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); + assertEquals(array.getBaseType(), Types.NVARCHAR); + assertEquals(((String[]) array.getArray(1, 1))[0], "foo"); + + array = + JdbcArray.createArray( + "TIMESTAMP", + new Timestamp[] {new Timestamp(1L), new Timestamp(100L), new Timestamp(1000L)}); + assertEquals(array.getBaseType(), Types.TIMESTAMP); + assertEquals(((Timestamp[]) array.getArray(1, 1))[0], new Timestamp(1L)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java new file mode 100644 index 000000000000..c629eac207cf --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java @@ -0,0 +1,349 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.rpc.Code; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.SQLException; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcBlobTest { + + private static final class PosLength { + private final long pos; + private final int len; + + private static PosLength of(long pos, int len) { + return new PosLength(pos, len); + } + + private PosLength(long pos, int len) { + this.pos = pos; + this.len = len; + } + + @Override + public String toString() { + return "pos: " + pos + ", len: " + len; + } + } + + private static final class PosBytes { + private final long pos; + private final byte[] bytes; + + private static PosBytes of(long pos, byte[] bytes) { + return new PosBytes(pos, bytes); + } + + private PosBytes(long pos, byte[] bytes) { + this.pos = pos; + this.bytes = bytes; + } + + @Override + public String toString() { + return "pos: " + pos + ", bytes: " + Arrays.toString(bytes); + } + } + + @Test + public void testLength() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + assertThat(blob.length(), is(equalTo(0L))); + blob.setBytes(1L, new byte[] {1, 2, 3}); + assertThat(blob.length(), is(equalTo(3L))); + blob.free(); + assertThat(blob.length(), is(equalTo(0L))); + } + + @Test + public void testGetBytes() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + assertThat(blob.getBytes(1L, 5), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + assertThat(blob.getBytes(2L, 5), is(equalTo(new byte[] {2, 3, 4, 5}))); + assertThat(blob.getBytes(2L, 3), is(equalTo(new byte[] {2, 3, 4}))); + assertThat(blob.getBytes(1L, 0), is(equalTo(new byte[] {}))); + + // test invalid parameters + PosLength[] params = + new PosLength[] {PosLength.of(0L, 4), PosLength.of(-1L, 4), PosLength.of(1L, -1)}; + for (PosLength param : params) { + boolean exception = false; + try { + blob.getBytes(param.pos, param.len); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testGetBinaryStream() throws SQLException, IOException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + byte[] buf = new byte[5]; + try (InputStream is = blob.getBinaryStream()) { + int b; + int index = 0; + while ((b = is.read()) > -1) { + buf[index] = (byte) b; + index++; + } + } + assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + + buf = new byte[10]; + try (InputStream is = blob.getBinaryStream()) { + assertThat(is.read(buf), is(equalTo(5))); + assertThat(is.read(), is(equalTo(-1))); + } + assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 4, 5, 0, 0, 0, 0, 0}))); + } + + @Test + public void testPosition() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + assertThat(blob.position(new byte[] {1}, 1L), is(equalTo(1L))); + assertThat(blob.position(new byte[] {1, 2}, 1L), is(equalTo(1L))); + assertThat(blob.position(new byte[] {2}, 1L), is(equalTo(2L))); + // note that the spec says that the method should return the position within the BLOB where the + // pattern can be found, so it's not relative to the starting position. + assertThat(blob.position(new byte[] {2}, 2L), is(equalTo(2L))); + assertThat(blob.position(new byte[] {1, 2, 3, 4, 5}, 1L), is(equalTo(1L))); + assertThat(blob.position(new byte[] {1, 2, 3, 4, 5, 6}, 1L), is(equalTo(-1L))); + assertThat(blob.position(new byte[] {1, 2, 3, 4, 5}, 2L), is(equalTo(-1L))); + assertThat(blob.position(new byte[] {2}, 3L), is(equalTo(-1L))); + assertThat(blob.position(new byte[] {1}, 6L), is(equalTo(-1L))); + + // test invalid parameters + PosBytes[] params = + new PosBytes[] { + PosBytes.of(0L, new byte[] {}), PosBytes.of(-1L, new byte[] {}), PosBytes.of(1L, null) + }; + for (PosBytes param : params) { + boolean exception = false; + try { + blob.position(param.bytes, param.pos); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testPositionBlob() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + + assertThat(blob.position(createBlob((byte) 1), 1L), is(equalTo(1L))); + assertThat(blob.position(createBlob((byte) 1, (byte) 2), 1L), is(equalTo(1L))); + assertThat(blob.position(createBlob((byte) 2), 1L), is(equalTo(2L))); + // note that the spec says that the method should return the position within the BLOB where the + // pattern can be found, so it's not relative to the starting position. + assertThat(blob.position(createBlob((byte) 2), 2L), is(equalTo(2L))); + assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 1L), is(equalTo(1L))); + assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5, 6}), 1L), is(equalTo(-1L))); + assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 2L), is(equalTo(-1L))); + assertThat(blob.position(createBlob(new byte[] {2}), 3L), is(equalTo(-1L))); + assertThat(blob.position(createBlob(new byte[] {1}), 6L), is(equalTo(-1L))); + + // test invalid parameters + PosBytes[] params = + new PosBytes[] { + PosBytes.of(0L, new byte[] {}), PosBytes.of(-1L, new byte[] {}), PosBytes.of(1L, null) + }; + for (PosBytes param : params) { + boolean exception = false; + try { + blob.position(createBlob(param.bytes), param.pos); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + private JdbcBlob createBlob(byte... bytes) throws SQLException { + if (bytes == null) { + return null; + } + JdbcBlob res = new JdbcBlob(); + res.setBytes(1L, bytes); + return res; + } + + @Test + public void testSetBytes() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3}); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 2, 3}))); + blob.setBytes(2L, new byte[] {1}); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3}))); + blob.setBytes(4L, new byte[] {4}); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3, 4}))); + blob.setBytes(8L, new byte[] {8}); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3, 4, 0, 0, 0, 8}))); + } + + @Test + public void testSetBytesOffsetLength() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(4L, new byte[] {1, 2, 3}, 0, 3); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0, 1, 2, 3}))); + blob.free(); + blob.setBytes(4L, new byte[] {1, 2, 3}, 1, 3); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0, 2, 3}))); + blob.free(); + blob.setBytes(4L, new byte[] {1, 2, 3}, 3, 3); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0}))); + blob.free(); + blob.setBytes(4L, new byte[] {1, 2, 3}, 4, 3); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0}))); + blob.setBytes(2L, new byte[] {1, 2, 3}, 0, 10); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 1, 2, 3}))); + blob.setBytes(3L, new byte[] {1, 2, 3}, 2, 10); + assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 1, 3, 3}))); + blob.setBytes(10L, new byte[] {1, 2, 3}, 2, 10); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {0, 1, 3, 3, 0, 0, 0, 0, 0, 3}))); + } + + @Test + public void testSetBinaryStream() throws SQLException, IOException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + try (OutputStream os = blob.setBinaryStream(1L)) { + os.write(6); + // no flush yet, so it should be unchanged + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + os.flush(); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 2, 3, 4, 5}))); + os.write(7); + } + // closing the stream should also flush the changes + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 7, 3, 4, 5}))); + + // test writing beyond the end of the stream + try (OutputStream os = blob.setBinaryStream(1L)) { + os.write(new byte[] {1, 2, 3, 4, 5, 6, 7}); + // no flush yet, so it should be unchanged + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 7, 3, 4, 5}))); + os.flush(); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + } + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + + // test writing from a position that is larger than 1 + try (OutputStream os = blob.setBinaryStream(5L)) { + os.write(new byte[] {1, 2, 3}); + // no flush yet, so it should be unchanged + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + os.flush(); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3}))); + } + + // test writing from a position that is larger than the current length + try (OutputStream os = blob.setBinaryStream(10L)) { + os.write(new byte[] {1, 2, 3}); + // no flush yet, so it should be unchanged + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3}))); + os.flush(); + assertThat( + blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}))); + } + + // test writing a large number of bytes + try (OutputStream os = blob.setBinaryStream(1L)) { + os.write(new byte[2000]); + // no flush yet, so it should be unchanged + assertThat( + blob.getBytes(1L, 3000), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}))); + os.flush(); + assertThat(blob.getBytes(1L, 3000), is(equalTo(new byte[2000]))); + } + } + + @Test + public void testTruncate() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + blob.truncate(3); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3}))); + blob.truncate(0); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {}))); + } + + @Test + public void testFree() throws SQLException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + blob.free(); + assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {}))); + } + + @Test + public void testGetBinaryStreamPosLength() throws SQLException, IOException { + JdbcBlob blob = new JdbcBlob(); + blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); + + byte[] buf = new byte[5]; + try (InputStream is = blob.getBinaryStream(1L, 3)) { + int b; + int index = 0; + while ((b = is.read()) > -1) { + buf[index] = (byte) b; + index++; + } + } + assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 0, 0}))); + + buf = new byte[10]; + try (InputStream is = blob.getBinaryStream(4L, 10)) { + assertThat(is.read(buf), is(equalTo(2))); + assertThat(is.read(), is(equalTo(-1))); + } + assertThat(buf, is(equalTo(new byte[] {4, 5, 0, 0, 0, 0, 0, 0, 0, 0}))); + + buf = new byte[10]; + try (InputStream is = blob.getBinaryStream(6L, 10)) { + assertThat(is.read(buf), is(equalTo(-1))); + } + assertThat(buf, is(equalTo(new byte[10]))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java new file mode 100644 index 000000000000..3bb04fc6309a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java @@ -0,0 +1,329 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.rpc.Code; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcClobTest { + + private static final class PosLength { + private final long pos; + private final int len; + + private static PosLength of(long pos, int len) { + return new PosLength(pos, len); + } + + private PosLength(long pos, int len) { + this.pos = pos; + this.len = len; + } + + @Override + public String toString() { + return "pos: " + pos + ", len: " + len; + } + } + + private static final class PosString { + private final long pos; + private final String str; + + private static PosString of(long pos, String str) { + return new PosString(pos, str); + } + + private PosString(long pos, String str) { + this.pos = pos; + this.str = str; + } + + @Override + public String toString() { + return "pos: " + pos + ", str: " + str; + } + } + + @Test + public void testLength() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + assertThat(clob.length(), is(equalTo(4L))); + clob.setString(1L, "test-test"); + assertThat(clob.length(), is(equalTo(9L))); + } + + @Test + public void testGetSubstring() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + assertThat(clob.getSubString(1, 4), is(equalTo("test"))); + assertThat(clob.getSubString(1, 2), is(equalTo("te"))); + assertThat(clob.getSubString(3, 2), is(equalTo("st"))); + assertThat(clob.getSubString(1, 5), is(equalTo("test"))); + assertThat(clob.getSubString(4, 5), is(equalTo("t"))); + assertThat(clob.getSubString(5, 5), is(equalTo(""))); + assertThat(clob.getSubString(6, 5), is(equalTo(""))); + + // test invalid parameters + PosLength[] params = + new PosLength[] {PosLength.of(0L, 4), PosLength.of(-1L, 4), PosLength.of(1L, -1)}; + for (PosLength param : params) { + boolean exception = false; + try { + clob.getSubString(param.pos, param.len); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testGetCharacterStream() throws SQLException, IOException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + char[] cbuf = new char[4]; + try (Reader reader = clob.getCharacterStream()) { + reader.read(cbuf, 0, 4); + } + assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + try (Reader reader = clob.getCharacterStream()) { + reader.read(cbuf, 0, 2); + reader.read(cbuf, 2, 2); + } + assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + try (Reader reader = clob.getCharacterStream()) { + reader.read(cbuf, 0, 2); + // changing the value of the clob will not change a character stream that has already been + // opened + clob.setString(1L, "foobar"); + reader.read(cbuf, 2, 2); + } + assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + } + + @Test + public void testPositionString() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + assertThat(clob.position("st", 1L), is(equalTo(3L))); + clob.setString(1L, "foobarfoobar"); + assertThat(clob.position("bar", 1L), is(equalTo(4L))); + assertThat(clob.position("bar", 2L), is(equalTo(4L))); + assertThat(clob.position("bar", 5L), is(equalTo(10L))); + assertThat(clob.position("bar", 8L), is(equalTo(10L))); + assertThat(clob.position("bar", 10L), is(equalTo(10L))); + assertThat(clob.position("bar", 11L), is(equalTo(-1L))); + assertThat(clob.position("bar", 100L), is(equalTo(-1L))); + assertThat(clob.position("not_there", 1L), is(equalTo(-1L))); + // test invalid parameters + PosString[] params = + new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; + for (PosString param : params) { + boolean exception = false; + try { + clob.position(param.str, param.pos); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testPositionClob() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + JdbcClob search = new JdbcClob(); + search.setString(1L, "st"); + assertThat(clob.position(search, 1L), is(equalTo(3L))); + clob.setString(1L, "foobarfoobar"); + search.setString(1L, "bar"); + assertThat(clob.position(search, 1L), is(equalTo(4L))); + assertThat(clob.position(search, 2L), is(equalTo(4L))); + assertThat(clob.position(search, 5L), is(equalTo(10L))); + assertThat(clob.position(search, 8L), is(equalTo(10L))); + assertThat(clob.position(search, 10L), is(equalTo(10L))); + assertThat(clob.position(search, 11L), is(equalTo(-1L))); + assertThat(clob.position(search, 100L), is(equalTo(-1L))); + search.setString(1L, "not_there"); + assertThat(clob.position(search, 1L), is(equalTo(-1L))); + // test invalid parameters + PosString[] params = + new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; + for (PosString param : params) { + boolean exception = false; + try { + search.setString(1L, param.str); + clob.position(search, param.pos); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testSetString() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test"); + assertThat(clob.getSubString(1L, 4), is(equalTo("test"))); + clob.setString(1L, "bar"); + assertThat(clob.getSubString(1L, 4), is(equalTo("bart"))); + clob.setString(1L, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + clob.setString(2L, "foobar"); + assertThat(clob.getSubString(1L, 7), is(equalTo("ffoobar"))); + clob.setString(8L, "test"); + assertThat(clob.getSubString(1L, 11), is(equalTo("ffoobartest"))); + clob.setString(15, "end"); + assertThat(clob.getSubString(1L, 17), is(equalTo("ffoobartest end"))); + // test invalid parameters + PosString[] params = + new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; + for (PosString param : params) { + boolean exception = false; + try { + clob.setString(param.pos, param.str); + } catch (SQLException e) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } + assertThat(param.toString(), exception, is(true)); + } + } + + @Test + public void testSetStringOffsetLen() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "test", 2, 3); + assertThat(clob.getSubString(1L, 4), is(equalTo("est"))); + clob.setString(1L, "bar", 1, 1); + assertThat(clob.getSubString(1L, 4), is(equalTo("bst"))); + clob.setString(1L, "foobar", 1, 6); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + clob.setString(2L, "foobar", 2, 5); + assertThat(clob.getSubString(1L, 7), is(equalTo("foobar"))); + clob.setString(8L, "test", 4, 1); + assertThat(clob.getSubString(1L, 8), is(equalTo("foobar t"))); + clob.setString(15, "end", 1, 3); + assertThat(clob.getSubString(1L, 17), is(equalTo("foobar t end"))); + } + + @Test + public void testSetCharacterStream() throws SQLException, IOException { + JdbcClob clob = new JdbcClob(); + clob.setString(1, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + try (Writer writer = clob.setCharacterStream(1L)) { + writer.write("t"); + // not yet flushed, there should be no change + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + writer.flush(); + // after a flush the change should be visible + assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + writer.write("est"); + } + // close should also autoflush + assertThat(clob.getSubString(1L, 6), is(equalTo("testar"))); + + // start all over + clob.free(); + clob.setString(1, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + try (Writer writer = clob.setCharacterStream(5L)) { + writer.write("t"); + // not yet flushed, there should be no change + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + writer.flush(); + // after a flush the change should be visible + assertThat(clob.getSubString(1L, 6), is(equalTo("foobtr"))); + writer.write("est"); + } + // close should also autoflush + assertThat(clob.getSubString(1L, 8), is(equalTo("foobtest"))); + + // do a test with multiple flushes + clob.free(); + clob.setString(1, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + try (Writer writer = clob.setCharacterStream(1L)) { + writer.write("t"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + writer.flush(); + assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + writer.write("est"); + assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + writer.flush(); + assertThat(clob.getSubString(1L, 6), is(equalTo("testar"))); + } + assertThat(clob.getSubString(1L, 8), is(equalTo("testar"))); + + // writer after end + clob.free(); + clob.setString(1, "foobar"); + assertThat(clob.getSubString(1L, 10), is(equalTo("foobar"))); + try (Writer writer = clob.setCharacterStream(10L)) { + writer.write("t"); + assertThat(clob.getSubString(1L, 20), is(equalTo("foobar"))); + writer.flush(); + assertThat(clob.getSubString(1L, 20), is(equalTo("foobar t"))); + writer.write("est"); + } + assertThat(clob.getSubString(1L, 20), is(equalTo("foobar test"))); + } + + @Test + public void testTruncate() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + clob.truncate(3L); + assertThat(clob.getSubString(1L, 6), is(equalTo("foo"))); + clob.truncate(0L); + assertThat(clob.getSubString(1L, 6), is(equalTo(""))); + } + + @Test + public void testFree() throws SQLException { + JdbcClob clob = new JdbcClob(); + clob.setString(1L, "foobar"); + assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + clob.free(); + assertThat(clob.getSubString(1L, 6), is(equalTo(""))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java new file mode 100644 index 000000000000..8fdbeacbd543 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 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.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * This test executes a SQL script that has been generated from the log of all the subclasses of + * {@link AbstractConnectionImplTest} and covers the same test cases. Its aim is to verify that the + * connection reacts correctly in all possible states (i.e. DML statements should not be allowed + * when the connection is in read-only mode, or when a read-only transaction has started etc.) + */ +@RunWith(JUnit4.class) +public class JdbcConnectionGeneratedSqlScriptTest { + + static class TestConnectionProvider implements GenericConnectionProvider { + @Override + public GenericConnection getConnection() { + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.getUri()).thenReturn(ConnectionImplTest.URI); + com.google.cloud.spanner.jdbc.Connection spannerConnection = + ConnectionImplTest.createConnection(options); + when(options.getConnection()).thenReturn(spannerConnection); + JdbcConnection connection = + new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options); + JdbcGenericConnection res = JdbcGenericConnection.of(connection); + res.setStripCommentsBeforeExecute(true); + return res; + } + } + + @Test + public void testGeneratedScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile( + "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class, false); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java new file mode 100644 index 000000000000..68bf06058b54 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -0,0 +1,416 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.rpc.Code; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Savepoint; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcConnectionTest { + @Rule public final ExpectedException exception = ExpectedException.none(); + + private JdbcConnection createConnection(ConnectionOptions options) { + com.google.cloud.spanner.jdbc.Connection spannerConnection = + ConnectionImplTest.createConnection(options); + when(options.getConnection()).thenReturn(spannerConnection); + return new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options); + } + + @Test + public void testAutoCommit() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.isAutocommit()).thenReturn(true); + try (Connection connection = createConnection(options)) { + assertThat(connection.getAutoCommit(), is(true)); + connection.setAutoCommit(false); + assertThat(connection.getAutoCommit(), is(false)); + // execute a query that will start a transaction + connection.createStatement().executeQuery(AbstractConnectionImplTest.SELECT); + // setting autocommit will automatically commit the transaction + connection.setAutoCommit(true); + assertThat(connection.getAutoCommit(), is(true)); + } + } + + @Test + public void testReadOnly() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.isAutocommit()).thenReturn(true); + when(options.isReadOnly()).thenReturn(true); + try (Connection connection = createConnection(options)) { + assertThat(connection.isReadOnly(), is(true)); + connection.setReadOnly(false); + assertThat(connection.isReadOnly(), is(false)); + // start a transaction + connection.createStatement().execute("begin transaction"); + // setting readonly should no longer be allowed + exception.expect(JdbcExceptionMatcher.matchCode(Code.FAILED_PRECONDITION)); + connection.setReadOnly(true); + } + } + + @Test + public void testCommit() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + // verify that there is no transaction started + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + // start a transaction + connection.createStatement().execute(AbstractConnectionImplTest.SELECT); + // verify that we did start a transaction + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(true)); + // do a commit + connection.commit(); + // verify that there is no transaction started anymore + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + // verify that there is a commit timestamp + assertThat(connection.getSpannerConnection().getCommitTimestamp(), is(notNullValue())); + } + } + + @Test + public void testRollback() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + // verify that there is no transaction started + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + // start a transaction + connection.createStatement().execute(AbstractConnectionImplTest.SELECT); + // verify that we did start a transaction + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(true)); + // do a rollback + connection.rollback(); + // verify that there is no transaction started anymore + assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + // verify that there is no commit timestamp + try (ResultSet rs = + connection.createStatement().executeQuery("show variable commit_timestamp")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getTimestamp("COMMIT_TIMESTAMP"), is(nullValue())); + } + } + } + + @Test + public void testClosedAbstractJdbcConnection() + throws SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException {} + + @Test + public void testClosedJdbcConnection() + throws SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException { + testClosed(Connection.class, "getCatalog"); + testClosed(Connection.class, "getWarnings"); + testClosed(Connection.class, "clearWarnings"); + testClosed(Connection.class, "getHoldability"); + testClosed(Connection.class, "createClob"); + testClosed(Connection.class, "createBlob"); + testClosed(Connection.class, "createNClob"); + testClosed(Connection.class, "createSQLXML"); + testClosed(Connection.class, "getCatalog"); + testClosed(Connection.class, "getClientInfo"); + testClosed(Connection.class, "getSchema"); + testClosed(Connection.class, "getNetworkTimeout"); + + testClosed( + Connection.class, "setCatalog", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, + "prepareCall", + new Class[] {String.class, int.class, int.class}, + new Object[] {"TEST", 0, 0}); + testClosed( + Connection.class, + "prepareCall", + new Class[] {String.class, int.class, int.class, int.class}, + new Object[] {"TEST", 0, 0, 0}); + testClosed( + Connection.class, + "setClientInfo", + new Class[] {String.class, String.class}, + new Object[] {"TEST", "TEST"}); + testClosed( + Connection.class, "setClientInfo", new Class[] {Properties.class}, new Object[] {null}); + testClosed( + Connection.class, "getClientInfo", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, + "createStruct", + new Class[] {String.class, Object[].class}, + new Object[] {"TEST", new Object[] {}}); + testClosed(Connection.class, "setSchema", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, + "setNetworkTimeout", + new Class[] {Executor.class, int.class}, + new Object[] {null, 0}); + + testClosed(Connection.class, "getTypeMap"); + testClosed(Connection.class, "createStatement"); + testClosed(Connection.class, "getAutoCommit"); + testClosed(Connection.class, "commit"); + testClosed(Connection.class, "rollback"); + testClosed(Connection.class, "getMetaData"); + testClosed(Connection.class, "isReadOnly"); + testClosed(Connection.class, "getTransactionIsolation"); + testClosed(Connection.class, "setSavepoint"); + + testClosed( + Connection.class, + "setTypeMap", + new Class[] {Map.class}, + new Object[] {Collections.EMPTY_MAP}); + testClosed( + Connection.class, "prepareStatement", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, "prepareCall", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed(Connection.class, "nativeSQL", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, "prepareStatement", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed( + Connection.class, "setAutoCommit", new Class[] {boolean.class}, new Object[] {true}); + testClosed( + Connection.class, "setReadOnly", new Class[] {boolean.class}, new Object[] {true}); + testClosed( + Connection.class, "setTransactionIsolation", new Class[] {int.class}, new Object[] {0}); + testClosed( + Connection.class, + "createStatement", + new Class[] {int.class, int.class}, + new Object[] {0, 0}); + testClosed( + Connection.class, + "prepareStatement", + new Class[] {String.class, int.class, int.class}, + new Object[] {"TEST", 0, 0}); + testClosed( + Connection.class, + "createStatement", + new Class[] {int.class, int.class, int.class}, + new Object[] {0, 0, 0}); + testClosed( + Connection.class, + "prepareStatement", + new Class[] {String.class, int.class, int.class, int.class}, + new Object[] {"TEST", 0, 0, 0}); + testClosed( + Connection.class, + "prepareStatement", + new Class[] {String.class, int.class}, + new Object[] {"TEST", 0}); + testClosed( + Connection.class, + "prepareStatement", + new Class[] {String.class, int[].class}, + new Object[] {"TEST", new int[] {0}}); + testClosed( + Connection.class, + "prepareStatement", + new Class[] {String.class, String[].class}, + new Object[] {"TEST", new String[] {"COL1"}}); + testClosed( + Connection.class, + "createArrayOf", + new Class[] {String.class, Object[].class}, + new Object[] {"TEST", new Object[] {"COL1"}}); + + testClosed( + Connection.class, "setSavepoint", new Class[] {String.class}, new Object[] {"TEST"}); + testClosed(Connection.class, "rollback", new Class[] {Savepoint.class}, new Object[] {null}); + testClosed( + Connection.class, + "releaseSavepoint", + new Class[] {Savepoint.class}, + new Object[] {null}); + } + + private void testClosed(Class clazz, String name) + throws NoSuchMethodException, SecurityException, SQLException, IllegalAccessException, + IllegalArgumentException { + testClosed(clazz, name, null, null); + } + + private void testClosed( + Class clazz, String name, Class[] paramTypes, Object[] args) + throws NoSuchMethodException, SecurityException, SQLException, IllegalAccessException, + IllegalArgumentException { + Method method = clazz.getDeclaredMethod(name, paramTypes); + testInvokeMethodOnClosedConnection(method, args); + } + + private void testInvokeMethodOnClosedConnection(Method method, Object... args) + throws SQLException, IllegalAccessException, IllegalArgumentException { + ConnectionOptions options = mock(ConnectionOptions.class); + JdbcConnection connection = createConnection(options); + connection.close(); + boolean valid = false; + try { + method.invoke(connection, args); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof JdbcSqlException + && ((JdbcSqlException) e.getTargetException()).getCode() == Code.FAILED_PRECONDITION + && ((JdbcSqlException) e.getTargetException()).getMessage().endsWith("has been closed")) { + // this is the expected exception + valid = true; + } + } + assertThat( + "Method did not throw exception on closed connection: " + method.getName(), + valid, + is(true)); + } + + @Test + public void testTransactionIsolation() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + assertThat( + connection.getTransactionIsolation(), is(equalTo(Connection.TRANSACTION_SERIALIZABLE))); + // assert that setting it to this value is ok. + connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); + // assert that setting it to something else is not ok. + int[] settings = + new int[] { + Connection.TRANSACTION_READ_COMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED, + Connection.TRANSACTION_REPEATABLE_READ, + -100 + }; + for (int setting : settings) { + boolean exception = false; + try { + connection.setTransactionIsolation(setting); + } catch (SQLException e) { + if (setting == -100) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } else { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.UNIMPLEMENTED); + } + } + assertThat(exception, is(true)); + } + } + } + + @Test + public void testHoldability() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + assertThat(connection.getHoldability(), is(equalTo(ResultSet.CLOSE_CURSORS_AT_COMMIT))); + // assert that setting it to this value is ok. + connection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + // assert that setting it to something else is not ok. + int[] settings = new int[] {ResultSet.HOLD_CURSORS_OVER_COMMIT, -100}; + for (int setting : settings) { + boolean exception = false; + try { + connection.setHoldability(setting); + } catch (SQLException e) { + if (setting == -100) { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); + } else { + exception = + (e instanceof JdbcSqlException + && ((JdbcSqlException) e).getCode() == Code.UNIMPLEMENTED); + } + } + assertThat(exception, is(true)); + } + } + } + + @Test + public void testWarnings() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + assertThat(connection.getWarnings(), is(nullValue())); + + // Push one warning and get it twice. + connection.pushWarning(new SQLWarning("test")); + assertThat(connection.getWarnings().getMessage(), is(equalTo("test"))); + assertThat(connection.getWarnings().getMessage(), is(equalTo("test"))); + + // Clear warnings and push two warnings and get them both. + connection.clearWarnings(); + connection.pushWarning(new SQLWarning("test 1")); + connection.pushWarning(new SQLWarning("test 2")); + assertThat(connection.getWarnings().getMessage(), is(equalTo("test 1"))); + assertThat(connection.getWarnings().getMessage(), is(equalTo("test 1"))); + assertThat(connection.getWarnings().getNextWarning().getMessage(), is(equalTo("test 2"))); + + // Clear warnings. + connection.clearWarnings(); + assertThat(connection.getWarnings(), is(nullValue())); + } + } + + @Test + public void testSetClientInfo() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + assertThat(connection.getWarnings(), is(nullValue())); + connection.setClientInfo("test", "foo"); + assertThat(connection.getWarnings(), is(notNullValue())); + assertThat( + connection.getWarnings().getMessage(), + is(equalTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED))); + + connection.clearWarnings(); + assertThat(connection.getWarnings(), is(nullValue())); + + Properties props = new Properties(); + props.setProperty("test", "foo"); + connection.setClientInfo(props); + assertThat(connection.getWarnings(), is(notNullValue())); + assertThat( + connection.getWarnings().getMessage(), + is(equalTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED))); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java new file mode 100644 index 000000000000..db7c7f812837 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -0,0 +1,434 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.auth.oauth2.GoogleCredentials; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowIdLifetime; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcDatabaseMetaDataTest { + private static final String DEFAULT_CATALOG = ""; + private static final String DEFAULT_SCHEMA = ""; + private static final String TEST_TABLE = "FOO"; + private static final int DATABASE_MAJOR_VERSION = 1; + private static final int DATABASE_MINOR_VERSION = 0; + private static final String DATABASE_PRODUCT_NAME = "Google Cloud Spanner"; + + @Test + public void testTrivialMethods() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + assertThat(meta.allProceduresAreCallable(), is(true)); + assertThat(meta.allTablesAreSelectable(), is(true)); + assertThat(meta.autoCommitFailureClosesAllResultSets(), is(false)); + assertThat(meta.dataDefinitionCausesTransactionCommit(), is(false)); + assertThat(meta.dataDefinitionIgnoredInTransactions(), is(false)); + for (int type : + new int[] { + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE + }) { + assertThat(meta.deletesAreDetected(type), is(false)); + assertThat(meta.insertsAreDetected(type), is(false)); + } + assertThat(meta.doesMaxRowSizeIncludeBlobs(), is(true)); + assertThat(meta.generatedKeyAlwaysReturned(), is(false)); + assertThat(meta.getCatalogSeparator(), is(equalTo("."))); + assertThat(meta.getCatalogTerm(), is(equalTo("CATALOG"))); + assertThat(meta.getDatabaseMajorVersion(), is(equalTo(DATABASE_MAJOR_VERSION))); + assertThat(meta.getDatabaseMinorVersion(), is(equalTo(DATABASE_MINOR_VERSION))); + assertThat(meta.getDatabaseProductName(), is(equalTo(DATABASE_PRODUCT_NAME))); + assertThat( + meta.getDatabaseProductVersion(), + is(equalTo(DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION))); + assertThat(meta.getDriverName(), is(equalTo("com.google.cloud.spanner.jdbc.JdbcDriver"))); + assertThat(meta.getExtraNameCharacters(), is(equalTo(""))); + assertThat(meta.getIdentifierQuoteString(), is(equalTo("`"))); + assertThat(meta.getJDBCMajorVersion(), is(equalTo(4))); + assertThat(meta.getJDBCMinorVersion(), is(equalTo(1))); // Java 7 is JDBC 4.1 + assertThat(meta.getMaxBinaryLiteralLength(), is(equalTo(0))); + assertThat(meta.getMaxCatalogNameLength(), is(equalTo(0))); + assertThat(meta.getMaxCharLiteralLength(), is(equalTo(0))); + assertThat(meta.getMaxColumnNameLength(), is(equalTo(128))); + assertThat(meta.getMaxColumnsInGroupBy(), is(equalTo(1000))); + assertThat(meta.getMaxColumnsInIndex(), is(equalTo(16))); + assertThat(meta.getMaxColumnsInOrderBy(), is(equalTo(0))); + assertThat(meta.getMaxColumnsInSelect(), is(equalTo(0))); + assertThat(meta.getMaxColumnsInTable(), is(equalTo(1024))); + assertThat(meta.getMaxConnections(), is(equalTo(0))); // there is a max number of sessions, but + // that is not the same as connections + assertThat(meta.getMaxCursorNameLength(), is(equalTo(0))); + assertThat(meta.getMaxIndexLength(), is(equalTo(8000))); + assertThat(meta.getMaxProcedureNameLength(), is(equalTo(0))); + assertThat(meta.getMaxRowSize(), is(equalTo(1024 * 10000000))); + assertThat(meta.getMaxSchemaNameLength(), is(equalTo(0))); + assertThat(meta.getMaxStatementLength(), is(equalTo(1000000))); + assertThat(meta.getMaxStatements(), is(equalTo(0))); + assertThat(meta.getMaxTableNameLength(), is(equalTo(128))); + assertThat(meta.getMaxTablesInSelect(), is(equalTo(0))); + assertThat(meta.getMaxUserNameLength(), is(equalTo(0))); + assertThat(meta.getProcedureTerm(), is(equalTo("PROCEDURE"))); + assertThat(meta.getResultSetHoldability(), is(equalTo(ResultSet.CLOSE_CURSORS_AT_COMMIT))); + assertThat(meta.getRowIdLifetime(), is(equalTo(RowIdLifetime.ROWID_UNSUPPORTED))); + assertThat(meta.getSchemaTerm(), is(equalTo("SCHEMA"))); + assertThat(meta.getSearchStringEscape(), is(equalTo("\\"))); + assertThat(meta.getSQLStateType(), is(equalTo(DatabaseMetaData.sqlStateSQL))); + assertThat(meta.isCatalogAtStart(), is(false)); + assertThat(meta.isReadOnly(), is(equalTo(connection.isReadOnly()))); + assertThat(meta.storesLowerCaseIdentifiers(), is(false)); + assertThat(meta.storesLowerCaseQuotedIdentifiers(), is(false)); + assertThat(meta.storesMixedCaseIdentifiers(), is(true)); + assertThat(meta.storesMixedCaseQuotedIdentifiers(), is(true)); + assertThat(meta.storesUpperCaseIdentifiers(), is(false)); + assertThat(meta.storesUpperCaseQuotedIdentifiers(), is(false)); + assertThat(meta.supportsAlterTableWithAddColumn(), is(true)); + assertThat(meta.supportsAlterTableWithDropColumn(), is(true)); + assertThat(meta.supportsANSI92EntryLevelSQL(), is(false)); + assertThat(meta.supportsANSI92FullSQL(), is(false)); + assertThat(meta.supportsANSI92IntermediateSQL(), is(false)); + assertThat(meta.supportsBatchUpdates(), is(true)); + assertThat(meta.supportsCatalogsInDataManipulation(), is(false)); + assertThat(meta.supportsCatalogsInIndexDefinitions(), is(false)); + assertThat(meta.supportsCatalogsInPrivilegeDefinitions(), is(false)); + assertThat(meta.supportsCatalogsInProcedureCalls(), is(false)); + assertThat(meta.supportsCatalogsInTableDefinitions(), is(false)); + assertThat(meta.supportsColumnAliasing(), is(true)); + assertThat(meta.supportsConvert(), is(false)); + assertThat(meta.supportsCoreSQLGrammar(), is(false)); + assertThat(meta.supportsCorrelatedSubqueries(), is(true)); + assertThat(meta.supportsDataDefinitionAndDataManipulationTransactions(), is(false)); + assertThat(meta.supportsDataManipulationTransactionsOnly(), is(true)); + assertThat(meta.supportsDifferentTableCorrelationNames(), is(false)); + assertThat(meta.supportsExpressionsInOrderBy(), is(true)); + assertThat(meta.supportsExtendedSQLGrammar(), is(false)); + assertThat(meta.supportsFullOuterJoins(), is(true)); + assertThat(meta.supportsGetGeneratedKeys(), is(false)); + assertThat(meta.supportsGroupBy(), is(true)); + assertThat(meta.supportsGroupByBeyondSelect(), is(true)); + assertThat(meta.supportsGroupByUnrelated(), is(true)); + assertThat(meta.supportsIntegrityEnhancementFacility(), is(false)); + assertThat(meta.supportsLikeEscapeClause(), is(true)); + assertThat(meta.supportsLimitedOuterJoins(), is(true)); + assertThat(meta.supportsMinimumSQLGrammar(), is(false)); + assertThat(meta.supportsMixedCaseIdentifiers(), is(false)); + assertThat(meta.supportsMixedCaseQuotedIdentifiers(), is(false)); + assertThat(meta.supportsMultipleOpenResults(), is(true)); + assertThat(meta.supportsMultipleResultSets(), is(true)); + assertThat(meta.supportsMultipleTransactions(), is(true)); + assertThat(meta.supportsNamedParameters(), is(false)); + assertThat(meta.supportsNonNullableColumns(), is(true)); + assertThat(meta.supportsOpenCursorsAcrossCommit(), is(false)); + assertThat(meta.supportsOpenCursorsAcrossRollback(), is(false)); + assertThat(meta.supportsOpenStatementsAcrossCommit(), is(true)); + assertThat(meta.supportsOpenStatementsAcrossRollback(), is(true)); + assertThat(meta.supportsOrderByUnrelated(), is(true)); + assertThat(meta.supportsOuterJoins(), is(true)); + assertThat(meta.supportsPositionedDelete(), is(false)); + assertThat(meta.supportsPositionedUpdate(), is(false)); + for (int type : + new int[] { + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE + }) { + assertThat(meta.supportsResultSetType(type), is(type == ResultSet.TYPE_FORWARD_ONLY)); + for (int concur : new int[] {ResultSet.CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}) { + assertThat( + meta.supportsResultSetConcurrency(type, concur), + is(type == ResultSet.TYPE_FORWARD_ONLY && concur == ResultSet.CONCUR_READ_ONLY)); + } + } + assertThat(meta.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT), is(true)); + assertThat(meta.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT), is(false)); + assertThat(meta.supportsSavepoints(), is(false)); + assertThat(meta.supportsSchemasInDataManipulation(), is(false)); + assertThat(meta.supportsSchemasInIndexDefinitions(), is(false)); + assertThat(meta.supportsSchemasInPrivilegeDefinitions(), is(false)); + assertThat(meta.supportsSchemasInProcedureCalls(), is(false)); + assertThat(meta.supportsSchemasInTableDefinitions(), is(false)); + assertThat(meta.supportsSelectForUpdate(), is(false)); + assertThat(meta.supportsStatementPooling(), is(false)); + assertThat(meta.supportsStoredFunctionsUsingCallSyntax(), is(false)); + assertThat(meta.supportsStoredProcedures(), is(false)); + assertThat(meta.supportsSubqueriesInComparisons(), is(true)); + assertThat(meta.supportsSubqueriesInExists(), is(true)); + assertThat(meta.supportsSubqueriesInIns(), is(true)); + assertThat(meta.supportsSubqueriesInQuantifieds(), is(true)); + assertThat(meta.supportsTableCorrelationNames(), is(true)); + assertThat( + meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE), is(true)); + for (int level : + new int[] { + Connection.TRANSACTION_NONE, + Connection.TRANSACTION_READ_COMMITTED, + Connection.TRANSACTION_READ_UNCOMMITTED, + Connection.TRANSACTION_REPEATABLE_READ + }) { + assertThat(meta.supportsTransactionIsolationLevel(level), is(false)); + } + + // trivial tests that guarantee that the function works, but the return value doesn't matter + assertThat(meta.getNumericFunctions(), is(notNullValue())); + assertThat(meta.getSQLKeywords(), is(notNullValue())); + assertThat(meta.getStringFunctions(), is(notNullValue())); + assertThat(meta.getSystemFunctions(), is(notNullValue())); + assertThat(meta.getTimeDateFunctions(), is(notNullValue())); + } + + @Test + public void testGetAttributes() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getAttributes(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(21))); + } + } + + @Test + public void testGetBestRowIdentifier() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = + meta.getBestRowIdentifier( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + TEST_TABLE, + DatabaseMetaData.bestRowTransaction, + false)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(8))); + } + } + + @Test + public void testGetCatalogs() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getCatalogs()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(""))); + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(1))); + } + } + + @Test + public void testGetClientInfoProperties() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getClientInfoProperties()) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(4))); + } + } + + public void testGetColumnPrivileges() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = + meta.getColumnPrivileges(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(8))); + } + } + + @Test + public void testGetFunctionColumns() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getFunctionColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(17))); + } + } + + @Test + public void testGetFunctions() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getFunctions(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(6))); + } + } + + @Test + public void testGetProcedureColumns() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getProcedureColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(20))); + } + } + + @Test + public void testGetProcedures() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getProcedures(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(9))); + } + } + + @Test + public void testGetPseudoColumns() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getPseudoColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(12))); + } + } + + @Test + public void testGetSuperTables() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getSuperTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(4))); + } + } + + @Test + public void testGetSuperTypes() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getSuperTypes(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(6))); + } + } + + @Test + public void testGetTablePrivileges() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getTablePrivileges(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(7))); + } + } + + @Test + public void testGetTableTypes() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getTableTypes()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_TYPE"), is(equalTo("TABLE"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_TYPE"), is(equalTo("VIEW"))); + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(1))); + } + } + + @Test + public void testGetTypeInfo() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getTypeInfo()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("STRING"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("INT64"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("BYTES"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("FLOAT64"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("BOOL"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("DATE"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("TIMESTAMP"))); + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(18))); + } + } + + @Test + public void testGetUDTs() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getUDTs(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(7))); + } + } + + @Test + public void testGetVersionColumns() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getVersionColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(8))); + } + } + + @Test + public void testGetUserName() throws SQLException, IOException { + GoogleCredentials credentials = + GoogleCredentials.fromStream( + ConnectionOptionsTest.class.getResource("test-key.json").openStream()); + JdbcConnection connection = mock(JdbcConnection.class); + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.getCredentials()).thenReturn(credentials); + when(connection.getConnectionOptions()).thenReturn(options); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + assertThat(meta.getUserName(), is(equalTo("test@test-project.iam.gserviceaccount.com"))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java new file mode 100644 index 000000000000..94e0523e5645 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcDriverTest { + private static final String TEST_KEY_PATH = + ConnectionOptionsTest.class.getResource("test-key.json").getFile(); + + /** + * Make sure the JDBC driver class is loaded. This is needed when running the test using Maven. + */ + static { + try { + Class.forName("com.google.cloud.spanner.jdbc.JdbcDriver"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException( + "JdbcDataSource failed to load com.google.cloud.spanner.jdbc.JdbcDriver", e); + } + } + + @Test + public void testConnect() throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/test-project/instances/static-test-instance/databases/test-database;credentials=%s", + TEST_KEY_PATH))) { + assertThat(connection.isClosed(), is(false)); + } + } + + @Test(expected = SQLException.class) + public void testInvalidConnect() throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/test-project/instances/static-test-instance/databases/test-database;credentialsUrl=%s", + TEST_KEY_PATH))) { + assertThat(connection.isClosed(), is(false)); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java new file mode 100644 index 000000000000..afe9657f0471 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java @@ -0,0 +1,64 @@ +/* + * Copyright 2019 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.common.base.Preconditions; +import com.google.rpc.Code; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +public final class JdbcExceptionMatcher extends BaseMatcher { + private final Code errorCode; + private final String message; + + public static JdbcExceptionMatcher matchCode(Code errorCode) { + Preconditions.checkNotNull(errorCode); + return new JdbcExceptionMatcher(errorCode, null); + } + + public static JdbcExceptionMatcher matchCodeAndMessage(Code errorCode, String message) { + Preconditions.checkNotNull(errorCode); + Preconditions.checkNotNull(message); + return new JdbcExceptionMatcher(errorCode, message); + } + + private JdbcExceptionMatcher(Code errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } + + @Override + public boolean matches(Object item) { + if (item instanceof JdbcSqlException) { + JdbcSqlException exception = (JdbcSqlException) item; + if (message == null) { + return exception.getCode().equals(errorCode); + } + return exception.getCode().equals(errorCode) + && exception.getMessage().equals(errorCode.name() + ": " + message); + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText(JdbcSqlException.class.getName() + " with code " + errorCode.name()); + if (message != null) { + description.appendText(" - " + JdbcSqlException.class.getName() + " with message " + message); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java new file mode 100644 index 000000000000..6c9d276e69a8 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -0,0 +1,351 @@ +/* + * Copyright 2019 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.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; +import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +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 io.grpc.Server; +import io.grpc.Status; +import io.grpc.Status.Code; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test that the JDBC driver propagates {@link SQLException}s when a gRPC error occurs. */ +@RunWith(JUnit4.class) +public class JdbcGrpcErrorTest { + private static final Statement SELECT1 = Statement.of("SELECT 1 AS COL1"); + private static final ResultSetMetadata SELECT1_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("COL1") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build(); + private static final com.google.spanner.v1.ResultSet SELECT1_RESULTSET = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .setMetadata(SELECT1_METADATA) + .build(); + private static final Statement UPDATE_STATEMENT = + Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2"); + private static final int UPDATE_COUNT = 1; + private static final Statement INVALID_UPDATE_STATEMENT = + Statement.of("UPDATE NON_EXISING_TABLE SET FOO=1 WHERE BAR=2"); + + private static MockSpannerServiceImpl mockSpanner; + private static MockInstanceAdminImpl mockInstanceAdmin; + private static MockDatabaseAdminImpl mockDatabaseAdmin; + private static Server server; + private static InetSocketAddress address; + + @Rule public ExpectedException expected = ExpectedException.none(); + // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. + private final Exception serverException = + Status.FAILED_PRECONDITION.withDescription("test exception").asRuntimeException(); + private final SpannerJdbcExceptionMatcher testExceptionMatcher = + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, Code.FAILED_PRECONDITION, "test exception"); + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. + mockSpanner.putStatementResult(StatementResult.query(SELECT1, SELECT1_RESULTSET)); + mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT)); + mockSpanner.putStatementResult( + StatementResult.exception( + INVALID_UPDATE_STATEMENT, + Status.NOT_FOUND.withDescription("Unknown table name").asRuntimeException())); + mockInstanceAdmin = new MockInstanceAdminImpl(); + mockDatabaseAdmin = new MockDatabaseAdminImpl(); + address = new InetSocketAddress("localhost", 0); + server = + NettyServerBuilder.forAddress(address) + .addService(mockSpanner) + .addService(mockInstanceAdmin) + .addService(mockDatabaseAdmin) + .build() + .start(); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + @Before + public void reset() { + mockSpanner.removeAllExecutionTimes(); + // Close Spanner pool to prevent reusage of the same Spanner instance (and thereby the same + // session pool). + mockSpanner.reset(); + SpannerPool.closeSpannerPool(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + server.getPort(), "proj", "inst", "db"); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void autocommitBeginTransaction() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setBeginTransactionExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void autocommitBeginPDMLTransaction() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setBeginTransactionExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void transactionalBeginTransaction() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setBeginTransactionExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void readOnlyBeginTransaction() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setBeginTransactionExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.setReadOnly(true); + connection.createStatement().executeQuery(SELECT1.getSql()); + } + } + + @Test + public void autocommitExecuteSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void autocommitPDMLExecuteSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void transactionalExecuteSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void autocommitExecuteBatchDml() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteBatchDmlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.executeBatch(); + } + } + } + + @Test + public void transactionalExecuteBatchDml() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteBatchDmlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.addBatch(UPDATE_STATEMENT.getSql()); + statement.executeBatch(); + } + } + } + + @Test + public void autocommitCommit() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void transactionalCommit() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + connection.commit(); + } + } + + @Test + public void autocommitRollback() throws SQLException { + // The JDBC driver should throw the exception of the SQL statement and ignore any errors from + // the rollback() method. + expected.expect( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, Code.NOT_FOUND, "Unknown table name")); + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeUpdate(INVALID_UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void transactionalRollback() throws SQLException { + // Rollback exceptions are ignored by the client library and not propagated to the JDBC driver. + // This method will therefore not throw any errors. + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + connection.rollback(); + } + } + + @Test + public void autocommitExecuteStreamingSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteStreamingSqlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeQuery(SELECT1.getSql()); + } + } + + @Test + public void transactionalExecuteStreamingSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteStreamingSqlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeQuery(SELECT1.getSql()); + } + } + + @Test + public void readOnlyExecuteStreamingSql() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setExecuteStreamingSqlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.setReadOnly(true); + connection.createStatement().executeQuery(SELECT1.getSql()); + } + } + + @Test + public void autocommitCreateSession() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void transactionalCreateSession() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + } + } + + @Test + public void readOnlyCreateSession() throws SQLException { + expected.expect(testExceptionMatcher); + mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + try (java.sql.Connection connection = createConnection()) { + connection.setAutoCommit(false); + connection.setReadOnly(true); + connection.createStatement().executeQuery(SELECT1.getSql()); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java new file mode 100644 index 000000000000..f0b3fe12848e --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -0,0 +1,637 @@ +/* + * Copyright 2019 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 com.google.cloud.spanner.jdbc.JdbcParameterStore.convertPositionalParametersToNamedParameters; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; + +import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Value; +import com.google.common.io.CharStreams; +import com.google.rpc.Code; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.math.BigDecimal; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcParameterStoreTest { + + /** Tests setting a parameter value together with a sql type */ + @SuppressWarnings("deprecation") + @Test + public void testSetParameterWithType() throws SQLException, IOException { + JdbcParameterStore params = new JdbcParameterStore(); + // test the valid default combinations + params.setParameter(1, true, Types.BOOLEAN); + assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, (byte) 1, Types.TINYINT); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (short) 1, Types.SMALLINT); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1, Types.INTEGER); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1L, Types.BIGINT); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (float) 1, Types.FLOAT); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, (double) 1, Types.DOUBLE); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, new Date(1970 - 1900, 0, 1), Types.DATE); + assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); + params.setParameter(1, new Time(0L), Types.TIME); + assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Timestamp(0L), Types.TIMESTAMP); + assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new byte[] {1, 2, 3}, Types.BINARY); + assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + params.setParameter(1, "test", Types.NVARCHAR); + assertThat((String) params.getParameter(1), is(equalTo("test"))); + verifyParameter(params, Value.string("test")); + + params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), Types.BLOB); + assertThat((JdbcBlob) params.getParameter(1), is(equalTo(new JdbcBlob(new byte[] {1, 2, 3})))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + params.setParameter(1, new ByteArrayInputStream(new byte[] {1, 2, 3}), Types.BLOB); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + + params.setParameter(1, new JdbcClob("test"), Types.CLOB); + assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + verifyParameter(params, Value.string("test")); + params.setParameter(1, new StringReader("test"), Types.CLOB); + assertThat( + stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), + is(true)); + verifyParameter(params, Value.string("test")); + + params.setParameter(1, new JdbcClob("test"), Types.NCLOB); + assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + verifyParameter(params, Value.string("test")); + params.setParameter(1, new StringReader("test"), Types.NCLOB); + assertThat( + stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), + is(true)); + verifyParameter(params, Value.string("test")); + + // test unsupported types + boolean expectedException = false; + try { + params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; + } + } + assertThat(expectedException, is(true)); + + // types that should lead to int64 + for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { + params.setParameter(1, (byte) 1, type); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (short) 1, type); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1, type); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1L, type); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (float) 1, type); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (double) 1, type); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, BigDecimal.ONE, type); + assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + verifyParameter(params, Value.int64(1)); + } + + // types that should lead to float64 + for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) { + params.setParameter(1, (byte) 1, type); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, (short) 1, type); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, 1, type); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, 1L, type); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, (float) 1, type); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, (double) 1, type); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, BigDecimal.ONE, type); + assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + verifyParameter(params, Value.float64(1)); + } + + // types that should lead to date + for (int type : new int[] {Types.DATE}) { + params.setParameter(1, new Date(1970 - 1900, 0, 1), type); + assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); + params.setParameter(1, new Time(0L), type); + assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); + params.setParameter(1, new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0), type); + assertThat( + (Timestamp) params.getParameter(1), + is(equalTo(new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0)))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); + } + + // types that should lead to timestamp + for (int type : new int[] {Types.TIME, Types.TIMESTAMP}) { + params.setParameter(1, new Date(0L), type); + assertThat((Date) params.getParameter(1), is(equalTo(new Date(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Time(0L), type); + assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Timestamp(0L), type); + assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + } + + // types that should lead to bytes (except BLOB which is handled separately) + for (int type : new int[] {Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY}) { + params.setParameter(1, new byte[] {1, 2, 3}, type); + assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + } + + // types that should lead to string + for (int type : + new int[] { + Types.CHAR, + Types.VARCHAR, + Types.LONGVARCHAR, + Types.NCHAR, + Types.NVARCHAR, + Types.LONGNVARCHAR + }) { + params.setParameter(1, "test", type); + assertThat((String) params.getParameter(1), is(equalTo("test"))); + verifyParameter(params, Value.string("test")); + + params.setParameter(1, new StringReader("test"), type); + assertThat( + stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), + is(true)); + verifyParameter(params, Value.string("test")); + + params.setParameter( + 1, new ByteArrayInputStream(StandardCharsets.US_ASCII.encode("test").array()), type); + assertThat( + asciiStreamsEqual( + (ByteArrayInputStream) params.getParameter(1), + new ByteArrayInputStream(StandardCharsets.US_ASCII.encode("test").array())), + is(true)); + verifyParameter(params, Value.string("test")); + + params.setParameter(1, new URL("https://cloud.google.com/spanner"), type); + assertThat( + (URL) params.getParameter(1), is(equalTo(new URL("https://cloud.google.com/spanner")))); + verifyParameter(params, Value.string("https://cloud.google.com/spanner")); + } + + // types that should lead to bool + for (int type : new int[] {Types.BOOLEAN, Types.BIT}) { + params.setParameter(1, true, type); + assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, (byte) 1, type); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, (short) 1, type); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, 1, type); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, 1L, type); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, (float) 1, type); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, (double) 1, type); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, BigDecimal.ONE, type); + assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + verifyParameter(params, Value.bool(true)); + } + } + + /** + * Tests setting a parameter value without knowing the sql type. The type must be deferred from + * the type of the parameter value + */ + @SuppressWarnings("deprecation") + @Test + public void testSetParameterWithoutType() throws SQLException { + JdbcParameterStore params = new JdbcParameterStore(); + params.setParameter(1, (byte) 1, null); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (short) 1, null); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1, null); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, 1L, null); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.int64(1)); + params.setParameter(1, (float) 1, null); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, (double) 1, null); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.float64(1)); + params.setParameter(1, new Date(1970 - 1900, 0, 1), null); + assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); + params.setParameter(1, new Time(0L), null); + assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Timestamp(0L), null); + assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new byte[] {1, 2, 3}, null); + assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + + params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), null); + assertThat((JdbcBlob) params.getParameter(1), is(equalTo(new JdbcBlob(new byte[] {1, 2, 3})))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); + params.setParameter(1, new JdbcClob("test"), null); + assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + verifyParameter(params, Value.string("test")); + params.setParameter(1, true, null); + assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, "test", null); + assertThat((String) params.getParameter(1), is(equalTo("test"))); + verifyParameter(params, Value.string("test")); + params.setParameter(1, new JdbcClob("test"), null); + assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + verifyParameter(params, Value.string("test")); + } + + private boolean stringReadersEqual(StringReader r1, StringReader r2) throws IOException { + boolean res = CharStreams.toString(r1).equals(CharStreams.toString(r2)); + r1.reset(); + r2.reset(); + return res; + } + + private boolean asciiStreamsEqual(InputStream is1, InputStream is2) throws IOException { + InputStreamReader r1 = new InputStreamReader(is1, StandardCharsets.US_ASCII); + String s1 = CharStreams.toString(r1); + InputStreamReader r2 = new InputStreamReader(is2, StandardCharsets.US_ASCII); + String s2 = CharStreams.toString(r2); + is1.reset(); + is2.reset(); + return s1.equals(s2); + } + + /** Tests setting array types of parameters */ + @Test + public void testSetArrayParameter() throws SQLException { + JdbcParameterStore params = new JdbcParameterStore(); + params.setParameter( + 1, JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("BOOL", new Boolean[] {true, false, true})))); + verifyParameter(params, Value.boolArray(new boolean[] {true, false, true})); + + params.setParameter( + 1, JdbcArray.createArray("BOOL", new Boolean[] {true, false, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("BOOL", new Boolean[] {true, false, null})))); + verifyParameter(params, Value.boolArray(Arrays.asList(true, false, null))); + + params.setParameter(1, JdbcArray.createArray("BOOL", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("BOOL", null)))); + verifyParameter(params, Value.boolArray((boolean[]) null)); + + params.setParameter(1, JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L})))); + verifyParameter(params, Value.int64Array(new long[] {1, 2, 3})); + + params.setParameter(1, JdbcArray.createArray("INT64", new Long[] {1L, 2L, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("INT64", new Long[] {1L, 2L, null})))); + verifyParameter(params, Value.int64Array(Arrays.asList(1L, 2L, null))); + + params.setParameter(1, JdbcArray.createArray("INT64", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("INT64", null)))); + verifyParameter(params, Value.int64Array((long[]) null)); + + params.setParameter( + 1, JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, 3D}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, 3D})))); + verifyParameter(params, Value.float64Array(new double[] {1, 2, 3})); + + params.setParameter( + 1, JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, null})))); + verifyParameter(params, Value.float64Array(Arrays.asList(1D, 2D, null))); + + params.setParameter(1, JdbcArray.createArray("FLOAT64", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("FLOAT64", null)))); + verifyParameter(params, Value.float64Array((double[]) null)); + + @SuppressWarnings("deprecation") + Date sqlDate = new Date(2018 - 1900, 12 - 1, 14); + params.setParameter(1, JdbcArray.createArray("DATE", new Date[] {sqlDate}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("DATE", new Date[] {sqlDate})))); + verifyParameter( + params, + Value.dateArray(Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14)))); + + params.setParameter(1, JdbcArray.createArray("DATE", new Date[] {sqlDate, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("DATE", new Date[] {sqlDate, null})))); + verifyParameter( + params, + Value.dateArray(Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14), null))); + + params.setParameter(1, JdbcArray.createArray("DATE", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("DATE", null)))); + verifyParameter(params, Value.dateArray(null)); + + Timestamp sqlTimestamp = new Timestamp(System.currentTimeMillis()); + params.setParameter( + 1, JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp})))); + verifyParameter( + params, Value.timestampArray(Arrays.asList(com.google.cloud.Timestamp.of(sqlTimestamp)))); + + params.setParameter( + 1, JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null})))); + verifyParameter( + params, + Value.timestampArray(Arrays.asList(com.google.cloud.Timestamp.of(sqlTimestamp), null))); + + params.setParameter(1, JdbcArray.createArray("TIMESTAMP", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("TIMESTAMP", null)))); + verifyParameter(params, Value.timestampArray(null)); + + params.setParameter( + 1, JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}})))); + verifyParameter( + params, + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom(new byte[] {1, 2, 3}), + ByteArray.copyFrom(new byte[] {4, 5, 6})))); + + params.setParameter( + 1, JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}, null}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}, null})))); + verifyParameter( + params, + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom(new byte[] {1, 2, 3}), + ByteArray.copyFrom(new byte[] {4, 5, 6}), + null))); + + params.setParameter(1, JdbcArray.createArray("BYTES", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("BYTES", null)))); + verifyParameter(params, Value.bytesArray(null)); + + params.setParameter( + 1, JdbcArray.createArray("STRING", new String[] {"test1", "test2", "test3"}), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is(equalTo(JdbcArray.createArray("STRING", new String[] {"test1", "test2", "test3"})))); + verifyParameter(params, Value.stringArray(Arrays.asList("test1", "test2", "test3"))); + + params.setParameter( + 1, + JdbcArray.createArray("STRING", new String[] {"test1", null, "test2", "test3"}), + Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), + is( + equalTo( + JdbcArray.createArray("STRING", new String[] {"test1", null, "test2", "test3"})))); + verifyParameter(params, Value.stringArray(Arrays.asList("test1", null, "test2", "test3"))); + + params.setParameter(1, JdbcArray.createArray("STRING", null), Types.ARRAY); + assertThat( + (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("STRING", null)))); + verifyParameter(params, Value.stringArray(null)); + } + + private void verifyParameter(JdbcParameterStore params, Value value) throws SQLException { + Statement.Builder builder = Statement.newBuilder("SELECT * FROM FOO WHERE BAR=:p1"); + params.bindParameterValue(builder.bind("p1"), 1); + assertThat(builder.build().getParameters().get("p1"), is(equalTo(value))); + } + + @Test + public void testConvertPositionalParametersToNamedParameters() throws SQLException { + assertThat( + convertPositionalParametersToNamedParameters("select * from foo where name=?") + .sqlWithNamedParameters, + is(equalTo("select * from foo where name=@p1"))); + assertThat( + convertPositionalParametersToNamedParameters("?'?test?\"?test?\"?'?") + .sqlWithNamedParameters, + is(equalTo("@p1'?test?\"?test?\"?'@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?'?it\\'?s'?").sqlWithNamedParameters, + is(equalTo("@p1'?it\\'?s'@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?'?it\\\"?s'?").sqlWithNamedParameters, + is(equalTo("@p1'?it\\\"?s'@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?\"?it\\\"?s\"?").sqlWithNamedParameters, + is(equalTo("@p1\"?it\\\"?s\"@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?`?it\\`?s`?").sqlWithNamedParameters, + is(equalTo("@p1`?it\\`?s`@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?'''?it\\'?s'''?").sqlWithNamedParameters, + is(equalTo("@p1'''?it\\'?s'''@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?\"\"\"?it\\\"?s\"\"\"?") + .sqlWithNamedParameters, + is(equalTo("@p1\"\"\"?it\\\"?s\"\"\"@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?```?it\\`?s```?").sqlWithNamedParameters, + is(equalTo("@p1```?it\\`?s```@p2"))); + assertThat( + convertPositionalParametersToNamedParameters("?'''?it\\'?s \n ?it\\'?s'''?") + .sqlWithNamedParameters, + is(equalTo("@p1'''?it\\'?s \n ?it\\'?s'''@p2"))); + + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); + assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); + + assertThat( + convertPositionalParametersToNamedParameters( + "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") + .sqlWithNamedParameters, + is( + equalTo( + "select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'"))); + + assertThat( + convertPositionalParametersToNamedParameters( + "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where name=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3"))); + assertThat( + convertPositionalParametersToNamedParameters( + "select * " + "from foo " + "where id between ? and ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "where id between @p1 and @p2"))); + assertThat( + convertPositionalParametersToNamedParameters("select * " + "from foo " + "limit ? offset ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "limit @p1 offset @p2"))); + assertThat( + convertPositionalParametersToNamedParameters( + "select * " + + "from foo " + + "where col1=? " + + "and col2 like ? " + + "and col3 > ? " + + "and col4 < ? " + + "and col5 != ? " + + "and col6 not in (?, ?, ?) " + + "and col7 in (?, ?, ?) " + + "and col8 between ? and ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where col1=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3 " + + "and col4 < @p4 " + + "and col5 != @p5 " + + "and col6 not in (@p6, @p7, @p8) " + + "and col7 in (@p9, @p10, @p11) " + + "and col8 between @p12 and @p13"))); + } + + private void assertUnclosedLiteral(String sql) { + boolean exception = false; + try { + convertPositionalParametersToNamedParameters(sql); + } catch (SQLException t) { + assertThat(t instanceof JdbcSqlException, is(true)); + JdbcSqlException e = (JdbcSqlException) t; + assertThat(e.getCode(), is(Code.INVALID_ARGUMENT)); + assertThat( + e.getMessage(), + startsWith( + Code.INVALID_ARGUMENT.name() + + ": SQL statement contains an unclosed literal: " + + sql)); + exception = true; + } + assertThat(exception, is(true)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java new file mode 100644 index 000000000000..bbfded162f67 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -0,0 +1,325 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.rpc.Code; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Arrays; +import java.util.Calendar; +import java.util.TimeZone; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcPreparedStatementTest { + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private String generateSqlWithParameters(int numberOfParams) { + StringBuilder sql = new StringBuilder("INSERT INTO FOO ("); + boolean first = true; + for (int i = 0; i < numberOfParams; i++) { + if (first) { + first = false; + } else { + sql.append(", "); + } + sql.append("COL").append(i); + } + sql.append(") VALUES ("); + first = true; + for (int i = 0; i < numberOfParams; i++) { + if (first) { + first = false; + } else { + sql.append(", "); + } + sql.append("?"); + } + sql.append(")"); + return sql.toString(); + } + + private JdbcConnection createMockConnection() throws SQLException { + return createMockConnection(mock(Connection.class)); + } + + private JdbcConnection createMockConnection(Connection spanner) throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getSpannerConnection()).thenReturn(spanner); + when(connection.createBlob()).thenCallRealMethod(); + when(connection.createClob()).thenCallRealMethod(); + when(connection.createNClob()).thenCallRealMethod(); + when(connection.createArrayOf(anyString(), any(Object[].class))).thenCallRealMethod(); + + return connection; + } + + @Test + public void testParameters() throws SQLException, MalformedURLException { + final int numberOfParams = 48; + String sql = generateSqlWithParameters(numberOfParams); + + JdbcConnection connection = createMockConnection(); + try (JdbcPreparedStatement ps = new JdbcPreparedStatement(connection, sql)) { + 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); + ps.setAsciiStream(4, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setBinaryStream(6, new ByteArrayInputStream("TEST".getBytes())); + ps.setBinaryStream(7, new ByteArrayInputStream("TEST".getBytes()), 4); + ps.setBinaryStream(8, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setBlob(9, connection.createBlob()); + ps.setBlob(10, new ByteArrayInputStream("TEST".getBytes())); + ps.setBlob(11, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setBoolean(12, Boolean.TRUE); + ps.setByte(13, (byte) 1); + ps.setBytes(14, "TEST".getBytes()); + ps.setCharacterStream(15, new StringReader("TEST")); + ps.setCharacterStream(16, new StringReader("TEST"), 4); + ps.setCharacterStream(17, new StringReader("TEST"), 4l); + ps.setClob(18, connection.createClob()); + ps.setClob(19, new StringReader("TEST")); + ps.setClob(20, new StringReader("TEST"), 4l); + ps.setDate(21, new Date(1000l)); + ps.setDate(22, new Date(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setDouble(23, 1d); + ps.setFloat(24, 1f); + ps.setInt(25, 1); + ps.setLong(26, 1l); + ps.setNCharacterStream(27, new StringReader("TEST")); + ps.setNCharacterStream(28, new StringReader("TEST"), 4l); + ps.setNClob(29, connection.createNClob()); + ps.setNClob(30, new StringReader("TEST")); + ps.setNClob(31, new StringReader("TEST"), 4l); + ps.setNString(32, "TEST"); + ps.setNull(33, Types.BIGINT); + ps.setNull(34, Types.BIGINT, "INT64"); + ps.setObject(35, "TEST"); + ps.setObject(36, "TEST", Types.NVARCHAR); + ps.setObject(37, "TEST", Types.NVARCHAR, 20); + ps.setShort(40, (short) 1); + ps.setString(42, "TEST"); + ps.setTime(43, new Time(1000l)); + ps.setTime(44, new Time(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setTimestamp(45, new Timestamp(1000l)); + ps.setTimestamp(46, new Timestamp(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setUnicodeStream(47, new ByteArrayInputStream("TEST".getBytes()), 4); + ps.setURL(48, new URL("https://spanner.google.com")); + + testSetUnsupportedTypes(ps); + + JdbcParameterMetaData pmd = ps.getParameterMetaData(); + Assert.assertEquals(numberOfParams, pmd.getParameterCount()); + Assert.assertEquals(JdbcArray.class.getName(), pmd.getParameterClassName(1)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(2)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(3)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(4)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(6)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(7)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(8)); + Assert.assertEquals(JdbcBlob.class.getName(), pmd.getParameterClassName(9)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(10)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(11)); + Assert.assertEquals(Boolean.class.getName(), pmd.getParameterClassName(12)); + Assert.assertEquals(Byte.class.getName(), pmd.getParameterClassName(13)); + Assert.assertEquals(byte[].class.getName(), pmd.getParameterClassName(14)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(15)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(16)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(17)); + Assert.assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(18)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(19)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(20)); + Assert.assertEquals(Date.class.getName(), pmd.getParameterClassName(21)); + Assert.assertEquals(Date.class.getName(), pmd.getParameterClassName(22)); + Assert.assertEquals(Double.class.getName(), pmd.getParameterClassName(23)); + Assert.assertEquals(Float.class.getName(), pmd.getParameterClassName(24)); + Assert.assertEquals(Integer.class.getName(), pmd.getParameterClassName(25)); + Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(26)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(27)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(28)); + Assert.assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(29)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(30)); + Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(31)); + Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(32)); + Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(33)); + Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(34)); + Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(35)); + Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(36)); + Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(37)); + Assert.assertNull(pmd.getParameterClassName(38)); + Assert.assertNull(pmd.getParameterClassName(39)); + Assert.assertEquals(Short.class.getName(), pmd.getParameterClassName(40)); + Assert.assertNull(pmd.getParameterClassName(41)); + Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(42)); + Assert.assertEquals(Time.class.getName(), pmd.getParameterClassName(43)); + Assert.assertEquals(Time.class.getName(), pmd.getParameterClassName(44)); + Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(45)); + Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(46)); + Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(47)); + Assert.assertEquals(URL.class.getName(), pmd.getParameterClassName(48)); + + ps.clearParameters(); + pmd = ps.getParameterMetaData(); + Assert.assertEquals(numberOfParams, pmd.getParameterCount()); + } + } + + private void testSetUnsupportedTypes(PreparedStatement ps) { + // TODO: Rewrite these tests using functional interfaces when Java8 is available. + boolean expectedException = false; + try { + ps.setBigDecimal(5, BigDecimal.valueOf(1l)); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; + } + } + assertThat(expectedException, is(true)); + expectedException = false; + try { + ps.setRef(38, (Ref) null); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; + } + } + assertThat(expectedException, is(true)); + expectedException = false; + try { + ps.setRowId(39, (RowId) null); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; + } + } + assertThat(expectedException, is(true)); + expectedException = false; + try { + ps.setSQLXML(41, (SQLXML) null); + } catch (SQLException e) { + if (e instanceof JdbcSqlException) { + expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; + } + } + assertThat(expectedException, is(true)); + } + + @Test + public void testSetNullValues() throws SQLException { + String sql = generateSqlWithParameters(27); + try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(), sql)) { + ps.setNull(1, Types.BLOB); + ps.setNull(2, Types.NVARCHAR); + ps.setNull(4, Types.BINARY); + ps.setNull(5, Types.BOOLEAN); + ps.setNull(6, Types.TINYINT); + ps.setNull(7, Types.DATE); + ps.setNull(8, Types.DOUBLE); + ps.setNull(9, Types.FLOAT); + ps.setNull(10, Types.INTEGER); + ps.setNull(11, Types.BIGINT); + ps.setNull(12, Types.SMALLINT); + ps.setNull(13, Types.TIME); + ps.setNull(14, Types.TIMESTAMP); + ps.setNull(15, Types.CHAR); + ps.setNull(16, Types.CLOB); + ps.setNull(17, Types.LONGNVARCHAR); + ps.setNull(18, Types.LONGVARBINARY); + ps.setNull(19, Types.LONGVARCHAR); + ps.setNull(20, Types.NCHAR); + ps.setNull(21, Types.NCLOB); + ps.setNull(23, Types.NVARCHAR); + ps.setNull(24, Types.REAL); + ps.setNull(25, Types.BIT); + ps.setNull(26, Types.VARBINARY); + ps.setNull(27, Types.VARCHAR); + + JdbcParameterMetaData pmd = ps.getParameterMetaData(); + Assert.assertEquals(27, pmd.getParameterCount()); + Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(14)); + + ps.clearParameters(); + pmd = ps.getParameterMetaData(); + Assert.assertEquals(27, pmd.getParameterCount()); + } + } + + @Test + public void testGetResultSetMetadata() throws SQLException { + final String sql = "SELECT * FROM FOO"; + Connection connection = mock(Connection.class); + ResultSet rs = + ResultSets.forRows( + Type.struct( + StructField.of("ID", Type.int64()), + StructField.of("NAME", Type.string()), + StructField.of("AMOUNT", Type.float64())), + Arrays.asList( + Struct.newBuilder() + .set("ID") + .to(1L) + .set("NAME") + .to("foo") + .set("AMOUNT") + .to(Math.PI) + .build())); + when(connection.executeQuery(Statement.of(sql))).thenReturn(rs); + try (JdbcPreparedStatement ps = + new JdbcPreparedStatement(createMockConnection(connection), sql)) { + ResultSetMetaData metadata = ps.getMetaData(); + assertThat(metadata.getColumnCount(), is(equalTo(3))); + assertThat(metadata.getColumnLabel(1), is(equalTo("ID"))); + assertThat(metadata.getColumnLabel(2), is(equalTo("NAME"))); + assertThat(metadata.getColumnLabel(3), is(equalTo("AMOUNT"))); + assertThat(metadata.getColumnType(1), is(equalTo(Types.BIGINT))); + assertThat(metadata.getColumnType(2), is(equalTo(Types.NVARCHAR))); + assertThat(metadata.getColumnType(3), is(equalTo(Types.DOUBLE))); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java new file mode 100644 index 000000000000..e97382d0a0b4 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -0,0 +1,483 @@ +/* + * Copyright 2019 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.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.ByteArray; +import com.google.cloud.spanner.ResultSet; +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.Type.StructField; +import com.google.cloud.spanner.Value; +import com.google.common.base.Preconditions; +import java.sql.Date; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.internal.stubbing.answers.Returns; + +@RunWith(JUnit4.class) +public class JdbcResultSetMetaDataTest { + private JdbcResultSetMetaData subject; + private java.sql.Connection connection; + + private static class TestColumn { + private final Type type; + private final String name; + private final int defaultSize; + private final boolean calculated; + + private TestColumn(Type type, String name, Integer nulls, int size, boolean calculated) { + Preconditions.checkNotNull(type); + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(nulls); + this.type = type; + this.name = name; + this.defaultSize = getDefaultSize(type); + this.calculated = calculated; + } + + private static int getDefaultSize(Type type) { + if (type == Type.bool()) return 1; + if (type == Type.date()) return 10; + if (type == Type.float64()) return 14; + if (type == Type.int64()) return 10; + if (type == Type.timestamp()) return 24; + if (type == Type.string()) return 50; + if (type == Type.bytes()) return 50; + return 50; + } + + private boolean isTableColumn() { + return !calculated; + } + + private static class Builder { + private Type type; + private String name; + private Integer nulls; + private int size = 0; + private boolean calculated = false; + + public static Builder getBuilder() { + return new Builder(); + } + + private TestColumn build() { + return new TestColumn(type, name, nulls, size, calculated); + } + + private Builder withType(Type type) { + this.type = type; + return this; + } + + private Builder withName(String name) { + this.name = name; + return this; + } + + private Builder withNotNull() { + this.nulls = ResultSetMetaData.columnNoNulls; + return this; + } + + private Builder withNullable() { + this.nulls = ResultSetMetaData.columnNullable; + return this; + } + + private Builder withNullableUnknown() { + this.nulls = ResultSetMetaData.columnNullableUnknown; + return this; + } + + private Builder withSize(int size) { + this.size = size; + return this; + } + + private Builder withCalculated(boolean calculated) { + this.calculated = calculated; + return this; + } + } + } + + private static final List TEST_COLUMNS = createTestColumns(); + + @Before + public void setup() throws SQLException { + connection = mock(java.sql.Connection.class); + Statement statement = mock(Statement.class); + JdbcResultSet resultSet = getFooTestResultSet(statement); + when(connection.getSchema()).thenReturn(""); + when(connection.getCatalog()).thenReturn("test-database"); + when(statement.getConnection()).then(new Returns(connection)); + + subject = resultSet.getMetaData(); + } + + private static List createTestColumns() { + List res = new ArrayList<>(); + int index = 1; + for (Type type : getAllTypes()) { + TestColumn.Builder builder = TestColumn.Builder.getBuilder(); + builder.withName("COL" + index).withType(type).withSize(getDefaultSize(type)); + if (index % 2 == 1) builder.withNotNull(); + else builder.withNullable(); + res.add(builder.build()); + index++; + } + TestColumn.Builder builder = TestColumn.Builder.getBuilder(); + builder + .withName("CALCULATED") + .withType(Type.int64()) + .withNullableUnknown() + .withCalculated(true); + res.add(builder.build()); + return res; + } + + private static int getDefaultSize(Type type) { + if (type == Type.string()) return 100; + return 0; + } + + private static List getAllTypes() { + List types = new ArrayList<>(); + types.add(Type.bool()); + types.add(Type.bytes()); + types.add(Type.date()); + types.add(Type.float64()); + types.add(Type.int64()); + types.add(Type.string()); + types.add(Type.timestamp()); + List arrayTypes = new ArrayList<>(); + for (Type type : types) { + arrayTypes.add(Type.array(type)); + } + types.addAll(arrayTypes); + + return types; + } + + private JdbcResultSet getFooTestResultSet(Statement statement) throws SQLException { + List rows = new ArrayList<>(4); + for (int row = 1; row <= 4; row++) { + Struct.Builder builder = Struct.newBuilder(); + for (TestColumn col : TEST_COLUMNS) { + builder.set(col.name).to(getDefaultValue(col.type, row)); + } + rows.add(builder.build()); + } + StructField[] fields = new StructField[TEST_COLUMNS.size()]; + int index = 0; + for (TestColumn col : TEST_COLUMNS) { + fields[index] = StructField.of(col.name, col.type); + index++; + } + + ResultSet rs = ResultSets.forRows(Type.struct(fields), rows); + return JdbcResultSet.of(statement, rs); + } + + private Value getDefaultValue(Type type, int row) { + if (type == Type.bool()) return Value.bool(Boolean.TRUE); + if (type == Type.bytes()) return Value.bytes(ByteArray.copyFrom("test byte array " + row)); + if (type == Type.date()) return Value.date(com.google.cloud.Date.fromYearMonthDay(2018, 4, 1)); + if (type == Type.float64()) return Value.float64(123.45D); + if (type == Type.int64()) return Value.int64(12345L); + if (type == Type.string()) return Value.string("test value " + row); + if (type == Type.timestamp()) return Value.timestamp(com.google.cloud.Timestamp.now()); + + if (type.getCode() == Code.ARRAY) { + if (type.getArrayElementType() == Type.bool()) + return Value.boolArray(Arrays.asList(Boolean.TRUE, Boolean.FALSE)); + if (type.getArrayElementType() == Type.bytes()) + return Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("test byte array " + row), + ByteArray.copyFrom("test byte array " + row))); + if (type.getArrayElementType() == Type.date()) + return Value.dateArray( + Arrays.asList( + com.google.cloud.Date.fromYearMonthDay(2018, 4, 1), + com.google.cloud.Date.fromYearMonthDay(2018, 4, 2))); + if (type.getArrayElementType() == Type.float64()) + return Value.float64Array(Arrays.asList(123.45D, 543.21D)); + if (type.getArrayElementType() == Type.int64()) + return Value.int64Array(Arrays.asList(12345L, 54321L)); + if (type.getArrayElementType() == Type.string()) + return Value.stringArray(Arrays.asList("test value " + row, "test value " + row)); + if (type.getArrayElementType() == Type.timestamp()) + return Value.timestampArray( + Arrays.asList(com.google.cloud.Timestamp.now(), com.google.cloud.Timestamp.now())); + } + return null; + } + + @Test + public void testGetColumnCount() throws SQLException { + assertEquals(TEST_COLUMNS.size(), subject.getColumnCount()); + } + + @Test + public void testIsAutoIncrement() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(false, subject.isAutoIncrement(i)); + } + } + + @Test + public void testIsCaseSensitive() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + Type type = TEST_COLUMNS.get(i - 1).type; + assertEquals(type == Type.string() || type == Type.bytes(), subject.isCaseSensitive(i)); + } + } + + @Test + public void testIsSearchable() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(true, subject.isSearchable(i)); + } + } + + @Test + public void testIsCurrency() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(false, subject.isCurrency(i)); + } + } + + @Test + public void testIsNullable() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(ResultSetMetaData.columnNullableUnknown, subject.isNullable(i)); + } + } + + @Test + public void testIsSigned() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + Type type = TEST_COLUMNS.get(i - 1).type; + if (type == Type.int64() || type == Type.float64()) { + assertTrue(subject.isSigned(i)); + } else { + assertFalse(subject.isSigned(i)); + } + } + } + + @Test + public void testGetColumnDisplaySize() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals( + getDefaultDisplaySize(TEST_COLUMNS.get(i - 1).type, i), subject.getColumnDisplaySize(i)); + } + } + + private int getDefaultDisplaySize(Type type, int column) throws SQLException { + if (type.getCode() == Code.ARRAY) return 50; + if (type == Type.bool()) return 5; + if (type == Type.bytes()) return 50; + if (type == Type.date()) return 10; + if (type == Type.float64()) return 14; + if (type == Type.int64()) return 10; + if (type == Type.string()) { + int length = subject.getPrecision(column); + return length == 0 ? 50 : length; + } + if (type == Type.timestamp()) return 16; + return 10; + } + + @Test + public void testGetColumnLabel() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(TEST_COLUMNS.get(i - 1).name, subject.getColumnLabel(i)); + } + } + + @Test + public void testGetColumnName() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(TEST_COLUMNS.get(i - 1).name, subject.getColumnName(i)); + } + } + + @Test + public void testGetSchemaName() throws SQLException { + assertEquals("", subject.getSchemaName(1)); + } + + @Test + public void testGetPrecision() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(getPrecision(TEST_COLUMNS.get(i - 1)), subject.getPrecision(i)); + } + } + + private int getPrecision(TestColumn col) { + if (col.type == Type.bool()) return 1; + if (col.type == Type.date()) return 10; + if (col.type == Type.float64()) return 14; + if (col.type == Type.int64()) return 10; + if (col.type == Type.timestamp()) return 24; + if (col.isTableColumn()) return col.defaultSize; + return 50; + } + + @Test + public void testGetScale() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(getScale(TEST_COLUMNS.get(i - 1)), subject.getScale(i)); + } + } + + private int getScale(TestColumn col) { + if (col.type == Type.float64()) return 15; + return 0; + } + + @Test + public void testGetTableName() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals("", subject.getTableName(i)); + } + } + + @Test + public void testGetCatalogName() throws SQLException { + assertEquals("test-database", subject.getCatalogName(1)); + } + + @Test + public void testGetColumnType() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(getSqlType(TEST_COLUMNS.get(i - 1).type), subject.getColumnType(i)); + } + } + + private int getSqlType(Type type) { + if (type == Type.bool()) return Types.BOOLEAN; + if (type == Type.bytes()) return Types.BINARY; + if (type == Type.date()) return Types.DATE; + if (type == Type.float64()) return Types.DOUBLE; + if (type == Type.int64()) return Types.BIGINT; + if (type == Type.string()) return Types.NVARCHAR; + if (type == Type.timestamp()) return Types.TIMESTAMP; + if (type.getCode() == Code.ARRAY) return Types.ARRAY; + return Types.OTHER; + } + + @Test + public void getColumnTypeName() throws SQLException { + int index = 1; + for (TestColumn col : TEST_COLUMNS) { + assertEquals(col.type.getCode().name(), subject.getColumnTypeName(index)); + index++; + } + } + + @Test + public void testIsReadOnly() throws SQLException { + for (int i = 0; i < TEST_COLUMNS.size(); i++) { + assertFalse(subject.isReadOnly(i)); + } + } + + @Test + public void testIsWritable() throws SQLException { + for (int i = 0; i < TEST_COLUMNS.size(); i++) { + assertTrue(subject.isWritable(i)); + } + } + + @Test + public void testIsDefinitelyWritable() throws SQLException { + for (int i = 0; i < TEST_COLUMNS.size(); i++) { + assertFalse(subject.isDefinitelyWritable(i)); + } + } + + @Test + public void testGetColumnClassName() throws SQLException { + for (int i = 1; i <= TEST_COLUMNS.size(); i++) { + assertEquals(getTypeClassName(TEST_COLUMNS.get(i - 1).type), subject.getColumnClassName(i)); + } + } + + private String getTypeClassName(Type type) { + if (type == Type.bool()) return Boolean.class.getName(); + if (type == Type.bytes()) return byte[].class.getName(); + if (type == Type.date()) return Date.class.getName(); + if (type == Type.float64()) return Double.class.getName(); + if (type == Type.int64()) return Long.class.getName(); + if (type == Type.string()) return String.class.getName(); + if (type == Type.timestamp()) return Timestamp.class.getName(); + if (type.getCode() == Code.ARRAY) { + if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); + if (type.getArrayElementType() == Type.bytes()) return byte[][].class.getName(); + if (type.getArrayElementType() == Type.date()) return Date[].class.getName(); + if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); + if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); + if (type.getArrayElementType() == Type.string()) return String[].class.getName(); + if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); + } + return null; + } + + private static final String EXPECTED_TO_STRING = + "Col 1: COL1 BOOL\n" + + "Col 2: COL2 BYTES\n" + + "Col 3: COL3 DATE\n" + + "Col 4: COL4 FLOAT64\n" + + "Col 5: COL5 INT64\n" + + "Col 6: COL6 STRING\n" + + "Col 7: COL7 TIMESTAMP\n" + + "Col 8: COL8 ARRAY\n" + + "Col 9: COL9 ARRAY\n" + + "Col 10: COL10 ARRAY\n" + + "Col 11: COL11 ARRAY\n" + + "Col 12: COL12 ARRAY\n" + + "Col 13: COL13 ARRAY\n" + + "Col 14: COL14 ARRAY\n" + + "Col 15: CALCULATED INT64\n"; + + @Test + public void testToString() { + assertEquals(subject.toString(), EXPECTED_TO_STRING); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java new file mode 100644 index 000000000000..dbe75a86437c --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -0,0 +1,1141 @@ +/* + * Copyright 2019 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.assertArrayEquals; +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.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.ByteArray; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Time; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.internal.stubbing.answers.Returns; + +@RunWith(JUnit4.class) +public class JdbcResultSetTest { + private static final String UNKNOWN_COLUMN = "UNKNOWN_COLUMN"; + private static final String STRING_COL_NULL = "STRING_COL_NULL"; + private static final String STRING_COL_NOT_NULL = "STRING_COL_NOT_NULL"; + private static final String STRING_VALUE = "FOO"; + private static final int STRING_COLINDEX_NULL = 1; + private static final int STRING_COLINDEX_NOTNULL = 2; + private static final String BOOLEAN_COL_NULL = "BOOLEAN_COL_NULL"; + private static final String BOOLEAN_COL_NOT_NULL = "BOOLEAN_COL_NOT_NULL"; + private static final boolean BOOLEAN_VALUE = true; + private static final int BOOLEAN_COLINDEX_NULL = 3; + private static final int BOOLEAN_COLINDEX_NOTNULL = 4; + private static final String DOUBLE_COL_NULL = "DOUBLE_COL_NULL"; + private static final String DOUBLE_COL_NOT_NULL = "DOUBLE_COL_NOT_NULL"; + private static final double DOUBLE_VALUE = 3.14159265359D; + private static final int DOUBLE_COLINDEX_NULL = 5; + private static final int DOUBLE_COLINDEX_NOTNULL = 6; + private static final String BYTES_COL_NULL = "BYTES_COL_NULL"; + private static final String BYTES_COL_NOT_NULL = "BYTES_COL_NOT_NULL"; + private static final ByteArray BYTES_VALUE = ByteArray.copyFrom("FOO"); + private static final int BYTES_COLINDEX_NULL = 7; + private static final int BYTES_COLINDEX_NOTNULL = 8; + private static final String LONG_COL_NULL = "LONG_COL_NULL"; + private static final String LONG_COL_NOT_NULL = "LONG_COL_NOT_NULL"; + private static final long LONG_VALUE = 1L; + private static final int LONG_COLINDEX_NULL = 9; + private static final int LONG_COLINDEX_NOTNULL = 10; + private static final String DATE_COL_NULL = "DATE_COL_NULL"; + private static final String DATE_COL_NOT_NULL = "DATE_COL_NOT_NULL"; + private static final Date DATE_VALUE = Date.fromYearMonthDay(2019, 1, 18); + private static final int DATE_COLINDEX_NULL = 11; + private static final int DATE_COLINDEX_NOTNULL = 12; + private static final String TIMESTAMP_COL_NULL = "TIMESTAMP_COL_NULL"; + private static final String TIMESTAMP_COL_NOT_NULL = "TIMESTAMP_COL_NOT_NULL"; + private static final Timestamp TIMESTAMP_VALUE = + Timestamp.parseTimestamp("2019-01-18T10:00:01.1213Z"); + private static final int TIMESTAMP_COLINDEX_NULL = 13; + private static final int TIMESTAMP_COLINDEX_NOTNULL = 14; + private static final String TIME_COL_NULL = "TIME_COL_NULL"; + private static final String TIME_COL_NOT_NULL = "TIME_COL_NOT_NULL"; + private static final Timestamp TIME_VALUE = Timestamp.parseTimestamp("1970-01-01T10:01:02.995Z"); + private static final int TIME_COLINDEX_NULL = 15; + private static final int TIME_COLINDEX_NOTNULL = 16; + private static final String ARRAY_COL_NULL = "ARRAY_COL_NULL"; + private static final String ARRAY_COL_NOT_NULL = "ARRAY_COL_NOT_NULL"; + private static final long[] ARRAY_VALUE = new long[] {1L, 2L, 3L}; + private static final int ARRAY_COLINDEX_NULL = 17; + private static final int ARRAY_COLINDEX_NOTNULL = 18; + private static final String URL_COL_NULL = "URL_COL_NULL"; + private static final String URL_COL_NOT_NULL = "URL_COL_NOT_NULL"; + private static final String URL_VALUE = "https://cloud.google.com/spanner/docs/apis"; + private static final int URL_COLINDEX_NULL = 19; + private static final int URL_COLINDEX_NOTNULL = 20; + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private JdbcResultSet subject; + + private static ResultSet getMockResultSet() { + + return ResultSets.forRows( + Type.struct( + StructField.of(STRING_COL_NULL, Type.string()), + StructField.of(STRING_COL_NOT_NULL, Type.string()), + StructField.of(BOOLEAN_COL_NULL, Type.bool()), + StructField.of(BOOLEAN_COL_NOT_NULL, Type.bool()), + StructField.of(DOUBLE_COL_NULL, Type.float64()), + StructField.of(DOUBLE_COL_NOT_NULL, Type.float64()), + StructField.of(BYTES_COL_NULL, Type.bytes()), + StructField.of(BYTES_COL_NOT_NULL, Type.bytes()), + StructField.of(LONG_COL_NULL, Type.int64()), + StructField.of(LONG_COL_NOT_NULL, Type.int64()), + StructField.of(DATE_COL_NULL, Type.date()), + StructField.of(DATE_COL_NOT_NULL, Type.date()), + StructField.of(TIMESTAMP_COL_NULL, Type.timestamp()), + StructField.of(TIMESTAMP_COL_NOT_NULL, Type.timestamp()), + StructField.of(TIME_COL_NULL, Type.timestamp()), + StructField.of(TIME_COL_NOT_NULL, Type.timestamp()), + StructField.of(ARRAY_COL_NULL, Type.array(Type.int64())), + StructField.of(ARRAY_COL_NOT_NULL, Type.array(Type.int64())), + StructField.of(URL_COL_NULL, Type.string()), + StructField.of(URL_COL_NOT_NULL, Type.string())), + Arrays.asList( + Struct.newBuilder() + .set(STRING_COL_NULL) + .to((String) null) + .set(STRING_COL_NOT_NULL) + .to(STRING_VALUE) + .set(BOOLEAN_COL_NULL) + .to((Boolean) null) + .set(BOOLEAN_COL_NOT_NULL) + .to(BOOLEAN_VALUE) + .set(DOUBLE_COL_NULL) + .to((Double) null) + .set(DOUBLE_COL_NOT_NULL) + .to(DOUBLE_VALUE) + .set(BYTES_COL_NULL) + .to((ByteArray) null) + .set(BYTES_COL_NOT_NULL) + .to(BYTES_VALUE) + .set(LONG_COL_NULL) + .to((Long) null) + .set(LONG_COL_NOT_NULL) + .to(LONG_VALUE) + .set(DATE_COL_NULL) + .to((Date) null) + .set(DATE_COL_NOT_NULL) + .to(DATE_VALUE) + .set(TIMESTAMP_COL_NULL) + .to((Timestamp) null) + .set(TIMESTAMP_COL_NOT_NULL) + .to(TIMESTAMP_VALUE) + .set(TIME_COL_NULL) + .to((Timestamp) null) + .set(TIME_COL_NOT_NULL) + .to(TIME_VALUE) + .set(ARRAY_COL_NULL) + .toInt64Array((long[]) null) + .set(ARRAY_COL_NOT_NULL) + .toInt64Array(ARRAY_VALUE) + .set(URL_COL_NULL) + .to((String) null) + .set(URL_COL_NOT_NULL) + .to(URL_VALUE) + .build())); + } + + static ResultSet getMockResultSet_old() { + ResultSet res = mock(ResultSet.class); + when(res.getString(STRING_COL_NULL)).thenReturn(null); + when(res.isNull(STRING_COL_NULL)).thenReturn(true); + when(res.getString(STRING_COL_NOT_NULL)).thenReturn("FOO"); + when(res.isNull(STRING_COL_NOT_NULL)).thenReturn(false); + when(res.getString(STRING_COLINDEX_NULL - 1)).thenReturn(null); + when(res.isNull(STRING_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getString(STRING_COLINDEX_NOTNULL - 1)).thenReturn("BAR"); + when(res.isNull(STRING_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(STRING_COL_NULL)).thenReturn(Type.string()); + when(res.getColumnType(STRING_COL_NOT_NULL)).thenReturn(Type.string()); + when(res.getColumnType(STRING_COLINDEX_NULL - 1)).thenReturn(Type.string()); + when(res.getColumnType(STRING_COLINDEX_NOTNULL - 1)).thenReturn(Type.string()); + + when(res.getString(URL_COL_NULL)).thenReturn(null); + when(res.isNull(URL_COL_NULL)).thenReturn(true); + when(res.getString(URL_COL_NOT_NULL)).thenReturn("https://github.com/"); + when(res.isNull(URL_COL_NOT_NULL)).thenReturn(false); + when(res.getString(URL_COLINDEX_NULL - 1)).thenReturn(null); + when(res.isNull(URL_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getString(URL_COLINDEX_NOTNULL - 1)).thenReturn("https://github.com/"); + when(res.isNull(URL_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(URL_COL_NULL)).thenReturn(Type.string()); + when(res.getColumnType(URL_COL_NOT_NULL)).thenReturn(Type.string()); + when(res.getColumnType(URL_COLINDEX_NULL - 1)).thenReturn(Type.string()); + when(res.getColumnType(URL_COLINDEX_NOTNULL - 1)).thenReturn(Type.string()); + + when(res.getBoolean(BOOLEAN_COL_NULL)).thenReturn(false); + when(res.isNull(BOOLEAN_COL_NULL)).thenReturn(true); + when(res.getBoolean(BOOLEAN_COL_NOT_NULL)).thenReturn(true); + when(res.isNull(BOOLEAN_COL_NOT_NULL)).thenReturn(false); + when(res.getBoolean(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(false); + when(res.isNull(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getBoolean(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.isNull(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(BOOLEAN_COL_NULL)).thenReturn(Type.bool()); + when(res.getColumnType(BOOLEAN_COL_NOT_NULL)).thenReturn(Type.bool()); + when(res.getColumnType(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(Type.bool()); + when(res.getColumnType(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(Type.bool()); + + when(res.getDouble(DOUBLE_COL_NULL)).thenReturn(0d); + when(res.isNull(DOUBLE_COL_NULL)).thenReturn(true); + when(res.getDouble(DOUBLE_COL_NOT_NULL)).thenReturn(1.123456789d); + when(res.isNull(DOUBLE_COL_NOT_NULL)).thenReturn(false); + when(res.getDouble(DOUBLE_COLINDEX_NULL - 1)).thenReturn(0d); + when(res.isNull(DOUBLE_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getDouble(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(2.123456789d); + when(res.isNull(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(DOUBLE_COL_NULL)).thenReturn(Type.float64()); + when(res.getColumnType(DOUBLE_COL_NOT_NULL)).thenReturn(Type.float64()); + when(res.getColumnType(DOUBLE_COLINDEX_NULL - 1)).thenReturn(Type.float64()); + when(res.getColumnType(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(Type.float64()); + + when(res.getString(BYTES_COL_NULL)).thenReturn(null); + when(res.isNull(BYTES_COL_NULL)).thenReturn(true); + when(res.getBytes(BYTES_COL_NOT_NULL)).thenReturn(ByteArray.copyFrom("FOO")); + when(res.isNull(BYTES_COL_NOT_NULL)).thenReturn(false); + when(res.getBytes(BYTES_COLINDEX_NULL - 1)).thenReturn(null); + when(res.isNull(BYTES_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getBytes(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(ByteArray.copyFrom("BAR")); + when(res.isNull(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(BYTES_COL_NULL)).thenReturn(Type.bytes()); + when(res.getColumnType(BYTES_COL_NOT_NULL)).thenReturn(Type.bytes()); + when(res.getColumnType(BYTES_COLINDEX_NULL - 1)).thenReturn(Type.bytes()); + when(res.getColumnType(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(Type.bytes()); + + when(res.getLong(LONG_COL_NULL)).thenReturn(0l); + when(res.isNull(LONG_COL_NULL)).thenReturn(true); + when(res.getLong(LONG_COL_NOT_NULL)).thenReturn(1l); + when(res.isNull(LONG_COL_NOT_NULL)).thenReturn(false); + when(res.getLong(LONG_COLINDEX_NULL - 1)).thenReturn(0l); + when(res.isNull(LONG_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getLong(LONG_COLINDEX_NOTNULL - 1)).thenReturn(2l); + when(res.isNull(LONG_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(LONG_COL_NULL)).thenReturn(Type.int64()); + when(res.getColumnType(LONG_COL_NOT_NULL)).thenReturn(Type.int64()); + when(res.getColumnType(LONG_COLINDEX_NULL - 1)).thenReturn(Type.int64()); + when(res.getColumnType(LONG_COLINDEX_NOTNULL - 1)).thenReturn(Type.int64()); + + when(res.getDate(DATE_COL_NULL)).thenAnswer(new Returns(null)); + when(res.isNull(DATE_COL_NULL)).thenAnswer(new Returns(true)); + when(res.getDate(DATE_COL_NOT_NULL)) + .thenAnswer(new Returns(Date.fromYearMonthDay(2017, 9, 10))); + when(res.isNull(DATE_COL_NOT_NULL)).thenAnswer(new Returns(false)); + when(res.getDate(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(null)); + when(res.isNull(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(true)); + when(res.getDate(DATE_COLINDEX_NOTNULL - 1)) + .thenAnswer(new Returns(Date.fromYearMonthDay(2017, 9, 10))); + when(res.isNull(DATE_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(false)); + when(res.getColumnType(DATE_COL_NULL)).thenAnswer(new Returns(Type.date())); + when(res.getColumnType(DATE_COL_NOT_NULL)).thenAnswer(new Returns(Type.date())); + when(res.getColumnType(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(Type.date())); + when(res.getColumnType(DATE_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(Type.date())); + + Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal1.clear(); + cal1.set(2017, 8, 10, 8, 15, 59); + Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal2.clear(); + cal2.set(2017, 8, 11, 8, 15, 59); + when(res.getTimestamp(TIMESTAMP_COL_NULL)).thenReturn(null); + when(res.isNull(TIMESTAMP_COL_NULL)).thenReturn(true); + when(res.getTimestamp(TIMESTAMP_COL_NOT_NULL)).thenReturn(Timestamp.of(cal1.getTime())); + when(res.isNull(TIMESTAMP_COL_NOT_NULL)).thenReturn(false); + when(res.getTimestamp(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(null); + when(res.isNull(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(Timestamp.of(cal2.getTime())); + when(res.isNull(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(TIMESTAMP_COL_NULL)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIMESTAMP_COL_NOT_NULL)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(Type.timestamp()); + + Calendar cal3 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal3.clear(); + cal3.set(1970, 0, 1, 14, 6, 15); + Calendar cal4 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal4.clear(); + cal4.set(1970, 0, 1, 14, 6, 15); + when(res.getTimestamp(TIME_COL_NULL)).thenReturn(null); + when(res.isNull(TIME_COL_NULL)).thenReturn(true); + when(res.getTimestamp(TIME_COL_NOT_NULL)).thenReturn(Timestamp.of(cal3.getTime())); + when(res.isNull(TIME_COL_NOT_NULL)).thenReturn(false); + when(res.getTimestamp(TIME_COLINDEX_NULL - 1)).thenReturn(null); + when(res.isNull(TIME_COLINDEX_NULL - 1)).thenReturn(true); + when(res.getTimestamp(TIME_COLINDEX_NOTNULL - 1)).thenReturn(Timestamp.of(cal4.getTime())); + when(res.isNull(TIME_COLINDEX_NOTNULL - 1)).thenReturn(false); + when(res.getColumnType(TIME_COL_NULL)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIME_COL_NOT_NULL)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIME_COLINDEX_NULL - 1)).thenReturn(Type.timestamp()); + when(res.getColumnType(TIME_COLINDEX_NOTNULL - 1)).thenReturn(Type.timestamp()); + + when(res.getLongList(ARRAY_COL_NULL)).thenAnswer(new Returns(null)); + when(res.isNull(ARRAY_COL_NULL)).thenAnswer(new Returns(true)); + when(res.getLongList(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(Arrays.asList(1L, 2L, 3L))); + when(res.isNull(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(false)); + when(res.getLongList(ARRAY_COLINDEX_NULL - 1)).thenAnswer(new Returns(null)); + when(res.isNull(ARRAY_COLINDEX_NULL - 1)).thenAnswer(new Returns(true)); + when(res.getLongList(ARRAY_COLINDEX_NOTNULL - 1)) + .thenAnswer(new Returns(Arrays.asList(1L, 2L, 3L))); + when(res.isNull(ARRAY_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(false)); + when(res.getColumnType(ARRAY_COL_NULL)).thenAnswer(new Returns(Type.array(Type.int64()))); + when(res.getColumnType(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(Type.array(Type.int64()))); + when(res.getColumnType(ARRAY_COLINDEX_NULL - 1)) + .thenAnswer(new Returns(Type.array(Type.int64()))); + when(res.getColumnType(ARRAY_COLINDEX_NOTNULL - 1)) + .thenAnswer(new Returns(Type.array(Type.int64()))); + + when(res.getColumnIndex(STRING_COL_NOT_NULL)).thenAnswer(new Returns(1)); + when(res.getColumnIndex(UNKNOWN_COLUMN)).thenThrow(new IllegalArgumentException()); + when(res.getColumnIndex(DATE_COL_NOT_NULL)).thenAnswer(new Returns(DATE_COLINDEX_NOTNULL - 1)); + when(res.getColumnIndex(ARRAY_COL_NOT_NULL)) + .thenAnswer(new Returns(ARRAY_COLINDEX_NOTNULL - 1)); + when(res.getColumnIndex(ARRAY_COL_NULL)).thenAnswer(new Returns(ARRAY_COLINDEX_NULL - 1)); + + when(res.getType()) + .thenReturn( + Type.struct( + StructField.of(STRING_COL_NULL, Type.string()), + StructField.of(STRING_COL_NOT_NULL, Type.string()), + StructField.of(BOOLEAN_COL_NULL, Type.bool()), + StructField.of(BOOLEAN_COL_NOT_NULL, Type.bool()), + StructField.of(DOUBLE_COL_NULL, Type.float64()), + StructField.of(DOUBLE_COL_NOT_NULL, Type.float64()), + StructField.of(BYTES_COL_NULL, Type.bytes()), + StructField.of(BYTES_COL_NOT_NULL, Type.bytes()), + StructField.of(LONG_COL_NULL, Type.int64()), + StructField.of(LONG_COL_NOT_NULL, Type.int64()), + StructField.of(DATE_COL_NULL, Type.date()), + StructField.of(DATE_COL_NOT_NULL, Type.date()), + StructField.of(TIMESTAMP_COL_NULL, Type.timestamp()), + StructField.of(TIMESTAMP_COL_NOT_NULL, Type.timestamp()), + StructField.of(TIME_COL_NULL, Type.timestamp()), + StructField.of(TIME_COL_NOT_NULL, Type.timestamp()), + StructField.of(URL_COL_NULL, Type.string()), + StructField.of(URL_COL_NOT_NULL, Type.string()))); + + // Next behaviour. + when(res.next()).thenReturn(true, true, true, true, false); + + return res; + } + + public JdbcResultSetTest() throws SQLException { + subject = JdbcResultSet.of(mock(Statement.class), getMockResultSet()); + subject.next(); + } + + @Test + public void testWasNull() throws SQLException { + String value = subject.getString(STRING_COL_NULL); + boolean wasNull = subject.wasNull(); + assertTrue(wasNull); + assertNull(value); + String valueNotNull = subject.getString(STRING_COL_NOT_NULL); + boolean wasNotNull = subject.wasNull(); + assertFalse(wasNotNull); + assertNotNull(valueNotNull); + } + + @Test + public void testNext() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + assertTrue(rs.isBeforeFirst()); + assertFalse(rs.isAfterLast()); + int num = 0; + while (rs.next()) { + num++; + } + assertTrue(num > 0); + assertFalse(rs.isBeforeFirst()); + assertTrue(rs.isAfterLast()); + } + } + + @Test + public void testClose() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + assertFalse(rs.isClosed()); + rs.next(); + assertNotNull(rs.getString(STRING_COL_NOT_NULL)); + rs.close(); + assertTrue(rs.isClosed()); + boolean failed = false; + try { + // Should fail + rs.getString(STRING_COL_NOT_NULL); + } catch (SQLException e) { + failed = true; + } + assertTrue(failed); + } + } + + @Test + public void testGetStringIndex() throws SQLException { + assertNotNull(subject.getString(STRING_COLINDEX_NOTNULL)); + assertEquals(STRING_VALUE, subject.getString(STRING_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetNStringIndex() throws SQLException { + assertNotNull(subject.getNString(STRING_COLINDEX_NOTNULL)); + assertEquals(STRING_VALUE, subject.getNString(STRING_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getNString(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetURLIndex() throws SQLException, MalformedURLException { + assertNotNull(subject.getURL(URL_COLINDEX_NOTNULL)); + assertEquals(new URL(URL_VALUE), subject.getURL(URL_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getURL(URL_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetURLIndexInvalid() throws SQLException, MalformedURLException { + thrown.expect(JdbcSqlExceptionImpl.class); + thrown.expectMessage("Invalid URL"); + assertNotNull(subject.getURL(STRING_COLINDEX_NOTNULL)); + } + + @Test + public void testGetBooleanIndex() throws SQLException { + assertNotNull(subject.getBoolean(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertFalse(subject.getBoolean(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetLongIndex() throws SQLException { + assertNotNull(subject.getLong(LONG_COLINDEX_NOTNULL)); + assertEquals(LONG_VALUE, subject.getLong(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0l, subject.getLong(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDoubleIndex() throws SQLException { + assertNotNull(subject.getDouble(DOUBLE_COLINDEX_NOTNULL)); + assertEquals(DOUBLE_VALUE, subject.getDouble(DOUBLE_COLINDEX_NOTNULL), 0d); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getDouble(DOUBLE_COLINDEX_NULL), 0d); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBigDecimalIndexAndScale() throws SQLException { + assertNotNull(subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL, 2)); + assertEquals( + BigDecimal.valueOf(DOUBLE_VALUE).setScale(2, RoundingMode.HALF_UP), + subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL, 2)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(DOUBLE_COLINDEX_NULL, 2)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBytesIndex() throws SQLException { + assertNotNull(subject.getBytes(BYTES_COLINDEX_NOTNULL)); + assertArrayEquals(BYTES_VALUE.toByteArray(), subject.getBytes(BYTES_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBytes(BYTES_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetDateIndex() throws SQLException { + assertNotNull(subject.getDate(DATE_COLINDEX_NOTNULL)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getDate(DATE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(DATE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimeIndex() throws SQLException { + assertNotNull(subject.getTime(TIME_COLINDEX_NOTNULL)); + assertEquals( + new Time(TIME_VALUE.toSqlTimestamp().getTime()), subject.getTime(TIME_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getTime(TIME_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimestampIndex() throws SQLException { + assertNotNull(subject.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL)); + assertEquals( + TIMESTAMP_VALUE.toSqlTimestamp(), subject.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(TIMESTAMP_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringLabel() throws SQLException { + assertNotNull(subject.getString(STRING_COL_NOT_NULL)); + assertEquals("FOO", subject.getString(STRING_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetNStringLabel() throws SQLException { + assertNotNull(subject.getNString(STRING_COL_NOT_NULL)); + assertEquals("FOO", subject.getNString(STRING_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getNString(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetURLLabel() throws SQLException { + assertNotNull(subject.getString(URL_COL_NOT_NULL)); + assertEquals(URL_VALUE, subject.getString(URL_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(URL_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetURLLabelInvalid() throws SQLException { + thrown.expect(JdbcSqlExceptionImpl.class); + thrown.expectMessage("Invalid URL"); + assertNotNull(subject.getURL(STRING_COL_NOT_NULL)); + } + + @Test + public void testGetBooleanLabel() throws SQLException { + assertNotNull(subject.getBoolean(BOOLEAN_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertFalse(subject.getBoolean(BOOLEAN_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetLongLabel() throws SQLException { + assertNotNull(subject.getLong(LONG_COL_NOT_NULL)); + assertEquals(1l, subject.getLong(LONG_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertEquals(0l, subject.getLong(LONG_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDoubleLabel() throws SQLException { + assertNotNull(subject.getDouble(DOUBLE_COL_NOT_NULL)); + assertEquals(DOUBLE_VALUE, subject.getDouble(DOUBLE_COL_NOT_NULL), 0d); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getDouble(DOUBLE_COL_NULL), 0d); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBigDecimalLabelAndScale() throws SQLException { + assertNotNull(subject.getBigDecimal(DOUBLE_COL_NOT_NULL, 2)); + assertEquals(BigDecimal.valueOf(3.14d), subject.getBigDecimal(DOUBLE_COL_NOT_NULL, 2)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(DOUBLE_COL_NULL, 2)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBytesLabel() throws SQLException { + assertNotNull(subject.getBytes(BYTES_COL_NOT_NULL)); + assertArrayEquals( + ByteArray.copyFrom("FOO").toByteArray(), subject.getBytes(BYTES_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBytes(BYTES_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetDateLabel() throws SQLException { + assertNotNull(subject.getDate(DATE_COL_NOT_NULL)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getDate(DATE_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(DATE_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimeLabel() throws SQLException { + assertNotNull(subject.getTime(TIME_COL_NOT_NULL)); + assertEquals( + new Time(TIME_VALUE.toSqlTimestamp().getTime()), subject.getTime(TIME_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getTime(TIME_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimestampLabel() throws SQLException { + assertNotNull(subject.getTime(TIMESTAMP_COL_NOT_NULL)); + assertEquals(TIMESTAMP_VALUE.toSqlTimestamp(), subject.getTimestamp(TIMESTAMP_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(TIMESTAMP_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetMetaData() throws SQLException { + JdbcResultSetMetaData metadata = subject.getMetaData(); + assertNotNull(metadata); + } + + @Test + public void testFindColumn() throws SQLException { + assertEquals(2, subject.findColumn(STRING_COL_NOT_NULL)); + } + + @Test + public void testGetBigDecimalIndex() throws SQLException { + assertNotNull(subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL)); + assertEquals(BigDecimal.valueOf(DOUBLE_VALUE), subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBigDecimalLabel() throws SQLException { + assertNotNull(subject.getBigDecimal(DOUBLE_COL_NOT_NULL)); + assertEquals(BigDecimal.valueOf(DOUBLE_VALUE), subject.getBigDecimal(DOUBLE_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(DOUBLE_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStatement() throws SQLException { + assertNotNull(subject.getStatement()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetDateIndexCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(); + assertNotNull(subject.getDate(DATE_COLINDEX_NOTNULL, cal)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getDate(DATE_COLINDEX_NOTNULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(DATE_COLINDEX_NULL, cal)); + assertTrue(subject.wasNull()); + + Calendar calGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + Calendar expectedCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + expectedCal.clear(); + expectedCal.set(DATE_VALUE.getYear(), DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()); + java.sql.Date expected = new java.sql.Date(expectedCal.getTimeInMillis()); + assertEquals(expected, subject.getDate(DATE_COLINDEX_NOTNULL, calGMT)); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetDateLabelCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(); + assertNotNull(subject.getDate(DATE_COL_NOT_NULL, cal)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getDate(DATE_COL_NOT_NULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(DATE_COL_NULL, cal)); + assertTrue(subject.wasNull()); + + Calendar calGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + Calendar expected = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + expected.set( + DATE_VALUE.getYear(), DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth(), 0, 0, 0); + expected.clear(Calendar.MILLISECOND); + assertEquals( + new java.sql.Date(expected.getTimeInMillis()), subject.getDate(DATE_COL_NOT_NULL, calGMT)); + } + + @Test + public void testGetTimeIndexCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + + assertNotNull(subject.getTime(TIME_COLINDEX_NOTNULL, cal)); + assertEquals( + new Time(TIME_VALUE.toSqlTimestamp().getTime()), + subject.getTime(TIME_COLINDEX_NOTNULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTime(TIME_COLINDEX_NULL, cal)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimeLabelCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + + assertNotNull(subject.getTime(TIME_COL_NOT_NULL, cal)); + assertEquals( + new Time(TIME_VALUE.toSqlTimestamp().getTime()), subject.getTime(TIME_COL_NOT_NULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTime(TIME_COL_NULL, cal)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimestampIndexCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + + assertNotNull(subject.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL, cal)); + assertEquals( + TIMESTAMP_VALUE.toSqlTimestamp(), subject.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(TIMESTAMP_COLINDEX_NULL, cal)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimestampLabelCalendar() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + + assertNotNull(subject.getTimestamp(TIMESTAMP_COL_NOT_NULL, cal)); + assertEquals( + TIMESTAMP_VALUE.toSqlTimestamp(), subject.getTimestamp(TIMESTAMP_COL_NOT_NULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(TIMESTAMP_COL_NULL, cal)); + assertTrue(subject.wasNull()); + } + + @Test + public void testIsClosed() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + assertFalse(rs.isClosed()); + rs.close(); + assertTrue(rs.isClosed()); + } + } + + @Test + public void testGetByteIndex() throws SQLException { + assertNotNull(subject.getByte(LONG_COLINDEX_NOTNULL)); + assertEquals(LONG_VALUE, subject.getByte(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getByte(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetShortIndex() throws SQLException { + assertNotNull(subject.getShort(LONG_COLINDEX_NOTNULL)); + assertEquals(LONG_VALUE, subject.getShort(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getShort(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetIntIndex() throws SQLException { + assertNotNull(subject.getInt(LONG_COLINDEX_NOTNULL)); + int expected = (int) LONG_VALUE; + assertEquals(expected, subject.getInt(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getInt(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetFloatIndex() throws SQLException { + assertNotNull(subject.getFloat(DOUBLE_COLINDEX_NOTNULL)); + float expected = (float) DOUBLE_VALUE; + assertEquals(expected, subject.getFloat(DOUBLE_COLINDEX_NOTNULL), 0f); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getFloat(DOUBLE_COLINDEX_NULL), 0f); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetByteLabel() throws SQLException { + assertNotNull(subject.getByte(LONG_COL_NOT_NULL)); + assertEquals(1, subject.getByte(LONG_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getByte(LONG_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetShortLabel() throws SQLException { + assertNotNull(subject.getShort(LONG_COL_NOT_NULL)); + assertEquals(1, subject.getShort(LONG_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getShort(LONG_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetIntLabel() throws SQLException { + assertNotNull(subject.getInt(LONG_COL_NOT_NULL)); + assertEquals(1, subject.getInt(LONG_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getInt(LONG_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetFloatLabel() throws SQLException { + assertNotNull(subject.getFloat(DOUBLE_COL_NOT_NULL)); + float expected = (float) DOUBLE_VALUE; + assertEquals(expected, subject.getFloat(DOUBLE_COL_NOT_NULL), 0f); + assertFalse(subject.wasNull()); + assertEquals(0f, subject.getFloat(DOUBLE_COL_NULL), 0f); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetObjectLabel() throws SQLException { + assertNotNull(subject.getObject(DATE_COL_NOT_NULL)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getObject(DATE_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(DATE_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetObjectIndex() throws SQLException { + assertNotNull(subject.getObject(DATE_COLINDEX_NOTNULL)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getObject(DATE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(DATE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetObjectLabelMap() throws SQLException { + Map> map = new HashMap<>(); + assertNotNull(subject.getObject(DATE_COL_NOT_NULL, map)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getObject(DATE_COL_NOT_NULL, map)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(DATE_COL_NULL, map)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetObjectIndexMap() throws SQLException { + Map> map = Collections.emptyMap(); + assertNotNull(subject.getObject(DATE_COLINDEX_NOTNULL, map)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + subject.getObject(DATE_COLINDEX_NOTNULL, map)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(DATE_COLINDEX_NULL, map)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetArrayLabel() throws SQLException { + assertNotNull(subject.getArray(ARRAY_COL_NOT_NULL)); + assertEquals( + JdbcArray.createArray(JdbcDataType.INT64, Arrays.asList(1L, 2L, 3L)), + subject.getArray(ARRAY_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getArray(ARRAY_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetArrayIndex() throws SQLException { + assertNotNull(subject.getArray(ARRAY_COLINDEX_NOTNULL)); + assertEquals( + JdbcArray.createArray(JdbcDataType.INT64, Arrays.asList(1L, 2L, 3L)), + subject.getArray(ARRAY_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getArray(ARRAY_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetWarnings() throws SQLException { + assertNull(subject.getWarnings()); + } + + @Test + public void testClearWarnings() throws SQLException { + subject.clearWarnings(); + } + + @Test + public void testIsBeforeFirst() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + assertTrue(rs.isBeforeFirst()); + rs.next(); + assertFalse(rs.isBeforeFirst()); + } + } + + @Test + public void testIsAfterLast() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + assertFalse(rs.isAfterLast()); + while (rs.next()) { + // do nothing + } + assertTrue(rs.isAfterLast()); + } + } + + @Test + public void testGetCharacterStreamIndex() throws SQLException, IOException { + assertNotNull(subject.getCharacterStream(STRING_COLINDEX_NOTNULL)); + Reader actual = subject.getCharacterStream(STRING_COLINDEX_NOTNULL); + char[] cbuf = new char[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(STRING_VALUE, new String(cbuf, 0, len)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getCharacterStream(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetCharacterStreamLabel() throws SQLException, IOException { + assertNotNull(subject.getCharacterStream(STRING_COL_NOT_NULL)); + Reader actual = subject.getCharacterStream(STRING_COL_NOT_NULL); + char[] cbuf = new char[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals("FOO", new String(cbuf, 0, len)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getCharacterStream(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetNCharacterStreamIndex() throws SQLException, IOException { + assertNotNull(subject.getNCharacterStream(STRING_COLINDEX_NOTNULL)); + Reader actual = subject.getNCharacterStream(STRING_COLINDEX_NOTNULL); + char[] cbuf = new char[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(STRING_VALUE, new String(cbuf, 0, len)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getNCharacterStream(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetNCharacterStreamLabel() throws SQLException, IOException { + assertNotNull(subject.getNCharacterStream(STRING_COL_NOT_NULL)); + Reader actual = subject.getNCharacterStream(STRING_COL_NOT_NULL); + char[] cbuf = new char[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals("FOO", new String(cbuf, 0, len)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getNCharacterStream(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamIndex() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(STRING_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(STRING_COLINDEX_NOTNULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(STRING_VALUE, new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetUnicodeStreamIndex() throws SQLException, IOException { + assertNotNull(subject.getUnicodeStream(STRING_COLINDEX_NOTNULL)); + InputStream actual = subject.getUnicodeStream(STRING_COLINDEX_NOTNULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(STRING_VALUE, new String(cbuf, 0, len, StandardCharsets.UTF_16LE)); + assertEquals(6, len); + assertFalse(subject.wasNull()); + assertNull(subject.getUnicodeStream(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBinaryStreamIndex() throws SQLException, IOException { + assertNotNull(subject.getBinaryStream(BYTES_COLINDEX_NOTNULL)); + InputStream actual = subject.getBinaryStream(BYTES_COLINDEX_NOTNULL); + byte[] cbuf = new byte[3]; + int len = actual.read(cbuf, 0, cbuf.length); + assertArrayEquals(BYTES_VALUE.toByteArray(), cbuf); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getUnicodeStream(BYTES_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamLabel() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(STRING_COL_NOT_NULL)); + InputStream actual = subject.getAsciiStream(STRING_COL_NOT_NULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals("FOO", new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetUnicodeStreamLabel() throws SQLException, IOException { + assertNotNull(subject.getUnicodeStream(STRING_COL_NOT_NULL)); + InputStream actual = subject.getUnicodeStream(STRING_COL_NOT_NULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals("FOO", new String(cbuf, 0, len, StandardCharsets.UTF_16LE)); + assertEquals(6, len); + assertFalse(subject.wasNull()); + assertNull(subject.getUnicodeStream(STRING_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBinaryStreamLabel() throws SQLException, IOException { + assertNotNull(subject.getBinaryStream(BYTES_COL_NOT_NULL)); + InputStream actual = subject.getBinaryStream(BYTES_COL_NOT_NULL); + byte[] cbuf = new byte[3]; + int len = actual.read(cbuf, 0, cbuf.length); + assertArrayEquals(ByteArray.copyFrom("FOO").toByteArray(), cbuf); + assertEquals(3, len); + assertFalse(subject.wasNull()); + assertNull(subject.getUnicodeStream(BYTES_COL_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBeforeNext() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + thrown.expect(SQLException.class); + thrown.expectMessage( + "FAILED_PRECONDITION: ResultSet is before first row. Call next() first."); + rs.getBigDecimal(LONG_COLINDEX_NOTNULL); + } + } + + @Test + public void testGetAfterLast() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + while (rs.next()) { + // do nothing + } + thrown.expect(SQLException.class); + thrown.expectMessage( + "FAILED_PRECONDITION: ResultSet is after last row. There is no more data available."); + rs.getBigDecimal(LONG_COLINDEX_NOTNULL); + } + } + + @Test + public void testFindIllegalColumnName() throws SQLException { + thrown.expect(SQLException.class); + thrown.expectMessage("INVALID_ARGUMENT: no column with label " + UNKNOWN_COLUMN + " found"); + int index = subject.findColumn(UNKNOWN_COLUMN); + assertEquals(0, index); + } + + @Test + public void testGetRowAndIsFirst() throws SQLException { + try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { + int row = 0; + while (rs.next()) { + row++; + assertEquals(row, rs.getRow()); + assertEquals(row == 1, rs.isFirst()); + } + } + } + + @Test + public void testGetHoldability() throws SQLException { + assertEquals(java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT, subject.getHoldability()); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java new file mode 100644 index 000000000000..878b3a6bb0e9 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -0,0 +1,185 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import com.google.rpc.Code; +import java.sql.Array; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.List; + +/** SQL Script verifier for JDBC connections */ +public class JdbcSqlScriptVerifier extends AbstractSqlScriptVerifier { + + static class JdbcGenericStatementResult extends GenericStatementResult { + private final boolean result; + private final long updateCount; + private final ResultSet resultSet; + + private JdbcGenericStatementResult(Statement statement, boolean result) throws SQLException { + this.result = result; + if (result) { + this.resultSet = statement.getResultSet(); + this.updateCount = -1L; + } else { + this.resultSet = null; + this.updateCount = statement.getUpdateCount(); + } + } + + @Override + protected ResultType getResultType() { + if (result) { + return ResultType.RESULT_SET; + } + if (updateCount == -2L) { + return ResultType.NO_RESULT; + } + return ResultType.UPDATE_COUNT; + } + + @Override + protected GenericResultSet getResultSet() { + return new JdbcGenericResultSet(resultSet); + } + + @Override + protected long getUpdateCount() { + return updateCount; + } + } + + static class JdbcGenericResultSet extends GenericResultSet { + private final ResultSet resultSet; + + private JdbcGenericResultSet(ResultSet resultSet) { + this.resultSet = resultSet; + } + + @Override + protected boolean next() throws SQLException { + return resultSet.next(); + } + + @Override + protected Object getValue(String col) throws SQLException { + Object value = resultSet.getObject(col); + if (value instanceof Timestamp) { + return com.google.cloud.Timestamp.of((Timestamp) value); + } else if (value instanceof Array) { + Array array = (Array) value; + switch (array.getBaseType()) { + case Types.BIGINT: + Long[] longs = (Long[]) array.getArray(); + List res = new ArrayList<>(); + for (Long l : longs) { + res.add(l); + } + return res; + default: + throw new IllegalArgumentException( + "Unsupported array base type: " + array.getBaseType()); + } + } + return value; + } + + @Override + protected int getColumnCount() throws Exception { + return resultSet.getMetaData().getColumnCount(); + } + + @Override + protected Object getFirstValue() throws Exception { + String col = resultSet.getMetaData().getColumnName(1); + return getValue(col); + } + } + + public static class JdbcGenericConnection extends GenericConnection { + private final Connection connection; + /** + * Use this to strip comments from a statement before the statement is executed. This should + * only be used when the connection is used in a unit test with a mocked underlying connection. + */ + private boolean stripCommentsBeforeExecute; + + public static JdbcGenericConnection of(Connection connection) { + return new JdbcGenericConnection(connection); + } + + private JdbcGenericConnection(Connection connection) { + this.connection = connection; + } + + @Override + protected GenericStatementResult execute(String sql) throws SQLException { + Statement statement = connection.createStatement(); + if (isStripCommentsBeforeExecute()) { + sql = StatementParser.removeCommentsAndTrim(sql); + } + boolean result = statement.execute(sql); + return new JdbcGenericStatementResult(statement, result); + } + + @Override + public void close() throws Exception { + if (this.connection != null) { + this.connection.close(); + } + } + + boolean isStripCommentsBeforeExecute() { + return stripCommentsBeforeExecute; + } + + void setStripCommentsBeforeExecute(boolean stripCommentsBeforeExecute) { + this.stripCommentsBeforeExecute = stripCommentsBeforeExecute; + } + } + + public JdbcSqlScriptVerifier() {} + + public JdbcSqlScriptVerifier(GenericConnectionProvider connectionProvider) { + super(connectionProvider); + } + + @Override + protected void verifyExpectedException( + String statement, Exception e, String code, String messagePrefix) { + assertThat(e instanceof JdbcSqlException, is(true)); + JdbcSqlException jdbcException = (JdbcSqlException) e; + assertThat(statement, jdbcException.getCode(), is(equalTo(Code.valueOf(code)))); + if (messagePrefix != null) { + assertThat( + statement, + e.getMessage(), + startsWith(messagePrefix.substring(1, messagePrefix.length() - 1))); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java new file mode 100644 index 000000000000..bc563652050f --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -0,0 +1,322 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import com.google.rpc.Code; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Matchers; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class JdbcStatementTest { + @Rule public final ExpectedException thrown = ExpectedException.none(); + private static final String SELECT = "SELECT 1"; + private static final String UPDATE = "UPDATE FOO SET BAR=1 WHERE BAZ=2"; + private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; + + @Rule public final ExpectedException expected = ExpectedException.none(); + + private JdbcStatement createStatement() { + Connection spanner = mock(Connection.class); + + com.google.cloud.spanner.ResultSet resultSet = mock(com.google.cloud.spanner.ResultSet.class); + when(resultSet.next()).thenReturn(true, false); + when(resultSet.getLong(0)).thenReturn(1L); + + StatementResult selectResult = mock(StatementResult.class); + when(selectResult.getResultType()).thenReturn(ResultType.RESULT_SET); + when(selectResult.getResultSet()).thenReturn(resultSet); + when(spanner.execute(com.google.cloud.spanner.Statement.of(SELECT))).thenReturn(selectResult); + + StatementResult updateResult = mock(StatementResult.class); + when(updateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT); + when(updateResult.getUpdateCount()).thenReturn(1L); + when(spanner.execute(com.google.cloud.spanner.Statement.of(UPDATE))).thenReturn(updateResult); + + StatementResult ddlResult = mock(StatementResult.class); + when(ddlResult.getResultType()).thenReturn(ResultType.NO_RESULT); + when(spanner.execute(com.google.cloud.spanner.Statement.of(DDL))).thenReturn(ddlResult); + + when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(SELECT))).thenReturn(resultSet); + when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(UPDATE))) + .thenThrow( + SpannerExceptionFactory.newSpannerException(ErrorCode.INVALID_ARGUMENT, "not a query")); + when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(DDL))) + .thenThrow( + SpannerExceptionFactory.newSpannerException(ErrorCode.INVALID_ARGUMENT, "not a query")); + + when(spanner.executeUpdate(com.google.cloud.spanner.Statement.of(UPDATE))).thenReturn(1L); + when(spanner.executeUpdate(com.google.cloud.spanner.Statement.of(SELECT))) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "not an update")); + when(spanner.executeUpdate(com.google.cloud.spanner.Statement.of(DDL))) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "not an update")); + + when(spanner.executeBatchUpdate(Matchers.anyListOf(com.google.cloud.spanner.Statement.class))) + .thenAnswer( + new Answer() { + @SuppressWarnings("unchecked") + @Override + public long[] answer(InvocationOnMock invocation) throws Throwable { + List statements = + (List) invocation.getArguments()[0]; + if (statements.isEmpty() + || StatementParser.INSTANCE.isDdlStatement(statements.get(0).getSql())) { + return new long[0]; + } + long[] res = + new long + [((List) invocation.getArguments()[0]) + .size()]; + Arrays.fill(res, 1L); + return res; + } + }); + + JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getSpannerConnection()).thenReturn(spanner); + return new JdbcStatement(connection); + } + + @Test + public void testQueryTimeout() throws SQLException { + final String select = "SELECT 1"; + JdbcConnection connection = mock(JdbcConnection.class); + Connection spanner = mock(Connection.class); + when(connection.getSpannerConnection()).thenReturn(spanner); + StatementResult result = mock(StatementResult.class); + when(result.getResultType()).thenReturn(ResultType.RESULT_SET); + when(result.getResultSet()).thenReturn(mock(com.google.cloud.spanner.ResultSet.class)); + when(spanner.execute(com.google.cloud.spanner.Statement.of(select))).thenReturn(result); + try (Statement statement = new JdbcStatement(connection)) { + assertThat(statement.getQueryTimeout(), is(equalTo(0))); + statement.setQueryTimeout(1); + assertThat(statement.getQueryTimeout(), is(equalTo(1))); + statement.setQueryTimeout(99); + assertThat(statement.getQueryTimeout(), is(equalTo(99))); + statement.setQueryTimeout(0); + assertThat(statement.getQueryTimeout(), is(equalTo(0))); + } + + when(spanner.getStatementTimeout(TimeUnit.SECONDS)).thenReturn(1L); + when(spanner.getStatementTimeout(TimeUnit.MILLISECONDS)).thenReturn(1000L); + when(spanner.getStatementTimeout(TimeUnit.MICROSECONDS)).thenReturn(1000000L); + when(spanner.getStatementTimeout(TimeUnit.NANOSECONDS)).thenReturn(1000000000L); + when(spanner.hasStatementTimeout()).thenReturn(true); + try (Statement statement = new JdbcStatement(connection)) { + assertThat(statement.getQueryTimeout(), is(equalTo(0))); + statement.execute(select); + // statement has no timeout, so it should also not be set on the connection + verify(spanner, never()).setStatementTimeout(1L, TimeUnit.SECONDS); + } + try (Statement statement = new JdbcStatement(connection)) { + // now set a query timeout that should temporarily applied to the connection + statement.setQueryTimeout(2); + statement.execute(select); + // assert that it is temporarily set to 2 seconds, and then back to the original 1 second + // value + verify(spanner).setStatementTimeout(2L, TimeUnit.SECONDS); + verify(spanner).setStatementTimeout(1L, TimeUnit.SECONDS); + } + } + + @Test + public void testExecuteWithSelectStatement() throws SQLException { + Statement statement = createStatement(); + boolean res = statement.execute(SELECT); + assertThat(res, is(true)); + assertThat(statement.getUpdateCount(), is(equalTo(JdbcConstants.STATEMENT_RESULT_SET))); + try (ResultSet rs = statement.getResultSet()) { + assertThat(rs, is(notNullValue())); + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + + @Test + public void testExecuteWithUpdateStatement() throws SQLException { + Statement statement = createStatement(); + boolean res = statement.execute(UPDATE); + assertThat(res, is(false)); + assertThat(statement.getResultSet(), is(nullValue())); + assertThat(statement.getUpdateCount(), is(equalTo(1))); + } + + @Test + public void testExecuteWithDdlStatement() throws SQLException { + Statement statement = createStatement(); + boolean res = statement.execute(DDL); + assertThat(res, is(false)); + assertThat(statement.getResultSet(), is(nullValue())); + assertThat(statement.getUpdateCount(), is(equalTo(JdbcConstants.STATEMENT_NO_RESULT))); + } + + @Test + public void testExecuteQuery() throws SQLException { + Statement statement = createStatement(); + try (ResultSet rs = statement.executeQuery(SELECT)) { + assertThat(rs, is(notNullValue())); + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(1L))); + } + } + + @Test + public void testExecuteQueryWithUpdateStatement() throws SQLException { + Statement statement = createStatement(); + expected.expect(JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query")); + statement.executeQuery(UPDATE); + } + + @Test + public void testExecuteQueryWithDdlStatement() throws SQLException { + Statement statement = createStatement(); + expected.expect(JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query")); + statement.executeQuery(DDL); + } + + @Test + public void testExecuteUpdate() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.executeUpdate(UPDATE), is(equalTo(1))); + } + + @Test + public void testExecuteUpdateWithSelectStatement() throws SQLException { + Statement statement = createStatement(); + expected.expect( + JdbcExceptionMatcher.matchCodeAndMessage( + Code.INVALID_ARGUMENT, "The statement is not an update or DDL statement")); + statement.executeUpdate(SELECT); + } + + @Test + public void testExecuteUpdateWithDdlStatement() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.executeUpdate(DDL), is(equalTo(0))); + } + + @Test + public void testNoBatchMixing() throws SQLException { + thrown.expect(SQLException.class); + thrown.expectMessage("Mixing DML and DDL statements in a batch is not allowed."); + try (Statement statement = createStatement()) { + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'FOO')"); + statement.addBatch("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)"); + } + } + + @Test + public void testNoBatchQuery() throws SQLException { + thrown.expect(SQLException.class); + thrown.expectMessage( + "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching."); + try (Statement statement = createStatement()) { + statement.addBatch("SELECT * FROM FOO"); + } + } + + @Test + public void testDmlBatch() throws SQLException { + try (Statement statement = createStatement()) { + // Verify that multiple batches can be executed on the same statement. + for (int i = 0; i < 2; i++) { + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'TEST')"); + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (2, 'TEST')"); + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (3, 'TEST')"); + assertThat(statement.executeBatch(), is(equalTo(new int[] {1, 1, 1}))); + } + } + } + + @Test + public void testConvertUpdateCounts() throws SQLException { + try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { + int[] updateCounts = statement.convertUpdateCounts(new long[] {1L, 2L, 3L}); + assertThat(updateCounts, is(equalTo(new int[] {1, 2, 3}))); + updateCounts = statement.convertUpdateCounts(new long[] {0L, 0L, 0L}); + assertThat(updateCounts, is(equalTo(new int[] {0, 0, 0}))); + + expected.expect(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE)); + statement.convertUpdateCounts(new long[] {1L, Integer.MAX_VALUE + 1L}); + } + } + + @Test + public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException { + try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { + int[] updateCounts = new int[3]; + statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 2L, 3L}, updateCounts); + assertThat( + updateCounts, + is( + equalTo( + new int[] { + Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO + }))); + + statement.convertUpdateCountsToSuccessNoInfo(new long[] {0L, 0L, 0L}, updateCounts); + assertThat( + updateCounts, + is( + equalTo( + new int[] { + Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED + }))); + + statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 0L, 2L}, updateCounts); + assertThat( + updateCounts, + is( + equalTo( + new int[] { + Statement.SUCCESS_NO_INFO, Statement.EXECUTE_FAILED, Statement.SUCCESS_NO_INFO + }))); + + expected.expect(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE)); + statement.convertUpdateCountsToSuccessNoInfo( + new long[] {1L, Integer.MAX_VALUE + 1L}, updateCounts); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java new file mode 100644 index 000000000000..fc9d81549c56 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 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.jdbc.JdbcConnectionGeneratedSqlScriptTest.TestConnectionProvider; +import java.sql.Connection; +import java.sql.Statement; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * As JDBC connections store the statement timeout on {@link Statement} objects instead of on the + * {@link Connection}, the JDBC driver needs to set and reset the connection timeout on the + * underlying connection after each statement execution. JDBC also uses seconds as the time unit for + * timeouts, while the underlying {@link com.google.cloud.spanner.jdbc.Connection}s use + * milliseconds. This test script tests a number of special cases regarding this. + */ +@RunWith(JUnit4.class) +public class JdbcTimeoutSqlTest { + @Test + public void testTimeoutScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass(), false); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java new file mode 100644 index 000000000000..44e326cf9177 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java @@ -0,0 +1,166 @@ +/* + * Copyright 2019 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import com.google.api.client.util.Base64; +import com.google.cloud.Date; +import com.google.cloud.Timestamp; +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Value; +import com.google.protobuf.util.Timestamps; +import com.google.spanner.v1.ResultSet; +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.util.Random; + +public class RandomResultSetGenerator { + private static final Type TYPES[] = + new Type[] { + Type.newBuilder().setCode(TypeCode.BOOL).build(), + Type.newBuilder().setCode(TypeCode.INT64).build(), + Type.newBuilder().setCode(TypeCode.FLOAT64).build(), + Type.newBuilder().setCode(TypeCode.STRING).build(), + Type.newBuilder().setCode(TypeCode.BYTES).build(), + Type.newBuilder().setCode(TypeCode.DATE).build(), + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.BOOL)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.INT64)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.FLOAT64)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.STRING)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.BYTES)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.DATE)) + .build(), + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.TIMESTAMP)) + .build(), + }; + + private static final ResultSetMetadata generateMetadata() { + StructType.Builder rowTypeBuilder = StructType.newBuilder(); + for (int col = 0; col < TYPES.length; col++) { + rowTypeBuilder.addFields(Field.newBuilder().setName("COL" + col).setType(TYPES[col])).build(); + } + ResultSetMetadata.Builder builder = ResultSetMetadata.newBuilder(); + builder.setRowType(rowTypeBuilder.build()); + return builder.build(); + } + + private static final ResultSetMetadata METADATA = generateMetadata(); + + private final int rowCount; + private final Random random = new Random(); + + public RandomResultSetGenerator(int rowCount) { + this.rowCount = rowCount; + } + + public ResultSet generate() { + ResultSet.Builder builder = ResultSet.newBuilder(); + for (int row = 0; row < rowCount; row++) { + ListValue.Builder rowBuilder = ListValue.newBuilder(); + for (int col = 0; col < TYPES.length; col++) { + Value.Builder valueBuilder = Value.newBuilder(); + setRandomValue(valueBuilder, TYPES[col]); + rowBuilder.addValues(valueBuilder.build()); + } + builder.addRows(rowBuilder.build()); + } + builder.setMetadata(METADATA); + return builder.build(); + } + + private void setRandomValue(Value.Builder builder, Type type) { + if (randomNull()) { + builder.setNullValue(NullValue.NULL_VALUE); + } else { + switch (type.getCode()) { + case ARRAY: + int length = random.nextInt(20) + 1; + ListValue.Builder arrayBuilder = ListValue.newBuilder(); + for (int i = 0; i < length; i++) { + Value.Builder valueBuilder = Value.newBuilder(); + setRandomValue(valueBuilder, type.getArrayElementType()); + arrayBuilder.addValues(valueBuilder.build()); + } + builder.setListValue(arrayBuilder.build()); + break; + case BOOL: + builder.setBoolValue(random.nextBoolean()); + break; + case STRING: + case BYTES: + byte[] bytes = new byte[random.nextInt(200)]; + random.nextBytes(bytes); + builder.setStringValue(Base64.encodeBase64String(bytes)); + break; + case DATE: + Date date = + Date.fromYearMonthDay( + random.nextInt(2019) + 1, random.nextInt(11) + 1, random.nextInt(28) + 1); + builder.setStringValue(date.toString()); + break; + case FLOAT64: + builder.setNumberValue(random.nextDouble()); + break; + case INT64: + builder.setStringValue(String.valueOf(random.nextLong())); + break; + case TIMESTAMP: + com.google.protobuf.Timestamp ts = + Timestamps.add( + Timestamps.EPOCH, + com.google.protobuf.Duration.newBuilder() + .setSeconds(random.nextInt(100_000_000)) + .setNanos(random.nextInt(1000_000_000)) + .build()); + builder.setStringValue(Timestamp.fromProto(ts).toString()); + break; + case STRUCT: + case TYPE_CODE_UNSPECIFIED: + case UNRECOGNIZED: + default: + throw new IllegalArgumentException("Unknown or unsupported type: " + type.getCode()); + } + } + } + + private boolean randomNull() { + return random.nextInt(10) == 0; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java new file mode 100644 index 000000000000..830c9085156d --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java @@ -0,0 +1,166 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.ReadOnlyStalenessConverter; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ReadOnlyStalenessConverterTest { + + static String getAllowedValues( + Class> converterClass) + throws CompileException { + Set statements = ClientSideStatements.INSTANCE.getCompiledStatements(); + for (ClientSideStatementImpl statement : statements) { + if (statement.getSetStatement() != null + && converterClass.getName().endsWith(statement.getSetStatement().getConverterName())) { + return statement.getSetStatement().getAllowedValues(); + } + } + return null; + } + + @Test + public void testConvert() throws CompileException { + String allowedValues = getAllowedValues(ReadOnlyStalenessConverter.class); + assertThat(allowedValues, is(notNullValue())); + ReadOnlyStalenessConverter converter = new ReadOnlyStalenessConverter(allowedValues); + + assertThat(converter.convert("strong"), is(equalTo(TimestampBound.strong()))); + assertThat(converter.convert("Strong"), is(equalTo(TimestampBound.strong()))); + assertThat(converter.convert("STRONG"), is(equalTo(TimestampBound.strong()))); + + assertThat( + converter.convert("read_timestamp 2018-10-01T23:11:15.10001Z"), + is( + equalTo( + TimestampBound.ofReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); + assertThat( + converter.convert("Read_Timestamp 2018-10-01T23:11:15.999Z"), + is( + equalTo( + TimestampBound.ofReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.999Z"))))); + assertThat( + converter.convert("READ_TIMESTAMP 2018-10-01T23:11:15.1000Z"), + is( + equalTo( + TimestampBound.ofReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.1000Z"))))); + assertThat( + converter.convert("read_timestamp 2018-10-01T23:11:15.999999999Z"), + is( + equalTo( + TimestampBound.ofReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.999999999Z"))))); + assertThat( + converter.convert("read_timestamp\t2018-10-01T23:11:15.10001Z"), + is( + equalTo( + TimestampBound.ofReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); + assertThat(converter.convert("read_timestamp\n2018-10-01T23:11:15.10001Z"), is(nullValue())); + + assertThat( + converter.convert("min_read_timestamp 2018-10-01T23:11:15.10001Z"), + is( + equalTo( + TimestampBound.ofMinReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); + assertThat( + converter.convert("Min_Read_Timestamp 2018-10-01T23:11:15.999Z"), + is( + equalTo( + TimestampBound.ofMinReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.999Z"))))); + assertThat( + converter.convert("MIN_READ_TIMESTAMP 2018-10-01T23:11:15.1000Z"), + is( + equalTo( + TimestampBound.ofMinReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.1000Z"))))); + assertThat( + converter.convert("min_read_timestamp 2018-10-01T23:11:15.999999999Z"), + is( + equalTo( + TimestampBound.ofMinReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.999999999Z"))))); + assertThat( + converter.convert("min_read_timestamp\t2018-10-01T23:11:15.10001Z"), + is( + equalTo( + TimestampBound.ofMinReadTimestamp( + Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); + assertThat( + converter.convert("min_read_timestamp\n2018-10-01T23:11:15.10001Z"), is(nullValue())); + + assertThat( + converter.convert("exact_staleness 10s"), + is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); + assertThat( + converter.convert("Exact_Staleness 100ms"), + is(equalTo(TimestampBound.ofExactStaleness(100L, TimeUnit.MILLISECONDS)))); + assertThat( + converter.convert("EXACT_STALENESS 99999us"), + is(equalTo(TimestampBound.ofExactStaleness(99999L, TimeUnit.MICROSECONDS)))); + assertThat( + converter.convert("exact_staleness 999999999ns"), + is(equalTo(TimestampBound.ofExactStaleness(999999999L, TimeUnit.NANOSECONDS)))); + assertThat( + converter.convert("exact_staleness " + Long.MAX_VALUE + "ns"), + is(equalTo(TimestampBound.ofExactStaleness(Long.MAX_VALUE, TimeUnit.NANOSECONDS)))); + + assertThat( + converter.convert("max_staleness 10s"), + is(equalTo(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)))); + assertThat( + converter.convert("Max_Staleness 100ms"), + is(equalTo(TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)))); + assertThat( + converter.convert("MAX_STALENESS 99999us"), + is(equalTo(TimestampBound.ofMaxStaleness(99999L, TimeUnit.MICROSECONDS)))); + assertThat( + converter.convert("max_staleness 999999999ns"), + is(equalTo(TimestampBound.ofMaxStaleness(999999999L, TimeUnit.NANOSECONDS)))); + assertThat( + converter.convert("max_staleness " + Long.MAX_VALUE + "ns"), + is(equalTo(TimestampBound.ofMaxStaleness(Long.MAX_VALUE, TimeUnit.NANOSECONDS)))); + + assertThat(converter.convert(""), is(nullValue())); + assertThat(converter.convert(" "), is(nullValue())); + assertThat(converter.convert("random string"), is(nullValue())); + assertThat(converter.convert("read_timestamp"), is(nullValue())); + assertThat(converter.convert("min_read_timestamp"), is(nullValue())); + assertThat(converter.convert("exact_staleness"), is(nullValue())); + assertThat(converter.convert("max_staleness"), is(nullValue())); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java new file mode 100644 index 000000000000..6c0ca2d48b69 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java @@ -0,0 +1,199 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.NoCredentials; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Matchers; + +@RunWith(JUnit4.class) +public class ReadOnlyStalenessTest { + private static final String URI = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?readOnly=true"; + private static final String SELECT = "select foo from bar"; + + private final DatabaseClient dbClient = mock(DatabaseClient.class); + + private ConnectionImpl createConnection(ConnectionOptions options) { + Spanner spanner = mock(Spanner.class); + SpannerPool spannerPool = mock(SpannerPool.class); + when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) + .thenReturn(spanner); + DdlClient ddlClient = mock(DdlClient.class); + ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); + when(singleUseReadOnlyTx.executeQuery(Statement.of(SELECT))).thenReturn(mock(ResultSet.class)); + when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) + .thenReturn(singleUseReadOnlyTx); + ReadOnlyTransaction readOnlyTx = mock(ReadOnlyTransaction.class); + when(readOnlyTx.executeQuery(Statement.of(SELECT))).thenReturn(mock(ResultSet.class)); + when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))).thenReturn(readOnlyTx); + + return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); + } + + @Test + public void testDefaultReadOnlyStalenessAutocommitOnce() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(connection.isAutocommit(), is(true)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).singleUseReadOnlyTransaction(TimestampBound.strong()); + } + } + + @Test + public void testDefaultReadOnlyStalenessAutocommitTwice() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(connection.isAutocommit(), is(true)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + connection.execute(Statement.of(SELECT)); + verify(dbClient, times(2)).singleUseReadOnlyTransaction(TimestampBound.strong()); + } + } + + @Test + public void testDefaultReadOnlyStalenessAutocommitChanging() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(connection.isAutocommit(), is(true)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).singleUseReadOnlyTransaction(TimestampBound.strong()); + + connection.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + connection.execute(Statement.of(SELECT)); + verify(dbClient) + .singleUseReadOnlyTransaction(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + + connection.setReadOnlyStaleness(TimestampBound.ofMaxStaleness(5L, TimeUnit.SECONDS)); + connection.execute(Statement.of(SELECT)); + verify(dbClient) + .singleUseReadOnlyTransaction(TimestampBound.ofMaxStaleness(5L, TimeUnit.SECONDS)); + + connection.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); + connection.execute(Statement.of(SELECT)); + verify(dbClient) + .singleUseReadOnlyTransaction(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); + + connection.setReadOnlyStaleness(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); + connection.execute(Statement.of(SELECT)); + verify(dbClient) + .singleUseReadOnlyTransaction(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); + } + } + + @Test + public void testDefaultReadOnlyStalenessTransactionalOnce() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + assertThat(connection.isAutocommit(), is(false)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).readOnlyTransaction(TimestampBound.strong()); + } + } + + @Test + public void testDefaultReadOnlyStalenessTransactionalTwice() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + assertThat(connection.isAutocommit(), is(false)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + connection.execute(Statement.of(SELECT)); + connection.commit(); + // one transaction + verify(dbClient, times(1)).readOnlyTransaction(TimestampBound.strong()); + + connection.execute(Statement.of(SELECT)); + connection.commit(); + connection.execute(Statement.of(SELECT)); + // two transactions (plus one above) + verify(dbClient, times(3)).readOnlyTransaction(TimestampBound.strong()); + } + } + + @Test + public void testDefaultReadOnlyStalenessTransactionalChanging() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + assertThat(connection.isAutocommit(), is(false)); + assertThat(connection.isReadOnly(), is(true)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).readOnlyTransaction(TimestampBound.strong()); + connection.commit(); + + connection.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).readOnlyTransaction(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); + connection.commit(); + + connection.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); + connection.execute(Statement.of(SELECT)); + verify(dbClient).readOnlyTransaction(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); + connection.commit(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java new file mode 100644 index 000000000000..4c96632f371e --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java @@ -0,0 +1,170 @@ +/* + * Copyright 2019 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 com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.durationToString; +import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.getTimeUnitAbbreviation; +import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.parseRfc3339; +import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.parseTimeUnit; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.TimestampBound; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ReadOnlyStalenessUtilTest { + + @Test + public void testParseRfc3339() { + Map timestamps = new HashMap<>(); + timestamps.put( + "2018-03-01T10:11:12.999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999000000)); + timestamps.put("2018-10-28T02:00:00+02:00", Timestamp.ofTimeSecondsAndNanos(1540684800L, 0)); + timestamps.put("2018-10-28T03:00:00+01:00", Timestamp.ofTimeSecondsAndNanos(1540692000L, 0)); + timestamps.put( + "2018-01-01T00:00:00.000000001Z", Timestamp.ofTimeSecondsAndNanos(1514764800L, 1)); + timestamps.put("2018-10-28T02:00:00Z", Timestamp.ofTimeSecondsAndNanos(1540692000L, 0)); + timestamps.put( + "2018-12-31T23:59:59.999999999Z", Timestamp.ofTimeSecondsAndNanos(1546300799L, 999999999)); + timestamps.put( + "2018-03-01T10:11:12.9999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999900000)); + timestamps.put( + "2018-03-01T10:11:12.000000001Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 1)); + timestamps.put( + "2018-03-01T10:11:12.100000000Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000000)); + timestamps.put( + "2018-03-01T10:11:12.100000001Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000001)); + timestamps.put("2018-03-01T10:11:12-10:00", Timestamp.ofTimeSecondsAndNanos(1519935072L, 0)); + timestamps.put( + "2018-03-01T10:11:12.999999999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999999999)); + timestamps.put("2018-03-01T10:11:12-12:00", Timestamp.ofTimeSecondsAndNanos(1519942272L, 0)); + timestamps.put("2018-10-28T03:00:00Z", Timestamp.ofTimeSecondsAndNanos(1540695600L, 0)); + timestamps.put("2018-10-28T02:30:00Z", Timestamp.ofTimeSecondsAndNanos(1540693800L, 0)); + timestamps.put( + "2018-03-01T10:11:12.123Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 123000000)); + timestamps.put("2018-10-28T02:30:00+02:00", Timestamp.ofTimeSecondsAndNanos(1540686600L, 0)); + timestamps.put( + "2018-03-01T10:11:12.123456789Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 123456789)); + timestamps.put( + "2018-03-01T10:11:12.1000Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000000)); + + for (Entry ts : timestamps.entrySet()) { + Timestamp gTimestamp = parseRfc3339(ts.getKey()); + assertThat( + "Seconds for timestamp " + ts + " do not match", + gTimestamp.getSeconds(), + is(equalTo(ts.getValue().getSeconds()))); + assertThat( + "Nanos for timestamp " + ts + " do not match", + gTimestamp.getNanos(), + is(equalTo(ts.getValue().getNanos()))); + } + } + + @Test + public void testParseTimeUnit() { + assertThat(parseTimeUnit("s"), is(equalTo(TimeUnit.SECONDS))); + assertThat(parseTimeUnit("ms"), is(equalTo(TimeUnit.MILLISECONDS))); + assertThat(parseTimeUnit("us"), is(equalTo(TimeUnit.MICROSECONDS))); + assertThat(parseTimeUnit("ns"), is(equalTo(TimeUnit.NANOSECONDS))); + } + + @Test + public void testGetTimeUnitAbbreviation() { + assertThat(getTimeUnitAbbreviation(TimeUnit.SECONDS), is(equalTo("s"))); + assertThat(getTimeUnitAbbreviation(TimeUnit.MILLISECONDS), is(equalTo("ms"))); + assertThat(getTimeUnitAbbreviation(TimeUnit.MICROSECONDS), is(equalTo("us"))); + assertThat(getTimeUnitAbbreviation(TimeUnit.NANOSECONDS), is(equalTo("ns"))); + + List supportedTimeUnits = + Arrays.asList( + TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS); + for (TimeUnit unit : TimeUnit.values()) { + if (supportedTimeUnits.contains(unit)) { + assertThat(getTimeUnitAbbreviation(unit), is(notNullValue())); + } else { + String value = null; + try { + value = getTimeUnitAbbreviation(unit); + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.INVALID_ARGUMENT) { + value = "unsupported"; + } + } + assertThat(value, is(equalTo("unsupported"))); + } + } + } + + @Test + public void testStalenessToString() { + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(10L, TimeUnit.NANOSECONDS))), + is(equalTo("10ns"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(1000L, TimeUnit.NANOSECONDS))), + is(equalTo("1us"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(100000L, TimeUnit.NANOSECONDS))), + is(equalTo("100us"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(999999L, TimeUnit.NANOSECONDS))), + is(equalTo("999999ns"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(1L, TimeUnit.SECONDS))), + is(equalTo("1s"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(1000L, TimeUnit.MILLISECONDS))), + is(equalTo("1s"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(1001L, TimeUnit.MILLISECONDS))), + is(equalTo("1001ms"))); + assertThat( + durationToString( + new ReadOnlyStalenessUtil.MaxStalenessGetter( + TimestampBound.ofMaxStaleness(1000000000L, TimeUnit.NANOSECONDS))), + is(equalTo("1s"))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java new file mode 100644 index 000000000000..fe7622d934c8 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java @@ -0,0 +1,403 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.Options.ReadOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; +import com.google.spanner.v1.ResultSetStats; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ReadOnlyTransactionTest { + @Rule public ExpectedException exception = ExpectedException.none(); + + private static final class SimpleReadOnlyTransaction + implements com.google.cloud.spanner.ReadOnlyTransaction { + private Timestamp readTimestamp = null; + private final TimestampBound staleness; + + private SimpleReadOnlyTransaction(TimestampBound staleness) { + this.staleness = staleness; + } + + @Override + public ResultSet read( + String table, KeySet keys, Iterable columns, ReadOption... options) { + return null; + } + + @Override + public ResultSet readUsingIndex( + String table, String index, KeySet keys, Iterable columns, ReadOption... options) { + return null; + } + + @Override + public Struct readRow(String table, Key key, Iterable columns) { + return null; + } + + @Override + public Struct readRowUsingIndex(String table, String index, Key key, Iterable columns) { + return null; + } + + @Override + public ResultSet executeQuery(Statement statement, QueryOption... options) { + if (readTimestamp == null) { + switch (staleness.getMode()) { + case STRONG: + readTimestamp = Timestamp.now(); + break; + case READ_TIMESTAMP: + readTimestamp = staleness.getReadTimestamp(); + break; + case MIN_READ_TIMESTAMP: + readTimestamp = staleness.getMinReadTimestamp(); + break; + case EXACT_STALENESS: + Calendar cal = Calendar.getInstance(); + cal.add( + Calendar.MILLISECOND, (int) -staleness.getExactStaleness(TimeUnit.MILLISECONDS)); + readTimestamp = Timestamp.of(cal.getTime()); + break; + case MAX_STALENESS: + cal = Calendar.getInstance(); + cal.add(Calendar.MILLISECOND, (int) -staleness.getMaxStaleness(TimeUnit.MILLISECONDS)); + readTimestamp = Timestamp.of(cal.getTime()); + break; + default: + throw new IllegalStateException(); + } + } + return mock(ResultSet.class); + } + + @Override + public ResultSet analyzeQuery(Statement statement, QueryAnalyzeMode queryMode) { + ResultSet res = executeQuery(statement); + when(res.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); + return res; + } + + @Override + public void close() {} + + @Override + public Timestamp getReadTimestamp() { + return readTimestamp; + } + } + + private ReadOnlyTransaction createSubject() { + return createSubject(TimestampBound.strong()); + } + + private ReadOnlyTransaction createSubject(TimestampBound staleness) { + DatabaseClient client = mock(DatabaseClient.class); + when(client.readOnlyTransaction(staleness)) + .thenReturn(new SimpleReadOnlyTransaction(staleness)); + return ReadOnlyTransaction.newBuilder() + .setDatabaseClient(client) + .setReadOnlyStaleness(staleness) + .withStatementExecutor(new StatementExecutor()) + .build(); + } + + @Test + public void testExecuteDdl() { + ParsedStatement ddl = mock(ParsedStatement.class); + when(ddl.getType()).thenReturn(StatementType.DDL); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + createSubject().executeDdl(ddl); + } + + @Test + public void testExecuteUpdate() { + ParsedStatement update = mock(ParsedStatement.class); + when(update.getType()).thenReturn(StatementType.UPDATE); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + createSubject().executeUpdate(update); + } + + @Test + public void testWrite() { + Mutation mutation = Mutation.newInsertBuilder("foo").build(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + createSubject().write(mutation); + } + + @Test + public void testWriteIterable() { + Mutation mutation = Mutation.newInsertBuilder("foo").build(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + createSubject().write(Arrays.asList(mutation, mutation)); + } + + @Test + public void testRunBatch() { + ReadOnlyTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.runBatch(); + } + + @Test + public void testAbortBatch() { + ReadOnlyTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.abortBatch(); + } + + @Test + public void testGetCommitTimestamp() { + ReadOnlyTransaction transaction = createSubject(); + transaction.commit(); + assertThat(transaction.getState(), is(UnitOfWorkState.COMMITTED)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + transaction.getCommitTimestamp(); + } + + @Test + public void testIsReadOnly() { + assertThat(createSubject().isReadOnly(), is(true)); + } + + @Test + public void testExecuteQuery() { + for (TimestampBound staleness : getTestTimestampBounds()) { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + + ReadOnlyTransaction transaction = createSubject(staleness); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.NONE); + assertThat(rs, is(notNullValue())); + assertThat(rs.getStats(), is(nullValue())); + } + } + + @Test + public void testExecuteQueryWithOptionsTest() { + String sql = "SELECT * FROM FOO"; + QueryOption option = Options.prefetchChunks(10000); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of(sql); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + DatabaseClient client = mock(DatabaseClient.class); + com.google.cloud.spanner.ReadOnlyTransaction tx = + mock(com.google.cloud.spanner.ReadOnlyTransaction.class); + ResultSet resWithOptions = mock(ResultSet.class); + ResultSet resWithoutOptions = mock(ResultSet.class); + when(tx.executeQuery(Statement.of(sql), option)).thenReturn(resWithOptions); + when(tx.executeQuery(Statement.of(sql))).thenReturn(resWithoutOptions); + when(client.readOnlyTransaction(TimestampBound.strong())).thenReturn(tx); + + ReadOnlyTransaction transaction = + ReadOnlyTransaction.newBuilder() + .setDatabaseClient(client) + .setReadOnlyStaleness(TimestampBound.strong()) + .withStatementExecutor(new StatementExecutor()) + .build(); + ResultSet expectedWithOptions = DirectExecuteResultSet.ofResultSet(resWithOptions); + assertThat( + transaction.executeQuery(parsedStatement, AnalyzeMode.NONE, option), + is(equalTo(expectedWithOptions))); + ResultSet expectedWithoutOptions = DirectExecuteResultSet.ofResultSet(resWithoutOptions); + assertThat( + transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), + is(equalTo(expectedWithoutOptions))); + } + + @Test + public void testPlanQuery() { + for (TimestampBound staleness : getTestTimestampBounds()) { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + + ReadOnlyTransaction transaction = createSubject(staleness); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PLAN); + assertThat(rs, is(notNullValue())); + // get all results and then get the stats + while (rs.next()) { + // do nothing + } + assertThat(rs.getStats(), is(notNullValue())); + } + } + + @Test + public void testProfileQuery() { + for (TimestampBound staleness : getTestTimestampBounds()) { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + + ReadOnlyTransaction transaction = createSubject(staleness); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PROFILE); + assertThat(rs, is(notNullValue())); + // get all results and then get the stats + while (rs.next()) { + // do nothing + } + assertThat(rs.getStats(), is(notNullValue())); + } + } + + @Test + public void testGetReadTimestamp() { + for (TimestampBound staleness : getTestTimestampBounds()) { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + + ReadOnlyTransaction transaction = createSubject(staleness); + boolean expectedException = false; + try { + transaction.getReadTimestamp(); + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION) { + expectedException = true; + } + } + assertThat(expectedException, is(true)); + assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); + assertThat(transaction.getReadTimestamp(), is(notNullValue())); + } + } + + private List getTestTimestampBounds() { + return Arrays.asList( + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(Timestamp.now()), + TimestampBound.ofMinReadTimestamp(Timestamp.now()), + TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), + TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)); + } + + @Test + public void testState() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + + ReadOnlyTransaction transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + transaction.commit(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); + assertThat(transaction.isActive(), is(false)); + + transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + + transaction.commit(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); + assertThat(transaction.isActive(), is(false)); + + // start a new transaction + transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + transaction.rollback(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); + assertThat(transaction.isActive(), is(false)); + + transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + transaction.rollback(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); + assertThat(transaction.isActive(), is(false)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java new file mode 100644 index 000000000000..f64ff464d487 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java @@ -0,0 +1,581 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionManager.TransactionState; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.spanner.v1.ResultSetStats; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.ExecutionException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class ReadWriteTransactionTest { + + @Rule public final ExpectedException exception = ExpectedException.none(); + + private enum CommitBehavior { + SUCCEED, + FAIL, + ABORT; + } + + private static class SimpleTransactionManager implements TransactionManager { + private TransactionState state; + private Timestamp commitTimestamp; + private TransactionContext txContext; + private CommitBehavior commitBehavior; + + private SimpleTransactionManager(TransactionContext txContext, CommitBehavior commitBehavior) { + this.txContext = txContext; + this.commitBehavior = commitBehavior; + } + + @Override + public TransactionContext begin() { + state = TransactionState.STARTED; + return txContext; + } + + @Override + public void commit() { + switch (commitBehavior) { + case SUCCEED: + commitTimestamp = Timestamp.now(); + state = TransactionState.COMMITTED; + break; + case FAIL: + state = TransactionState.COMMIT_FAILED; + throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "commit failed"); + case ABORT: + state = TransactionState.COMMIT_FAILED; + commitBehavior = CommitBehavior.SUCCEED; + throw SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted"); + default: + throw new IllegalStateException(); + } + } + + @Override + public void rollback() { + state = TransactionState.ROLLED_BACK; + } + + @Override + public TransactionContext resetForRetry() { + return txContext; + } + + @Override + public Timestamp getCommitTimestamp() { + return commitTimestamp; + } + + @Override + public TransactionState getState() { + return state; + } + + @Override + public void close() { + if (state != TransactionState.COMMITTED) { + state = TransactionState.ROLLED_BACK; + } + } + } + + private ReadWriteTransaction createSubject() { + return createSubject(CommitBehavior.SUCCEED, false); + } + + private ReadWriteTransaction createSubject(CommitBehavior commitBehavior) { + return createSubject(commitBehavior, false); + } + + private ReadWriteTransaction createSubject( + final CommitBehavior commitBehavior, boolean withRetry) { + DatabaseClient client = mock(DatabaseClient.class); + when(client.transactionManager()) + .thenAnswer( + new Answer() { + @Override + public TransactionManager answer(InvocationOnMock invocation) throws Throwable { + TransactionContext txContext = mock(TransactionContext.class); + when(txContext.executeQuery(any(Statement.class))) + .thenReturn(mock(ResultSet.class)); + ResultSet rsWithStats = mock(ResultSet.class); + when(rsWithStats.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); + when(txContext.analyzeQuery(any(Statement.class), any(QueryAnalyzeMode.class))) + .thenReturn(rsWithStats); + when(txContext.executeUpdate(any(Statement.class))).thenReturn(1L); + return new SimpleTransactionManager(txContext, commitBehavior); + } + }); + return ReadWriteTransaction.newBuilder() + .setDatabaseClient(client) + .setRetryAbortsInternally(withRetry) + .setTransactionRetryListeners(Collections.emptyList()) + .withStatementExecutor(new StatementExecutor()) + .build(); + } + + @Test + public void testExecuteDdl() { + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.DDL); + + ReadWriteTransaction transaction = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + transaction.executeDdl(statement); + } + + @Test + public void testRunBatch() { + ReadWriteTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.runBatch(); + } + + @Test + public void testAbortBatch() { + ReadWriteTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.abortBatch(); + } + + @Test + public void testExecuteQuery() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.NONE); + assertThat(rs, is(notNullValue())); + assertThat(rs.getStats(), is(nullValue())); + } + + @Test + public void testPlanQuery() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PLAN); + assertThat(rs, is(notNullValue())); + while (rs.next()) { + // do nothing + } + assertThat(rs.getStats(), is(notNullValue())); + } + + @Test + public void testProfileQuery() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PROFILE); + assertThat(rs, is(notNullValue())); + while (rs.next()) { + // do nothing + } + assertThat(rs.getStats(), is(notNullValue())); + } + + @Test + public void testExecuteUpdate() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); + when(parsedStatement.isUpdate()).thenReturn(true); + Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + assertThat(transaction.executeUpdate(parsedStatement), is(1L)); + } + + @Test + public void testGetCommitTimestampBeforeCommit() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); + when(parsedStatement.isUpdate()).thenReturn(true); + Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + assertThat(transaction.executeUpdate(parsedStatement), is(1L)); + + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + transaction.getCommitTimestamp(); + } + + @Test + public void testGetCommitTimestampAfterCommit() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); + when(parsedStatement.isUpdate()).thenReturn(true); + Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + assertThat(transaction.executeUpdate(parsedStatement), is(1L)); + transaction.commit(); + + assertThat(transaction.getCommitTimestamp(), is(notNullValue())); + } + + @Test + public void testGetReadTimestamp() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); + + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + transaction.getReadTimestamp(); + } + + @Test + public void testState() { + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + + ReadWriteTransaction transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + + transaction.commit(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); + assertThat(transaction.isActive(), is(false)); + + // start a new transaction + transaction = createSubject(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + transaction.rollback(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); + assertThat(transaction.isActive(), is(false)); + + // start a new transaction that will fail on commit + transaction = createSubject(CommitBehavior.FAIL); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + try { + transaction.commit(); + } catch (SpannerException e) { + // ignore + } + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED))); + assertThat(transaction.isActive(), is(false)); + + // start a new transaction that will abort on commit + transaction = createSubject(CommitBehavior.ABORT); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + try { + transaction.commit(); + } catch (AbortedException e) { + // ignore + } + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED))); + assertThat(transaction.isActive(), is(false)); + + // Start a new transaction that will abort on commit, but with internal retry enabled, so it + // will in the end succeed. + transaction = createSubject(CommitBehavior.ABORT, true); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); + assertThat(transaction.isActive(), is(true)); + transaction.commit(); + assertThat( + transaction.getState(), + is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); + assertThat(transaction.isActive(), is(false)); + } + + @Test + public void testIsReadOnly() { + assertThat(createSubject().isReadOnly(), is(false)); + } + + private enum RetryResults { + SAME, + DIFFERENT; + } + + @Test + public void testRetry() { + for (RetryResults results : RetryResults.values()) { + String sql1 = "UPDATE FOO SET BAR=1 WHERE BAZ>=100 AND BAZ<200"; + String sql2 = "UPDATE FOO SET BAR=2 WHERE BAZ>=200 AND BAZ<300"; + DatabaseClient client = mock(DatabaseClient.class); + ParsedStatement update1 = mock(ParsedStatement.class); + when(update1.getType()).thenReturn(StatementType.UPDATE); + when(update1.isUpdate()).thenReturn(true); + when(update1.getStatement()).thenReturn(Statement.of(sql1)); + ParsedStatement update2 = mock(ParsedStatement.class); + when(update2.getType()).thenReturn(StatementType.UPDATE); + when(update2.isUpdate()).thenReturn(true); + when(update2.getStatement()).thenReturn(Statement.of(sql2)); + + TransactionManager txManager = mock(TransactionManager.class); + TransactionContext txContext1 = mock(TransactionContext.class); + when(txManager.begin()).thenReturn(txContext1); + when(txManager.getState()).thenReturn(null, TransactionState.STARTED); + when(client.transactionManager()).thenReturn(txManager); + when(txContext1.executeUpdate(Statement.of(sql1))).thenReturn(90L); + when(txContext1.executeUpdate(Statement.of(sql2))).thenReturn(80L); + + TransactionContext txContext2 = mock(TransactionContext.class); + when(txManager.resetForRetry()).thenReturn(txContext2); + when(client.transactionManager()).thenReturn(txManager); + if (results == RetryResults.SAME) { + when(txContext2.executeUpdate(Statement.of(sql1))).thenReturn(90L); + when(txContext2.executeUpdate(Statement.of(sql2))).thenReturn(80L); + } else if (results == RetryResults.DIFFERENT) { + when(txContext2.executeUpdate(Statement.of(sql1))).thenReturn(90L); + when(txContext2.executeUpdate(Statement.of(sql2))).thenReturn(90L); + } + + // first abort, then do nothing + doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted")) + .doNothing() + .when(txManager) + .commit(); + + ReadWriteTransaction subject = + ReadWriteTransaction.newBuilder() + .setRetryAbortsInternally(true) + .setTransactionRetryListeners(Collections.emptyList()) + .setDatabaseClient(client) + .withStatementExecutor(new StatementExecutor()) + .build(); + subject.executeUpdate(update1); + subject.executeUpdate(update2); + boolean expectedException = false; + try { + subject.commit(); + } catch (SpannerException e) { + if (results == RetryResults.DIFFERENT && e.getErrorCode() == ErrorCode.ABORTED) { + // expected + expectedException = true; + } else { + throw e; + } + } + assertThat(expectedException, is(results == RetryResults.DIFFERENT)); + } + } + + @Test + public void testChecksumResultSet() throws InterruptedException, ExecutionException { + DatabaseClient client = mock(DatabaseClient.class); + ReadWriteTransaction transaction = + ReadWriteTransaction.newBuilder() + .setRetryAbortsInternally(true) + .setTransactionRetryListeners(Collections.emptyList()) + .setDatabaseClient(client) + .withStatementExecutor(new StatementExecutor()) + .build(); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + ResultSet delegate1 = + ResultSets.forRows( + Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), + Arrays.asList( + Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), + Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build())); + ChecksumResultSet rs1 = + transaction.createChecksumResultSet(delegate1, parsedStatement, AnalyzeMode.NONE); + ResultSet delegate2 = + ResultSets.forRows( + Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), + Arrays.asList( + Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), + Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build())); + ChecksumResultSet rs2 = + transaction.createChecksumResultSet(delegate2, parsedStatement, AnalyzeMode.NONE); + // rs1 and rs2 are equal, rs3 contains the same rows, but in a different order + ResultSet delegate3 = + ResultSets.forRows( + Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), + Arrays.asList( + Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build(), + Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build())); + ChecksumResultSet rs3 = + transaction.createChecksumResultSet(delegate3, parsedStatement, AnalyzeMode.NONE); + + // rs4 contains the same rows as rs1 and rs2, but also an additional row + ResultSet delegate4 = + ResultSets.forRows( + Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), + Arrays.asList( + Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), + Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build(), + Struct.newBuilder().set("ID").to(3l).set("NAME").to("TEST 3").build())); + ChecksumResultSet rs4 = + transaction.createChecksumResultSet(delegate4, parsedStatement, AnalyzeMode.NONE); + + assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); + while (rs1.next() && rs2.next() && rs3.next() && rs4.next()) { + assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); + assertThat(rs1.getChecksum(), is(not(equalTo(rs3.getChecksum())))); + assertThat(rs1.getChecksum(), is(equalTo(rs4.getChecksum()))); + } + assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); + assertThat(rs1.getChecksum(), is(not(equalTo(rs3.getChecksum())))); + // rs4 contains one more row than rs1, but the last row of rs4 hasn't been consumed yet + assertThat(rs1.getChecksum(), is(equalTo(rs4.getChecksum()))); + assertThat(rs4.next(), is(true)); + assertThat(rs1.getChecksum(), is(not(equalTo(rs4.getChecksum())))); + } + + @Test + public void testChecksumResultSetWithArray() throws InterruptedException, ExecutionException { + DatabaseClient client = mock(DatabaseClient.class); + ReadWriteTransaction transaction = + ReadWriteTransaction.newBuilder() + .setRetryAbortsInternally(true) + .setTransactionRetryListeners(Collections.emptyList()) + .setDatabaseClient(client) + .withStatementExecutor(new StatementExecutor()) + .build(); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + Statement statement = Statement.of("SELECT * FROM FOO"); + when(parsedStatement.getStatement()).thenReturn(statement); + ResultSet delegate1 = + ResultSets.forRows( + Type.struct( + StructField.of("ID", Type.int64()), + StructField.of("PRICES", Type.array(Type.int64()))), + Arrays.asList( + Struct.newBuilder() + .set("ID") + .to(1l) + .set("PRICES") + .toInt64Array(new long[] {1L, 2L}) + .build(), + Struct.newBuilder() + .set("ID") + .to(2l) + .set("PRICES") + .toInt64Array(new long[] {3L, 4L}) + .build())); + ChecksumResultSet rs1 = + transaction.createChecksumResultSet(delegate1, parsedStatement, AnalyzeMode.NONE); + ResultSet delegate2 = + ResultSets.forRows( + Type.struct( + StructField.of("ID", Type.int64()), + StructField.of("PRICES", Type.array(Type.int64()))), + Arrays.asList( + Struct.newBuilder() + .set("ID") + .to(1l) + .set("PRICES") + .toInt64Array(new long[] {1L, 2L}) + .build(), + Struct.newBuilder() + .set("ID") + .to(2l) + .set("PRICES") + .toInt64Array(new long[] {3L, 5L}) + .build())); + ChecksumResultSet rs2 = + transaction.createChecksumResultSet(delegate2, parsedStatement, AnalyzeMode.NONE); + + rs1.next(); + rs2.next(); + assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); + rs1.next(); + rs2.next(); + assertThat(rs1.getChecksum(), is(not(equalTo(rs2.getChecksum())))); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java new file mode 100644 index 000000000000..52c2f2600ba7 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java @@ -0,0 +1,310 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ReplaceableForwardingResultSetTest { + + private ReplaceableForwardingResultSet createSubject() { + ResultSet delegate = + ResultSets.forRows( + Type.struct(StructField.of("test", Type.int64())), + Arrays.asList(Struct.newBuilder().set("test").to(1L).build())); + return new ReplaceableForwardingResultSet(delegate); + } + + @Test + public void testReplace() { + ResultSet delegate1 = + ResultSets.forRows( + Type.struct(StructField.of("test", Type.int64())), + Arrays.asList( + Struct.newBuilder().set("test").to(1L).build(), + Struct.newBuilder().set("test").to(2L).build())); + // First verify the behavior without replacing. + try (ResultSet rs = new ReplaceableForwardingResultSet(delegate1)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("test"), is(equalTo(1L))); + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("test"), is(equalTo(2L))); + assertThat(rs.next(), is(false)); + } + + delegate1 = + ResultSets.forRows( + Type.struct(StructField.of("test", Type.int64())), + Arrays.asList( + Struct.newBuilder().set("test").to(1L).build(), + Struct.newBuilder().set("test").to(2L).build())); + ResultSet delegate2 = + ResultSets.forRows( + Type.struct(StructField.of("test", Type.int64())), + Arrays.asList( + Struct.newBuilder().set("test").to(1L).build(), + Struct.newBuilder().set("test").to(3L).build())); + // Then verify the behavior with replacing. + try (ReplaceableForwardingResultSet rs = new ReplaceableForwardingResultSet(delegate1)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("test"), is(equalTo(1L))); + // Advance the delegate result set that will be used as replacement. + delegate2.next(); + // Replace the result set. + rs.replaceDelegate(delegate2); + // Verify that the replacement is being used. + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("test"), is(equalTo(3L))); + assertThat(rs.next(), is(false)); + } + } + + @Test + public void testMethodCallBeforeNext() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = Arrays.asList("getStats", "next", "close", "equals", "hashCode"); + ReplaceableForwardingResultSet subject = createSubject(); + // Test that all methods throw an IllegalStateException except the excluded methods when called + // before a call to ResultSet#next(). + callMethods(subject, excludedMethods, IllegalStateException.class); + } + + @Test + public void testMethodCallAfterClose() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = + Arrays.asList( + "getStats", + "next", + "close", + "getType", + "getColumnCount", + "getColumnIndex", + "getColumnType", + "ofResultSet", + "equals", + "hashCode"); + ReplaceableForwardingResultSet subject = createSubject(); + subject.next(); + subject.close(); + // Test that all methods throw an SpannerException except the excluded methods when called on a + // closed ResultSet. + callMethods(subject, excludedMethods, SpannerException.class); + } + + @Test + public void testMethodCallAfterNextHasReturnedFalse() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + List excludedMethods = + Arrays.asList( + "getStats", + "next", + "close", + "getType", + "getColumnCount", + "getColumnIndex", + "getColumnType", + "ofResultSet", + "equals", + "hashCode"); + ReplaceableForwardingResultSet subject = createSubject(); + subject.next(); + subject.next(); + // Test that all methods throw an IndexOutOfBoundsException except the excluded methods when + // called after a call to ResultSet#next() has returned false. + callMethods(subject, excludedMethods, IndexOutOfBoundsException.class); + } + + private void callMethods( + ReplaceableForwardingResultSet subject, + List excludedMethods, + Class expectedException) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + for (Method method : ReplaceableForwardingResultSet.class.getDeclaredMethods()) { + if (Modifier.isPublic(method.getModifiers()) && !excludedMethods.contains(method.getName())) { + boolean exception = false; + int numberOfParameters = method.getParameterTypes().length; + Class firstParameterType = null; + if (numberOfParameters == 1) { + firstParameterType = method.getParameterTypes()[0]; + } + try { + switch (numberOfParameters) { + case 0: + method.invoke(subject); + break; + case 1: + if (firstParameterType == String.class) { + method.invoke(subject, "test"); + } else if (firstParameterType == int.class) { + method.invoke(subject, 0); + } else { + fail("unknown parameter type"); + } + break; + default: + fail("method with more than 1 parameter is unknown"); + } + } catch (InvocationTargetException e) { + if (e.getCause().getClass().equals(expectedException)) { + // expected + exception = true; + } else { + throw e; + } + } + assertThat( + method.getName() + " did not throw an IllegalStateException", exception, is(true)); + } + } + } + + @Test + public void testValidMethodCall() + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + ResultSet delegate = mock(ResultSet.class); + when(delegate.next()).thenReturn(true, true, false); + try (ReplaceableForwardingResultSet subject = new ReplaceableForwardingResultSet(delegate)) { + subject.next(); + + // Cloud Spanner result sets use zero-based column indices, as opposed to the one-based column + // indices used by JDBC. The subject.getBoolean(0) and further zero-based calls below should + // therefore not cause any exceptions. + subject.getBoolean(0); + verify(delegate).getBoolean(0); + subject.getBoolean("test0"); + verify(delegate).getBoolean("test0"); + subject.getBooleanArray(1); + verify(delegate).getBooleanArray(1); + subject.getBooleanArray("test1"); + verify(delegate).getBooleanArray("test1"); + subject.getBooleanList(2); + verify(delegate).getBooleanList(2); + subject.getBooleanList("test2"); + verify(delegate).getBooleanList("test2"); + + subject.getBytes(0); + verify(delegate).getBytes(0); + subject.getBytes("test0"); + verify(delegate).getBytes("test0"); + subject.getBytesList(2); + verify(delegate).getBytesList(2); + subject.getBytesList("test2"); + verify(delegate).getBytesList("test2"); + + subject.getDate(0); + verify(delegate).getDate(0); + subject.getDate("test0"); + verify(delegate).getDate("test0"); + subject.getDateList(2); + verify(delegate).getDateList(2); + subject.getDateList("test2"); + verify(delegate).getDateList("test2"); + + subject.getDouble(0); + verify(delegate).getDouble(0); + subject.getDouble("test0"); + verify(delegate).getDouble("test0"); + subject.getDoubleArray(1); + verify(delegate).getDoubleArray(1); + subject.getDoubleArray("test1"); + verify(delegate).getDoubleArray("test1"); + subject.getDoubleList(2); + verify(delegate).getDoubleList(2); + subject.getDoubleList("test2"); + verify(delegate).getDoubleList("test2"); + + subject.getLong(0); + verify(delegate).getLong(0); + subject.getLong("test0"); + verify(delegate).getLong("test0"); + subject.getLongArray(1); + verify(delegate).getLongArray(1); + subject.getLongArray("test1"); + verify(delegate).getLongArray("test1"); + subject.getLongList(2); + verify(delegate).getLongList(2); + subject.getLongList("test2"); + verify(delegate).getLongList("test2"); + + subject.getString(0); + verify(delegate).getString(0); + subject.getString("test0"); + verify(delegate).getString("test0"); + subject.getStringList(2); + verify(delegate).getStringList(2); + subject.getStringList("test2"); + verify(delegate).getStringList("test2"); + + subject.getStructList(0); + subject.getStructList("test0"); + + subject.getTimestamp(0); + verify(delegate).getTimestamp(0); + subject.getTimestamp("test0"); + verify(delegate).getTimestamp("test0"); + subject.getTimestampList(2); + verify(delegate).getTimestampList(2); + subject.getTimestampList("test2"); + verify(delegate).getTimestampList("test2"); + + subject.getColumnCount(); + verify(delegate).getColumnCount(); + subject.getColumnIndex("test"); + verify(delegate).getColumnIndex("test"); + subject.getColumnType(100); + verify(delegate).getColumnType(100); + subject.getColumnType("test"); + verify(delegate).getColumnType("test"); + subject.getCurrentRowAsStruct(); + verify(delegate).getCurrentRowAsStruct(); + subject.getType(); + verify(delegate).getType(); + subject.isNull(50); + verify(delegate).isNull(50); + subject.isNull("test"); + verify(delegate).isNull("test"); + + while (subject.next()) { + // ignore + } + subject.getStats(); + verify(delegate).getStats(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java new file mode 100644 index 000000000000..43cf113ccee5 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2019 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.NoCredentials; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class SetReadOnlyStalenessSqlScriptTest { + + static class TestConnectionProvider implements GenericConnectionProvider { + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of( + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build())); + } + } + + @Test + public void testSetReadOnlyStalenessScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile("SetReadOnlyStalenessTest.sql", getClass(), false); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java new file mode 100644 index 000000000000..594e5772911d --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class SetStatementTimeoutSqlScriptTest { + + static class TestConnectionProvider implements GenericConnectionProvider { + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of( + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder().setUri(ConnectionImplTest.URI).build())); + } + } + + @Test + public void testSetStatementTimeoutScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + verifier.verifyStatementsInFile("SetStatementTimeoutTest.sql", getClass(), false); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java new file mode 100644 index 000000000000..b9890c5d4d36 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java @@ -0,0 +1,740 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.Options.ReadOption; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionRunner; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import com.google.cloud.spanner.jdbc.StatementParser.StatementType; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.v1.ResultSetStats; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class SingleUseTransactionTest { + private static final String VALID_QUERY = "SELECT * FROM FOO"; + private static final String INVALID_QUERY = "SELECT * FROM BAR"; + private static final String SLOW_QUERY = "SELECT * FROM SLOW_TABLE"; + private static final String VALID_UPDATE = "UPDATE FOO SET BAR=1"; + private static final String INVALID_UPDATE = "UPDATE BAR SET FOO=1"; + private static final String SLOW_UPDATE = "UPDATE SLOW_TABLE SET FOO=1"; + private static final long VALID_UPDATE_COUNT = 99L; + + @Rule public ExpectedException exception = ExpectedException.none(); + + private final StatementExecutor executor = new StatementExecutor(); + + private enum CommitBehavior { + SUCCEED, + FAIL, + ABORT; + } + + private static class SimpleTransactionManager implements TransactionManager { + private TransactionState state; + private Timestamp commitTimestamp; + private TransactionContext txContext; + private CommitBehavior commitBehavior; + + private SimpleTransactionManager(TransactionContext txContext, CommitBehavior commitBehavior) { + this.txContext = txContext; + this.commitBehavior = commitBehavior; + } + + @Override + public TransactionContext begin() { + state = TransactionState.STARTED; + return txContext; + } + + @Override + public void commit() { + switch (commitBehavior) { + case SUCCEED: + commitTimestamp = Timestamp.now(); + state = TransactionState.COMMITTED; + break; + case FAIL: + state = TransactionState.COMMIT_FAILED; + throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "commit failed"); + case ABORT: + state = TransactionState.COMMIT_FAILED; + commitBehavior = CommitBehavior.SUCCEED; + throw SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted"); + default: + throw new IllegalStateException(); + } + } + + @Override + public void rollback() { + state = TransactionState.ROLLED_BACK; + } + + @Override + public TransactionContext resetForRetry() { + return txContext; + } + + @Override + public Timestamp getCommitTimestamp() { + return commitTimestamp; + } + + @Override + public TransactionState getState() { + return state; + } + + @Override + public void close() { + if (state != TransactionState.COMMITTED) { + state = TransactionState.ROLLED_BACK; + } + } + } + + private static final class SimpleReadOnlyTransaction + implements com.google.cloud.spanner.ReadOnlyTransaction { + private Timestamp readTimestamp = null; + private final TimestampBound staleness; + + private SimpleReadOnlyTransaction(TimestampBound staleness) { + this.staleness = staleness; + } + + @Override + public ResultSet read( + String table, KeySet keys, Iterable columns, ReadOption... options) { + return null; + } + + @Override + public ResultSet readUsingIndex( + String table, String index, KeySet keys, Iterable columns, ReadOption... options) { + return null; + } + + @Override + public Struct readRow(String table, Key key, Iterable columns) { + return null; + } + + @Override + public Struct readRowUsingIndex(String table, String index, Key key, Iterable columns) { + return null; + } + + @Override + public ResultSet executeQuery(Statement statement, QueryOption... options) { + if (statement.equals(Statement.of(VALID_QUERY))) { + if (readTimestamp == null) { + switch (staleness.getMode()) { + case STRONG: + readTimestamp = Timestamp.now(); + break; + case READ_TIMESTAMP: + readTimestamp = staleness.getReadTimestamp(); + break; + case MIN_READ_TIMESTAMP: + readTimestamp = staleness.getMinReadTimestamp(); + break; + case EXACT_STALENESS: + Calendar cal = Calendar.getInstance(); + cal.add( + Calendar.MILLISECOND, (int) -staleness.getExactStaleness(TimeUnit.MILLISECONDS)); + readTimestamp = Timestamp.of(cal.getTime()); + break; + case MAX_STALENESS: + cal = Calendar.getInstance(); + cal.add( + Calendar.MILLISECOND, (int) -staleness.getMaxStaleness(TimeUnit.MILLISECONDS)); + readTimestamp = Timestamp.of(cal.getTime()); + break; + default: + throw new IllegalStateException(); + } + } + return mock(ResultSet.class); + } else if (statement.equals(Statement.of(SLOW_QUERY))) { + try { + Thread.sleep(10L); + } catch (InterruptedException e) { + // ignore + } + readTimestamp = Timestamp.now(); + return mock(ResultSet.class); + } else if (statement.equals(Statement.of(INVALID_QUERY))) { + throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid query"); + } else { + throw new IllegalArgumentException(); + } + } + + @Override + public ResultSet analyzeQuery(Statement statement, QueryAnalyzeMode queryMode) { + ResultSet rs = executeQuery(statement); + when(rs.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); + return rs; + } + + @Override + public void close() {} + + @Override + public Timestamp getReadTimestamp() { + return readTimestamp; + } + } + + private DdlClient createDefaultMockDdlClient() { + try { + DdlClient ddlClient = mock(DdlClient.class); + @SuppressWarnings("unchecked") + final OperationFuture operation = + mock(OperationFuture.class); + when(operation.get()).thenReturn(null); + when(ddlClient.executeDdl(anyString())).thenCallRealMethod(); + when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); + return ddlClient; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private SingleUseTransaction createSubject() { + return createSubject( + createDefaultMockDdlClient(), + false, + TimestampBound.strong(), + AutocommitDmlMode.TRANSACTIONAL, + CommitBehavior.SUCCEED, + 0L); + } + + private SingleUseTransaction createSubjectWithTimeout(long timeout) { + return createSubject( + createDefaultMockDdlClient(), + false, + TimestampBound.strong(), + AutocommitDmlMode.TRANSACTIONAL, + CommitBehavior.SUCCEED, + timeout); + } + + private SingleUseTransaction createSubject(AutocommitDmlMode dmlMode) { + return createSubject( + createDefaultMockDdlClient(), + false, + TimestampBound.strong(), + dmlMode, + CommitBehavior.SUCCEED, + 0L); + } + + private SingleUseTransaction createSubject(CommitBehavior commitBehavior) { + return createSubject( + createDefaultMockDdlClient(), + false, + TimestampBound.strong(), + AutocommitDmlMode.TRANSACTIONAL, + commitBehavior, + 0L); + } + + private SingleUseTransaction createDdlSubject(DdlClient ddlClient) { + return createSubject( + ddlClient, + false, + TimestampBound.strong(), + AutocommitDmlMode.TRANSACTIONAL, + CommitBehavior.SUCCEED, + 0L); + } + + private SingleUseTransaction createReadOnlySubject(TimestampBound staleness) { + return createSubject( + createDefaultMockDdlClient(), + true, + staleness, + AutocommitDmlMode.TRANSACTIONAL, + CommitBehavior.SUCCEED, + 0L); + } + + private SingleUseTransaction createSubject( + DdlClient ddlClient, + boolean readOnly, + TimestampBound staleness, + AutocommitDmlMode dmlMode, + final CommitBehavior commitBehavior, + long timeout) { + DatabaseClient dbClient = mock(DatabaseClient.class); + com.google.cloud.spanner.ReadOnlyTransaction singleUse = + new SimpleReadOnlyTransaction(staleness); + when(dbClient.singleUseReadOnlyTransaction(staleness)).thenReturn(singleUse); + + TransactionContext txContext = mock(TransactionContext.class); + when(txContext.executeUpdate(Statement.of(VALID_UPDATE))).thenReturn(VALID_UPDATE_COUNT); + when(txContext.executeUpdate(Statement.of(SLOW_UPDATE))) + .thenAnswer( + new Answer() { + @Override + public Long answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(10L); + return VALID_UPDATE_COUNT; + } + }); + when(txContext.executeUpdate(Statement.of(INVALID_UPDATE))) + .thenThrow( + SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update")); + SimpleTransactionManager txManager = new SimpleTransactionManager(txContext, commitBehavior); + when(dbClient.transactionManager()).thenReturn(txManager); + + when(dbClient.executePartitionedUpdate(Statement.of(VALID_UPDATE))) + .thenReturn(VALID_UPDATE_COUNT); + when(dbClient.executePartitionedUpdate(Statement.of(INVALID_UPDATE))) + .thenThrow( + SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update")); + + when(dbClient.readWriteTransaction()) + .thenAnswer( + new Answer() { + @Override + public TransactionRunner answer(InvocationOnMock invocation) throws Throwable { + TransactionRunner runner = + new TransactionRunner() { + private Timestamp commitTimestamp; + + @SuppressWarnings("unchecked") + @Override + public T run(TransactionCallable callable) { + if (commitBehavior == CommitBehavior.SUCCEED) { + this.commitTimestamp = Timestamp.now(); + return (T) Long.valueOf(1L); + } else if (commitBehavior == CommitBehavior.FAIL) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.UNKNOWN, "commit failed"); + } else { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.ABORTED, "commit aborted"); + } + } + + @Override + public Timestamp getCommitTimestamp() { + if (commitTimestamp == null) { + throw new IllegalStateException("no commit timestamp"); + } + return commitTimestamp; + } + + @Override + public TransactionRunner allowNestedTransaction() { + return this; + } + }; + return runner; + } + }); + + return SingleUseTransaction.newBuilder() + .setDatabaseClient(dbClient) + .setDdlClient(ddlClient) + .setAutocommitDmlMode(dmlMode) + .setReadOnly(readOnly) + .setReadOnlyStaleness(staleness) + .setStatementTimeout( + timeout == 0L + ? StatementExecutor.StatementTimeout.nullTimeout() + : StatementExecutor.StatementTimeout.of(timeout, TimeUnit.MILLISECONDS)) + .withStatementExecutor(executor) + .build(); + } + + private ParsedStatement createParsedDdl(String sql) { + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.DDL); + when(statement.getStatement()).thenReturn(Statement.of(sql)); + when(statement.getSqlWithoutComments()).thenReturn(sql); + return statement; + } + + private ParsedStatement createParsedQuery(String sql) { + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.QUERY); + when(statement.isQuery()).thenReturn(true); + when(statement.getStatement()).thenReturn(Statement.of(sql)); + return statement; + } + + private ParsedStatement createParsedUpdate(String sql) { + ParsedStatement statement = mock(ParsedStatement.class); + when(statement.getType()).thenReturn(StatementType.UPDATE); + when(statement.isUpdate()).thenReturn(true); + when(statement.getStatement()).thenReturn(Statement.of(sql)); + return statement; + } + + private List getTestTimestampBounds() { + return Arrays.asList( + TimestampBound.strong(), + TimestampBound.ofReadTimestamp(Timestamp.now()), + TimestampBound.ofMinReadTimestamp(Timestamp.now()), + TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), + TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)); + } + + @Test + public void testCommit() { + SingleUseTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.commit(); + } + + @Test + public void testRollback() { + SingleUseTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.rollback(); + } + + @Test + public void testRunBatch() { + SingleUseTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.runBatch(); + } + + @Test + public void testAbortBatch() { + SingleUseTransaction subject = createSubject(); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.abortBatch(); + } + + @Test + public void testExecuteDdl() { + String sql = "CREATE TABLE FOO"; + ParsedStatement ddl = createParsedDdl(sql); + DdlClient ddlClient = createDefaultMockDdlClient(); + SingleUseTransaction subject = createDdlSubject(ddlClient); + subject.executeDdl(ddl); + verify(ddlClient).executeDdl(sql); + } + + @Test + public void testExecuteQuery() { + for (TimestampBound staleness : getTestTimestampBounds()) { + for (AnalyzeMode analyzeMode : AnalyzeMode.values()) { + SingleUseTransaction subject = createReadOnlySubject(staleness); + ResultSet rs = subject.executeQuery(createParsedQuery(VALID_QUERY), analyzeMode); + assertThat(rs, is(notNullValue())); + assertThat(subject.getReadTimestamp(), is(notNullValue())); + assertThat( + subject.getState(), + is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + while (rs.next()) { + // just loop to the end to get stats + } + if (analyzeMode == AnalyzeMode.NONE) { + assertThat(rs.getStats(), is(nullValue())); + } else { + assertThat(rs.getStats(), is(notNullValue())); + } + } + } + for (TimestampBound staleness : getTestTimestampBounds()) { + SingleUseTransaction subject = createReadOnlySubject(staleness); + boolean expectedException = false; + try { + subject.executeQuery(createParsedQuery(INVALID_QUERY), AnalyzeMode.NONE); + } catch (SpannerException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat( + subject.getState(), + is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); + } + } + + @Test + public void testExecuteQueryWithOptionsTest() { + String sql = "SELECT * FROM FOO"; + QueryOption option = Options.prefetchChunks(10000); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getType()).thenReturn(StatementType.QUERY); + when(parsedStatement.isQuery()).thenReturn(true); + Statement statement = Statement.of(sql); + when(parsedStatement.getStatement()).thenReturn(statement); + DatabaseClient client = mock(DatabaseClient.class); + com.google.cloud.spanner.ReadOnlyTransaction tx = + mock(com.google.cloud.spanner.ReadOnlyTransaction.class); + when(tx.executeQuery(Statement.of(sql), option)).thenReturn(mock(ResultSet.class)); + when(client.singleUseReadOnlyTransaction(TimestampBound.strong())).thenReturn(tx); + + SingleUseTransaction transaction = + SingleUseTransaction.newBuilder() + .setDatabaseClient(client) + .setDdlClient(mock(DdlClient.class)) + .setAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL) + .withStatementExecutor(executor) + .setReadOnlyStaleness(TimestampBound.strong()) + .build(); + assertThat( + transaction.executeQuery(parsedStatement, AnalyzeMode.NONE, option), is(notNullValue())); + } + + @Test + public void testExecuteUpdate_Transactional_Valid() { + ParsedStatement update = createParsedUpdate(VALID_UPDATE); + SingleUseTransaction subject = createSubject(); + long updateCount = subject.executeUpdate(update); + assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + assertThat( + subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + } + + @Test + public void testExecuteUpdate_Transactional_Invalid() { + ParsedStatement update = createParsedUpdate(INVALID_UPDATE); + SingleUseTransaction subject = createSubject(); + exception.expect( + SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "invalid update")); + subject.executeUpdate(update); + } + + @Test + public void testExecuteUpdate_Transactional_Valid_FailedCommit() { + ParsedStatement update = createParsedUpdate(VALID_UPDATE); + SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); + exception.expect( + SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); + subject.executeUpdate(update); + } + + @Test + public void testExecuteUpdate_Transactional_Valid_AbortedCommit() { + ParsedStatement update = createParsedUpdate(VALID_UPDATE); + SingleUseTransaction subject = createSubject(CommitBehavior.ABORT); + // even though the transaction aborts at first, it will be retried and eventually succeed + long updateCount = subject.executeUpdate(update); + assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + assertThat( + subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + } + + @Test + public void testExecuteUpdate_Partitioned_Valid() { + ParsedStatement update = createParsedUpdate(VALID_UPDATE); + SingleUseTransaction subject = createSubject(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + long updateCount = subject.executeUpdate(update); + assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); + assertThat( + subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + } + + @Test + public void testExecuteUpdate_Partitioned_Invalid() { + ParsedStatement update = createParsedUpdate(INVALID_UPDATE); + SingleUseTransaction subject = createSubject(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + exception.expect( + SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "invalid update")); + subject.executeUpdate(update); + } + + @Test + public void testWrite() { + SingleUseTransaction subject = createSubject(); + subject.write(Mutation.newInsertBuilder("FOO").build()); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + assertThat( + subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + } + + @Test + public void testWriteFail() { + SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); + exception.expect( + SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); + subject.write(Mutation.newInsertBuilder("FOO").build()); + } + + @Test + public void testWriteIterable() { + SingleUseTransaction subject = createSubject(); + Mutation mutation = Mutation.newInsertBuilder("FOO").build(); + subject.write(Arrays.asList(mutation, mutation)); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + assertThat( + subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); + } + + @Test + public void testWriteIterableFail() { + SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); + Mutation mutation = Mutation.newInsertBuilder("FOO").build(); + exception.expect( + SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); + subject.write(Arrays.asList(mutation, mutation)); + } + + @Test + public void testMultiUse() { + for (TimestampBound staleness : getTestTimestampBounds()) { + SingleUseTransaction subject = createReadOnlySubject(staleness); + ResultSet rs = subject.executeQuery(createParsedQuery(VALID_QUERY), AnalyzeMode.NONE); + assertThat(rs, is(notNullValue())); + assertThat(subject.getReadTimestamp(), is(notNullValue())); + boolean expectedException = false; + try { + subject.executeQuery(createParsedQuery(VALID_QUERY), AnalyzeMode.NONE); + } catch (IllegalStateException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + } + + String sql = "CREATE TABLE FOO"; + ParsedStatement ddl = createParsedDdl(sql); + DdlClient ddlClient = createDefaultMockDdlClient(); + SingleUseTransaction subject = createDdlSubject(ddlClient); + subject.executeDdl(ddl); + verify(ddlClient).executeDdl(sql); + boolean expectedException = false; + try { + subject.executeDdl(ddl); + } catch (IllegalStateException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + + ParsedStatement update = createParsedUpdate(VALID_UPDATE); + subject = createSubject(); + long updateCount = subject.executeUpdate(update); + assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + expectedException = false; + try { + subject.executeUpdate(update); + } catch (IllegalStateException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + + subject = createSubject(); + subject.write(Mutation.newInsertBuilder("FOO").build()); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + expectedException = false; + try { + subject.write(Mutation.newInsertBuilder("FOO").build()); + } catch (IllegalStateException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + + subject = createSubject(); + Mutation mutation = Mutation.newInsertBuilder("FOO").build(); + subject.write(Arrays.asList(mutation, mutation)); + assertThat(subject.getCommitTimestamp(), is(notNullValue())); + expectedException = false; + try { + subject.write(Arrays.asList(mutation, mutation)); + } catch (IllegalStateException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + } + + @Test + public void testExecuteQueryWithTimeout() { + SingleUseTransaction subject = createSubjectWithTimeout(1L); + try { + subject.executeQuery(createParsedQuery(SLOW_QUERY), AnalyzeMode.NONE); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { + throw e; + } + } + assertThat( + subject.getState(), + is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getReadTimestamp(); + } + + @Test + public void testExecuteUpdateWithTimeout() { + SingleUseTransaction subject = createSubjectWithTimeout(1L); + boolean timeoutException = false; + try { + subject.executeUpdate(createParsedUpdate(SLOW_UPDATE)); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { + throw e; + } + timeoutException = true; + } + assertThat(timeoutException, is(true)); + assertThat( + subject.getState(), + is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getCommitTimestamp(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java new file mode 100644 index 000000000000..81cb883201e2 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 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.ErrorCode; +import com.google.cloud.spanner.SpannerException; +import com.google.common.base.Preconditions; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +public final class SpannerExceptionMatcher extends BaseMatcher { + private final ErrorCode errorCode; + private final String message; + + public static SpannerExceptionMatcher matchCode(ErrorCode errorCode) { + Preconditions.checkNotNull(errorCode); + return new SpannerExceptionMatcher(errorCode, null); + } + + public static SpannerExceptionMatcher matchCodeAndMessage(ErrorCode errorCode, String message) { + Preconditions.checkNotNull(errorCode); + Preconditions.checkNotNull(message); + return new SpannerExceptionMatcher(errorCode, message); + } + + private SpannerExceptionMatcher(ErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } + + @Override + public boolean matches(Object item) { + if (item instanceof SpannerException) { + SpannerException exception = (SpannerException) item; + if (message == null) { + return exception.getErrorCode().equals(errorCode); + } + return exception.getErrorCode().equals(errorCode) + && exception.getMessage().equals(errorCode.name() + ": " + message); + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText(SpannerException.class.getName() + " with code " + errorCode.name()); + if (message != null) { + description.appendText(" - " + SpannerException.class.getName() + " with message " + message); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java new file mode 100644 index 000000000000..5a1663c871b6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java @@ -0,0 +1,70 @@ +/* + * Copyright 2019 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.common.base.Preconditions; +import io.grpc.Status.Code; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +public final class SpannerJdbcExceptionMatcher extends BaseMatcher { + private final Class exceptionClass; + private final Code errorCode; + private final String message; + + public static SpannerJdbcExceptionMatcher matchCode( + Class exceptionClass, Code errorCode) { + Preconditions.checkNotNull(exceptionClass); + Preconditions.checkNotNull(errorCode); + return new SpannerJdbcExceptionMatcher(exceptionClass, errorCode, null); + } + + public static SpannerJdbcExceptionMatcher matchCodeAndMessage( + Class exceptionClass, Code errorCode, String message) { + Preconditions.checkNotNull(exceptionClass); + Preconditions.checkNotNull(errorCode); + Preconditions.checkNotNull(message); + return new SpannerJdbcExceptionMatcher(exceptionClass, errorCode, message); + } + + private SpannerJdbcExceptionMatcher(Class exceptionClass, Code errorCode, String message) { + this.exceptionClass = exceptionClass; + this.errorCode = errorCode; + this.message = message; + } + + @Override + public boolean matches(Object item) { + if (exceptionClass.isAssignableFrom(item.getClass())) { + JdbcSqlException exception = (JdbcSqlException) item; + if (message == null) { + return exception.getErrorCode() == errorCode.value(); + } + return exception.getErrorCode() == errorCode.value() + && exception.getMessage().endsWith(": " + message); + } + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText(exceptionClass.getName() + " with code " + errorCode.name()); + if (message != null) { + description.appendText(" - " + JdbcSqlException.class.getName() + " with message " + message); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java new file mode 100644 index 000000000000..a4b8e37240ed --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java @@ -0,0 +1,400 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.jdbc.ConnectionImpl.LeakedConnectionException; +import com.google.cloud.spanner.jdbc.SpannerPool.CheckAndCloseSpannersMode; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.logging.Handler; +import java.util.logging.Logger; +import java.util.logging.StreamHandler; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class SpannerPoolTest { + private static final String URI = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + private ConnectionImpl connection1 = mock(ConnectionImpl.class); + private ConnectionImpl connection2 = mock(ConnectionImpl.class); + private ConnectionImpl connection3 = mock(ConnectionImpl.class); + private GoogleCredentials credentials1 = mock(GoogleCredentials.class); + private GoogleCredentials credentials2 = mock(GoogleCredentials.class); + private ConnectionOptions options1 = mock(ConnectionOptions.class); + private ConnectionOptions options2 = mock(ConnectionOptions.class); + private ConnectionOptions options3 = mock(ConnectionOptions.class); + private ConnectionOptions options4 = mock(ConnectionOptions.class); + + private SpannerPool createSubjectAndMocks() { + return createSubjectAndMocks(0L); + } + + private SpannerPool createSubjectAndMocks(long closeSpannerAfterMillisecondsUnused) { + SpannerPool pool = + new SpannerPool(closeSpannerAfterMillisecondsUnused) { + @Override + Spanner createSpanner(SpannerPoolKey key) { + return mock(Spanner.class); + } + }; + + when(options1.getCredentials()).thenReturn(credentials1); + when(options1.getProjectId()).thenReturn("test-project-1"); + when(options2.getCredentials()).thenReturn(credentials2); + when(options2.getProjectId()).thenReturn("test-project-1"); + + when(options3.getCredentials()).thenReturn(credentials1); + when(options3.getProjectId()).thenReturn("test-project-2"); + when(options4.getCredentials()).thenReturn(credentials2); + when(options4.getProjectId()).thenReturn("test-project-2"); + + return pool; + } + + @AfterClass + public static void closeSpannerPool() { + SpannerPool.closeSpannerPool(); + } + + @Test + public void testGetSpanner() { + SpannerPool pool = createSubjectAndMocks(); + Spanner spanner1; + Spanner spanner2; + + // assert equal + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options1, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + spanner1 = pool.getSpanner(options2, connection1); + spanner2 = pool.getSpanner(options2, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + spanner1 = pool.getSpanner(options3, connection1); + spanner2 = pool.getSpanner(options3, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + spanner1 = pool.getSpanner(options4, connection1); + spanner2 = pool.getSpanner(options4, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + + // assert not equal + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options2, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options3, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options4, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + spanner1 = pool.getSpanner(options2, connection1); + spanner2 = pool.getSpanner(options3, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + spanner1 = pool.getSpanner(options2, connection1); + spanner2 = pool.getSpanner(options4, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + spanner1 = pool.getSpanner(options3, connection1); + spanner2 = pool.getSpanner(options4, connection2); + assertThat(spanner1, not(equalTo(spanner2))); + } + + @Test + public void testRemoveConnection() { + SpannerPool pool = createSubjectAndMocks(); + Spanner spanner1; + Spanner spanner2; + + // assert equal + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options1, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + // one connection removed, assert that we would still get the same Spanner + pool.removeConnection(options1, connection1); + spanner1 = pool.getSpanner(options1, connection1); + assertThat(spanner1, is(equalTo(spanner2))); + // remove two connections, assert that we would still get the same Spanner, as Spanners are not + // directly closed and removed. + pool.removeConnection(options1, connection1); + pool.removeConnection(options1, connection2); + spanner1 = pool.getSpanner(options1, connection1); + assertThat(spanner1, is(equalTo(spanner2))); + // remove the last connection again + pool.removeConnection(options1, connection1); + } + + private static Logger log = Logger.getLogger(SpannerPool.class.getName()); + private static OutputStream logCapturingStream; + private static StreamHandler customLogHandler; + + private void attachLogCapturer() { + logCapturingStream = new ByteArrayOutputStream(); + Logger currentLogger = log; + Handler[] handlers = new Handler[0]; + while (handlers.length == 0 && currentLogger != null) { + handlers = currentLogger.getHandlers(); + currentLogger = currentLogger.getParent(); + } + if (handlers.length == 0) { + throw new IllegalStateException("no handlers found for logger"); + } + customLogHandler = new StreamHandler(logCapturingStream, handlers[0].getFormatter()); + log.addHandler(customLogHandler); + } + + public String getTestCapturedLog() throws IOException { + customLogHandler.flush(); + return logCapturingStream.toString(); + } + + @Test + public void testRemoveConnectionOptionsNotRegistered() throws IOException { + attachLogCapturer(); + final String expectedLogPart = "There is no Spanner registered for ConnectionOptions"; + SpannerPool pool = createSubjectAndMocks(); + pool.getSpanner(options1, connection1); + pool.removeConnection(options2, connection1); + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog.contains(expectedLogPart), is(true)); + } + + @Test + public void testRemoveConnectionConnectionNotRegistered() throws IOException { + attachLogCapturer(); + final String expectedLogPart = "There are no connections registered for ConnectionOptions"; + SpannerPool pool = createSubjectAndMocks(); + pool.getSpanner(options1, connection1); + pool.removeConnection(options1, connection2); + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog.contains(expectedLogPart), is(true)); + } + + @Test + public void testRemoveConnectionConnectionAlreadyRemoved() throws IOException { + attachLogCapturer(); + final String expectedLogPart = "There are no connections registered for ConnectionOptions"; + SpannerPool pool = createSubjectAndMocks(); + pool.getSpanner(options1, connection1); + pool.removeConnection(options1, connection1); + pool.removeConnection(options1, connection1); + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog.contains(expectedLogPart), is(true)); + } + + @Test + public void testCloseSpanner() throws IOException { + SpannerPool pool = createSubjectAndMocks(); + Spanner spanner = pool.getSpanner(options1, connection1); + // verify that closing is not possible until all connections have been removed + boolean exception = false; + try { + pool.checkAndCloseSpanners(); + } catch (SpannerException e) { + exception = e.getErrorCode() == ErrorCode.FAILED_PRECONDITION; + } + assertThat(exception, is(true)); + + // remove the connection and verify that it is possible to close + pool.removeConnection(options1, connection1); + pool.checkAndCloseSpanners(); + verify(spanner).close(); + + final String expectedLogPart = + "WARNING: There is/are 1 connection(s) still open. Close all connections before stopping the application"; + Spanner spanner2 = pool.getSpanner(options1, connection1); + pool.checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog.contains(expectedLogPart), is(true)); + verify(spanner2, never()).close(); + + // remove the connection and verify that it is possible to close + pool.removeConnection(options1, connection1); + pool.checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); + verify(spanner2).close(); + } + + @Test + public void testLeakedConnection() throws IOException { + ConnectionOptions options = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(); + // create an actual connection object but not in a try-with-resources block + Connection connection = options.getConnection(); + // try to close the application which should fail + try { + ConnectionOptions.closeSpanner(); + fail("missing expected exception"); + } catch (SpannerException e) { + assertThat(e.getErrorCode(), is(equalTo(ErrorCode.FAILED_PRECONDITION))); + } + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog.contains(LeakedConnectionException.class.getName()), is(true)); + assertThat(capturedLog.contains("testLeakedConnection"), is(true)); + // Now close the connection to avoid trouble with other test cases. + connection.close(); + } + + @Test + public void testCloseUnusedSpanners() { + SpannerPool pool = createSubjectAndMocks(); + Spanner spanner1; + Spanner spanner2; + Spanner spanner3; + + // create two connections that use the same Spanner + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options1, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + + // all spanners are in use, this should have no effect + pool.closeUnusedSpanners(-1L); + verify(spanner1, never()).close(); + + // close one connection. This should also have no effect. + pool.removeConnection(options1, connection1); + pool.closeUnusedSpanners(-1L); + verify(spanner1, never()).close(); + + // close the other connection as well, the Spanner object should now be closed. + pool.removeConnection(options1, connection2); + pool.closeUnusedSpanners(-1L); + verify(spanner1).close(); + + // create three connections that use two different Spanners + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options2, connection2); + spanner3 = pool.getSpanner(options2, connection3); + assertThat(spanner1, not(equalTo(spanner2))); + assertThat(spanner2, is(equalTo(spanner3))); + + // all spanners are in use, this should have no effect + pool.closeUnusedSpanners(-1L); + verify(spanner1, never()).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection1. That should also mark spanner1 as no longer in use + pool.removeConnection(options1, connection1); + pool.closeUnusedSpanners(-1L); + verify(spanner1).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection2. That should have no effect, as connection3 is still using spanner2 + pool.removeConnection(options2, connection2); + pool.closeUnusedSpanners(-1L); + verify(spanner1).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection3. Now all should be closed. + pool.removeConnection(options2, connection3); + pool.closeUnusedSpanners(-1L); + verify(spanner1).close(); + verify(spanner2).close(); + verify(spanner3).close(); + } + + /** Allow the automatic close test to be run multiple times to ensure it is stable */ + private static final int NUMBER_OF_AUTOMATIC_CLOSE_TEST_RUNS = 1; + + private static final long TEST_AUTOMATIC_CLOSE_TIMEOUT = 2L; + private static final long SLEEP_BEFORE_VERIFICATION = 100L; + + @Test + public void testAutomaticCloser() throws InterruptedException { + for (int testRun = 0; testRun < NUMBER_OF_AUTOMATIC_CLOSE_TEST_RUNS; testRun++) { + // create a pool that will close unused spanners after 5 milliseconds + SpannerPool pool = createSubjectAndMocks(TEST_AUTOMATIC_CLOSE_TIMEOUT); + Spanner spanner1; + Spanner spanner2; + Spanner spanner3; + + // create two connections that use the same Spanner + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options1, connection2); + assertThat(spanner1, is(equalTo(spanner2))); + + // all spanners are in use, this should have no effect + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1, never()).close(); + + // close one connection. This should also have no effect. + pool.removeConnection(options1, connection1); + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1, never()).close(); + + // close the other connection as well, the Spanner object should now be closed. + pool.removeConnection(options1, connection2); + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1).close(); + + // create three connections that use two different Spanners + spanner1 = pool.getSpanner(options1, connection1); + spanner2 = pool.getSpanner(options2, connection2); + spanner3 = pool.getSpanner(options2, connection3); + assertThat(spanner1, not(equalTo(spanner2))); + assertThat(spanner2, is(equalTo(spanner3))); + + // all spanners are in use, this should have no effect + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1, never()).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection1. That should also mark spanner1 as no longer in use + pool.removeConnection(options1, connection1); + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection2. That should have no effect, as connection3 is still using spanner2 + pool.removeConnection(options2, connection2); + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1).close(); + verify(spanner2, never()).close(); + verify(spanner3, never()).close(); + + // close connection3. Now all should be closed. + pool.removeConnection(options2, connection3); + Thread.sleep(SLEEP_BEFORE_VERIFICATION); + verify(spanner1).close(); + verify(spanner2).close(); + verify(spanner3).close(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java new file mode 100644 index 000000000000..c32f39076578 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java @@ -0,0 +1,185 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; + +/** + * SQL script verifier implementation for Spanner {@link com.google.cloud.spanner.jdbc.Connection} + * + * @see AbstractSqlScriptVerifier for more information + */ +public class SqlScriptVerifier extends AbstractSqlScriptVerifier { + + static class ConnectionGenericStatementResult extends GenericStatementResult { + private final StatementResult result; + + private ConnectionGenericStatementResult(StatementResult result) { + this.result = result; + } + + @Override + protected ResultType getResultType() { + return result.getResultType(); + } + + @Override + protected GenericResultSet getResultSet() { + return new ConnectionGenericResultSet(result.getResultSet()); + } + + @Override + protected long getUpdateCount() { + return result.getUpdateCount(); + } + } + + static class ConnectionGenericResultSet extends GenericResultSet { + private final ResultSet resultSet; + + private ConnectionGenericResultSet(ResultSet resultSet) { + this.resultSet = resultSet; + } + + @Override + protected boolean next() { + return resultSet.next(); + } + + @Override + protected Object getValue(String col) { + if (resultSet.isNull(col)) { + return null; + } + Type type = resultSet.getColumnType(col); + switch (type.getCode()) { + case ARRAY: + return getArrayValue(resultSet, col, type.getArrayElementType()); + case BOOL: + return resultSet.getBoolean(col); + case BYTES: + return resultSet.getBytes(col); + case DATE: + return resultSet.getDate(col); + case FLOAT64: + return resultSet.getDouble(col); + case INT64: + return resultSet.getLong(col); + case STRING: + return resultSet.getString(col); + case TIMESTAMP: + return resultSet.getTimestamp(col); + case STRUCT: + throw new IllegalArgumentException("type struct not supported"); + } + throw new IllegalArgumentException("unknown type: " + type); + } + + private Object getArrayValue(ResultSet rs, String col, Type type) { + switch (type.getCode()) { + case BOOL: + return rs.getBooleanList(col); + case BYTES: + return rs.getBytesList(col); + case DATE: + return rs.getDateList(col); + case FLOAT64: + return rs.getDoubleList(col); + case INT64: + return rs.getLongList(col); + case STRING: + return rs.getStringList(col); + case STRUCT: + return rs.getStructList(col); + case TIMESTAMP: + return rs.getTimestampList(col); + case ARRAY: + throw new IllegalArgumentException("array of array not supported"); + } + throw new IllegalArgumentException("unknown type: " + type); + } + + @Override + protected int getColumnCount() throws Exception { + return resultSet.getColumnCount(); + } + + @Override + protected Object getFirstValue() throws Exception { + return getValue(resultSet.getType().getStructFields().get(0).getName()); + } + } + + public static class SpannerGenericConnection extends GenericConnection { + private final Connection connection; + + public static SpannerGenericConnection of(Connection connection) { + return new SpannerGenericConnection(connection); + } + + private SpannerGenericConnection(Connection connection) { + this.connection = connection; + } + + @Override + protected GenericStatementResult execute(String sql) { + return new ConnectionGenericStatementResult(connection.execute(Statement.of(sql))); + } + + @Override + public void close() throws Exception { + if (this.connection != null) { + this.connection.close(); + } + } + } + + public SqlScriptVerifier() { + this(null); + } + + public SqlScriptVerifier(GenericConnectionProvider provider) { + super(provider); + } + + @Override + protected void verifyExpectedException( + String statement, Exception e, String code, String messagePrefix) { + assertThat(e instanceof SpannerException, is(true)); + SpannerException spannerException = (SpannerException) e; + assertThat( + statement + " resulted in " + spannerException.toString(), + spannerException.getErrorCode(), + is(equalTo(ErrorCode.valueOf(code)))); + if (messagePrefix != null) { + assertThat( + statement, + e.getMessage(), + startsWith(messagePrefix.substring(1, messagePrefix.length() - 1))); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java new file mode 100644 index 000000000000..875ca0a08e48 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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; + +/** Class that runs all generators of SQL test scripts for the Connection API */ +public class SqlTestScriptsGenerator { + + /** Main method for generating the test script */ + public static void main(String[] args) throws Exception { + ClientSideStatementsTest.generateTestScript(); + ConnectionImplGeneratedSqlScriptTest.generateTestScript(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java new file mode 100644 index 000000000000..38def439eeea --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java @@ -0,0 +1,666 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.*; + +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.Test; + +public class StatementParserTest { + public static final String COPYRIGHT_PATTERN = + "\\/\\*\n" + + " \\* Copyright \\d{4} 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"; + private final StatementParser parser = StatementParser.INSTANCE; + private static final Pattern EXPECT_PATTERN = Pattern.compile("(?is)\\s*(?:@EXPECT)\\s+'(.*)'"); + + @Test + public void testRemoveComments() { + List statements = readStatementsFromFile("CommentsTest.sql"); + String currentlyExpected = ""; + for (String statement : statements) { + String sql = statement.trim(); + if (sql.startsWith("@EXPECT")) { + Matcher matcher = EXPECT_PATTERN.matcher(sql); + if (matcher.matches()) { + currentlyExpected = matcher.group(1); + } else { + throw new IllegalArgumentException("Unknown @EXPECT statement: " + sql); + } + } else { + assertThat( + StatementParser.removeCommentsAndTrim(statement), is(equalTo(currentlyExpected))); + } + } + + assertThat(StatementParser.removeCommentsAndTrim(""), is(equalTo(""))); + assertThat( + StatementParser.removeCommentsAndTrim("SELECT * FROM FOO"), + is(equalTo("SELECT * FROM FOO"))); + assertThat( + StatementParser.removeCommentsAndTrim("-- This is a one line comment\nSELECT * FROM FOO"), + is(equalTo("SELECT * FROM FOO"))); + assertThat( + StatementParser.removeCommentsAndTrim( + "/* This is a simple multi line comment */\nSELECT * FROM FOO"), + is(equalTo("SELECT * FROM FOO"))); + assertThat( + StatementParser.removeCommentsAndTrim( + "/* This is a \nmulti line comment */\nSELECT * FROM FOO"), + is(equalTo("SELECT * FROM FOO"))); + assertThat( + StatementParser.removeCommentsAndTrim( + "/* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO"), + is(equalTo("SELECT * FROM FOO"))); + } + + @Test + public void testStatementWithCommentContainingSlash() { + String sql = + "/*\n" + + " * Script for testing invalid/unrecognized statements\n" + + " */\n" + + "\n" + + "-- MERGE into test comment MERGE -- \n" + + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" + + "MERGE INTO wines w\n" + + "/*** test ****/" + + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" + + "ON v.column1 = w.winename\n" + + "WHEN NOT MATCHED \n" + + " INSERT VALUES(v.column1, v.column2)\n" + + "WHEN MATCHED\n" + + " UPDATE SET stock = stock + v.column2;\n"; + String sqlWithoutComments = + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" + + "MERGE INTO wines w\n" + + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" + + "ON v.column1 = w.winename\n" + + "WHEN NOT MATCHED \n" + + " INSERT VALUES(v.column1, v.column2)\n" + + "WHEN MATCHED\n" + + " UPDATE SET stock = stock + v.column2;"; + ParsedStatement statement = parser.parse(Statement.of(sql)); + assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); + } + + @Test + public void testStatementWithCommentContainingSlashAndNoAsteriskOnNewLine() { + String sql = + "/*\n" + + " * Script for testing invalid/unrecognized statements\n" + + " foo bar baz" + + " */\n" + + "\n" + + "-- MERGE INTO test comment MERGE\n" + + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" + + "MERGE INTO wines w\n" + + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" + + "ON v.column1 = w.winename\n" + + "-- test again --\n" + + "WHEN NOT MATCHED \n" + + " INSERT VALUES(v.column1, v.column2)\n" + + "WHEN MATCHED\n" + + " UPDATE SET stock = stock + v.column2;\n"; + String sqlWithoutComments = + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" + + "MERGE INTO wines w\n" + + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" + + "ON v.column1 = w.winename\n" + + "\nWHEN NOT MATCHED \n" + + " INSERT VALUES(v.column1, v.column2)\n" + + "WHEN MATCHED\n" + + " UPDATE SET stock = stock + v.column2;"; + ParsedStatement statement = parser.parse(Statement.of(sql)); + assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); + } + + @Test + public void testStatementWithHashTagSingleLineComment() { + assertThat( + parser + .parse(Statement.of("# this is a comment\nselect * from foo")) + .getSqlWithoutComments(), + is(equalTo("select * from foo"))); + assertThat( + parser.parse(Statement.of("select * from foo\n#this is a comment")).getSqlWithoutComments(), + is(equalTo("select * from foo"))); + assertThat( + parser + .parse(Statement.of("select *\nfrom foo # this is a comment\nwhere bar=1")) + .getSqlWithoutComments(), + is(equalTo("select *\nfrom foo \nwhere bar=1"))); + } + + @Test + public void testIsDdlStatement() { + assertFalse(parser.isDdlStatement("")); + assertFalse(parser.isDdlStatement("random text")); + assertFalse(parser.isDdlStatement("CREATETABLE")); + assertFalse(parser.isDdlStatement("CCREATE TABLE")); + assertFalse(parser.isDdlStatement("SELECT 1")); + assertFalse(parser.isDdlStatement("SELECT FOO FROM BAR")); + assertFalse(parser.isDdlStatement("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); + assertFalse(parser.isDdlStatement("UPDATE FOO SET NAME='NAME' WHERE ID=1")); + assertFalse(parser.isDdlStatement("DELETE FROM FOO")); + + assertTrue( + parser.isDdlStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertTrue(parser.isDdlStatement("alter table foo add Description string(100)")); + assertTrue(parser.isDdlStatement("drop table foo")); + assertTrue(parser.isDdlStatement("Create index BAR on foo (name)")); + + assertTrue( + parser + .parse( + Statement.of( + "\t\tCREATE\n\t TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "\n\n\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "-- this is a comment\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "-- SELECT in a single line comment \nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "/* SELECT in a multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + assertTrue( + parser + .parse( + Statement.of( + "/** SELECT in a java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()); + } + + @Test + public void testIsQuery() { + assertFalse(parser.isQuery("")); + assertFalse(parser.isQuery("random text")); + assertFalse(parser.isQuery("SELECT1")); + assertFalse(parser.isQuery("SSELECT 1")); + assertTrue(parser.isQuery("SELECT 1")); + assertTrue(parser.isQuery("select 1")); + assertTrue(parser.isQuery("SELECT foo FROM bar WHERE id=@id")); + assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); + assertFalse(parser.isQuery("UPDATE FOO SET NAME='NAME' WHERE ID=1")); + assertFalse(parser.isQuery("DELETE FROM FOO")); + assertFalse(parser.isQuery("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertFalse(parser.isQuery("alter table foo add Description string(100)")); + assertFalse(parser.isQuery("drop table foo")); + assertFalse(parser.isQuery("Create index BAR on foo (name)")); + assertTrue(parser.isQuery("select * from foo")); + assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); + + assertTrue(parser.parse(Statement.of("-- this is a comment\nselect * from foo")).isQuery()); + assertTrue( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nSELECT ID, NAME\nFROM\tTEST\n\tWHERE ID=1")) + .isQuery()); + assertTrue( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nselect max(id) from test")) + .isQuery()); + assertTrue( + parser.parse(Statement.of("-- INSERT in a single line comment \n select 1")).isQuery()); + assertTrue( + parser + .parse( + Statement.of( + "/* UPDATE in a multi line comment\n* with more information on the next line\n*/\nSELECT 1")) + .isQuery()); + assertTrue( + parser + .parse( + Statement.of( + "/** DELETE in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- UPDATE test\nSELECT 1")) + .isQuery()); + } + + @Test + public void testIsUpdate_InsertStatements() { + assertFalse(parser.isUpdateStatement("")); + assertFalse(parser.isUpdateStatement("random text")); + assertFalse(parser.isUpdateStatement("INSERTINTO FOO (ID) VALUES (1)")); + assertFalse(parser.isUpdateStatement("IINSERT INTO FOO (ID) VALUES (1)")); + assertTrue(parser.isUpdateStatement("INSERT INTO FOO (ID) VALUES (1)")); + assertTrue(parser.isUpdateStatement("insert into foo (id) values (1)")); + assertTrue(parser.isUpdateStatement("INSERT into Foo (id)\nSELECT id FROM bar WHERE id=@id")); + assertFalse(parser.isUpdateStatement("SELECT 1")); + assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); + assertFalse( + parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); + assertFalse(parser.isUpdateStatement("drop table foo")); + assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); + assertFalse(parser.isUpdateStatement("select * from foo")); + assertTrue(parser.isUpdateStatement("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); + assertTrue( + parser + .parse(Statement.of("-- this is a comment\ninsert into foo (id) values (1)")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nINSERT INTO FOO\n(ID)\tVALUES\n\t(1)")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nInsert intO foo (id) select 1")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "-- SELECT in a single line comment \n insert into foo (id) values (1)")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nINSERT INTO FOO (ID) VALUES (1)")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\ninsert into foo (id) values (1)")) + .isUpdate()); + } + + @Test + public void testIsUpdate_UpdateStatements() { + assertFalse(parser.isUpdateStatement("")); + assertFalse(parser.isUpdateStatement("random text")); + assertFalse(parser.isUpdateStatement("UPDATEFOO SET NAME='foo' WHERE ID=1")); + assertFalse(parser.isUpdateStatement("UUPDATE FOO SET NAME='foo' WHERE ID=1")); + assertTrue(parser.isUpdateStatement("UPDATE FOO SET NAME='foo' WHERE ID=1")); + assertTrue(parser.isUpdateStatement("update foo set name='foo' where id=1")); + assertTrue( + parser.isUpdateStatement("update foo set name=\n(SELECT name FROM bar WHERE id=@id)")); + assertFalse(parser.isUpdateStatement("SELECT 1")); + assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); + assertFalse( + parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); + assertFalse(parser.isUpdateStatement("drop table foo")); + assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); + assertFalse(parser.isUpdateStatement("select * from foo")); + assertTrue( + parser.isUpdateStatement( + "UPDATE FOO SET NAME=(SELECT NAME FROM FOO) WHERE ID=(SELECT ID+1 FROM FOO)")); + + assertTrue( + parser + .parse(Statement.of("-- this is a comment\nupdate foo set name='foo' where id=@id")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nUPDATE FOO\nSET NAME=\t'foo'\n\tWHERE ID=1")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nUPDATE FOO SET NAME=(select 'bar')")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of("-- SELECT in a single line comment \n update foo set name='bar'")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nUPDATE FOO SET NAME='BAR'")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\nupdate foo set bar='foo'")) + .isUpdate()); + } + + @Test + public void testIsUpdate_DeleteStatements() { + assertFalse(parser.isUpdateStatement("")); + assertFalse(parser.isUpdateStatement("random text")); + assertFalse(parser.isUpdateStatement("DELETEFROM FOO WHERE ID=1")); + assertFalse(parser.isUpdateStatement("DDELETE FROM FOO WHERE ID=1")); + assertTrue(parser.isUpdateStatement("DELETE FROM FOO WHERE ID=1")); + assertTrue(parser.isUpdateStatement("delete from foo where id=1")); + assertTrue( + parser.isUpdateStatement( + "delete from foo where name=\n(SELECT name FROM bar WHERE id=@id)")); + assertFalse(parser.isUpdateStatement("SELECT 1")); + assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); + assertFalse( + parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); + assertFalse(parser.isUpdateStatement("drop table foo")); + assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); + assertFalse(parser.isUpdateStatement("select * from foo")); + assertTrue( + parser.isUpdateStatement( + "UPDATE FOO SET NAME=(SELECT NAME FROM FOO) WHERE ID=(SELECT ID+1 FROM FOO)")); + + assertTrue( + parser + .parse(Statement.of("-- this is a comment\ndelete from foo where id=@id")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nDELETE FROM FOO\n\n\tWHERE ID=1")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nDELETE FROM FOO WHERE NAME=(select 'bar')")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "-- SELECT in a single line comment \n delete from foo where name='bar'")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nDELETE FROM FOO WHERE NAME='BAR'")) + .isUpdate()); + assertTrue( + parser + .parse( + Statement.of( + "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\ndelete from foo where bar='foo'")) + .isUpdate()); + } + + @Test + public void testParseStatementsWithNoParameters() throws CompileException { + for (ClientSideStatementImpl statement : getAllStatements()) { + if (statement.getSetStatement() == null) { + for (String testStatement : statement.getExampleStatements()) { + testParseStatement(testStatement, statement.getClass()); + } + } + } + } + + @Test + public void testParseStatementsWithOneParameterAtTheEnd() throws CompileException { + for (ClientSideStatementImpl statement : getAllStatements()) { + if (statement.getSetStatement() != null) { + for (String testStatement : statement.getExampleStatements()) { + testParseStatementWithOneParameterAtTheEnd(testStatement, statement.getClass()); + } + } + } + } + + private Set getAllStatements() throws CompileException { + return ClientSideStatements.INSTANCE.getCompiledStatements(); + } + + private void assertParsing( + String value, Class statementClass) { + assertThat(this.parse(value), is(equalTo(statementClass))); + } + + private void testParseStatement( + String statement, Class statementClass) { + assertThat( + "\"" + statement + "\" should be " + statementClass.getName(), + this.parse(statement), + is(equalTo(statementClass))); + assertParsing(upper(statement), statementClass); + assertParsing(lower(statement), statementClass); + assertParsing(withSpaces(statement), statementClass); + assertParsing(withTabs(statement), statementClass); + assertParsing(withLinefeeds(statement), statementClass); + assertParsing(withLeadingSpaces(statement), statementClass); + assertParsing(withLeadingTabs(statement), statementClass); + assertParsing(withLeadingLinefeeds(statement), statementClass); + assertParsing(withTrailingSpaces(statement), statementClass); + assertParsing(withTrailingTabs(statement), statementClass); + assertParsing(withTrailingLinefeeds(statement), statementClass); + + assertThat(parse(withInvalidPrefix(statement)), is(nullValue())); + assertThat(parse(withInvalidSuffix(statement)), is(nullValue())); + + assertNull(parse(withPrefix("%", statement))); + assertNull(parse(withPrefix("_", statement))); + assertNull(parse(withPrefix("&", statement))); + assertNull(parse(withPrefix("$", statement))); + assertNull(parse(withPrefix("@", statement))); + assertNull(parse(withPrefix("!", statement))); + assertNull(parse(withPrefix("*", statement))); + assertNull(parse(withPrefix("(", statement))); + assertNull(parse(withPrefix(")", statement))); + + assertThat( + withSuffix("%", statement) + " is not a valid statement", + parse(withSuffix("%", statement)), + is(nullValue())); + assertNull(parse(withSuffix("_", statement))); + assertNull(parse(withSuffix("&", statement))); + assertNull(parse(withSuffix("$", statement))); + assertNull(parse(withSuffix("@", statement))); + assertNull(parse(withSuffix("!", statement))); + assertNull(parse(withSuffix("*", statement))); + assertNull(parse(withSuffix("(", statement))); + assertNull(parse(withSuffix(")", statement))); + } + + private void testParseStatementWithOneParameterAtTheEnd( + String statement, Class statementClass) { + assertThat( + "\"" + statement + "\" should be " + statementClass.getName(), + this.parse(statement), + is(equalTo(statementClass))); + assertParsing(upper(statement), statementClass); + assertParsing(lower(statement), statementClass); + assertParsing(withSpaces(statement), statementClass); + assertParsing(withTabs(statement), statementClass); + assertParsing(withLinefeeds(statement), statementClass); + assertParsing(withLeadingSpaces(statement), statementClass); + assertParsing(withLeadingTabs(statement), statementClass); + assertParsing(withLeadingLinefeeds(statement), statementClass); + assertParsing(withTrailingSpaces(statement), statementClass); + assertParsing(withTrailingTabs(statement), statementClass); + assertParsing(withTrailingLinefeeds(statement), statementClass); + + assertNull(parse(withInvalidPrefix(statement))); + assertParsing(withInvalidSuffix(statement), statementClass); + + assertNull(parse(withPrefix("%", statement))); + assertNull(parse(withPrefix("_", statement))); + assertNull(parse(withPrefix("&", statement))); + assertNull(parse(withPrefix("$", statement))); + assertNull(parse(withPrefix("@", statement))); + assertNull(parse(withPrefix("!", statement))); + assertNull(parse(withPrefix("*", statement))); + assertNull(parse(withPrefix("(", statement))); + assertNull(parse(withPrefix(")", statement))); + + assertParsing(withSuffix("%", statement), statementClass); + assertParsing(withSuffix("_", statement), statementClass); + assertParsing(withSuffix("&", statement), statementClass); + assertParsing(withSuffix("$", statement), statementClass); + assertParsing(withSuffix("@", statement), statementClass); + assertParsing(withSuffix("!", statement), statementClass); + assertParsing(withSuffix("*", statement), statementClass); + assertParsing(withSuffix("(", statement), statementClass); + assertParsing(withSuffix(")", statement), statementClass); + } + + @SuppressWarnings("unchecked") + private Class parse(String statement) { + ClientSideStatementImpl optional = parser.parseClientSideStatement(statement); + return optional != null ? (Class) optional.getClass() : null; + } + + private String upper(String statement) { + return statement.toUpperCase(); + } + + private String lower(String statement) { + return statement.toLowerCase(); + } + + private String withLeadingSpaces(String statement) { + return " " + statement; + } + + private String withLeadingTabs(String statement) { + return "\t\t\t" + statement; + } + + private String withLeadingLinefeeds(String statement) { + return "\n\n\n" + statement; + } + + private String withTrailingSpaces(String statement) { + return statement + " "; + } + + private String withTrailingTabs(String statement) { + return statement + "\t\t"; + } + + private String withTrailingLinefeeds(String statement) { + return statement + "\n\n"; + } + + private String withSpaces(String statement) { + return statement.replaceAll(" ", " "); + } + + private String withTabs(String statement) { + return statement.replaceAll(" ", "\t"); + } + + private String withLinefeeds(String statement) { + return statement.replaceAll(" ", "\n"); + } + + private String withInvalidPrefix(String statement) { + return "foo " + statement; + } + + private String withInvalidSuffix(String statement) { + return statement + " bar"; + } + + private String withPrefix(String prefix, String statement) { + return prefix + statement; + } + + private String withSuffix(String suffix, String statement) { + return statement + suffix; + } + + private List readStatementsFromFile(String filename) { + File file = new File(getClass().getResource(filename).getFile()); + StringBuilder builder = new StringBuilder(); + try (Scanner scanner = new Scanner(file)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + builder.append(line).append("\n"); + } + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + String script = builder.toString().replaceAll(COPYRIGHT_PATTERN, ""); + String[] array = script.split(";"); + List res = new ArrayList<>(array.length); + for (String statement : array) { + if (statement != null && statement.trim().length() > 0) { + res.add(statement); + } + } + return res; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java new file mode 100644 index 000000000000..a9f06ce57160 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java @@ -0,0 +1,177 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType; +import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class StatementResultImplTest { + @Rule public ExpectedException exception = ExpectedException.none(); + + @Test + public void testNoResultGetResultSet() { + StatementResult subject = StatementResultImpl.noResult(); + assertThat(subject.getResultType(), is(equalTo(ResultType.NO_RESULT))); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getResultSet(); + } + + @Test + public void testNoResultGetUpdateCount() { + StatementResult subject = StatementResultImpl.noResult(); + assertThat(subject.getResultType(), is(equalTo(ResultType.NO_RESULT))); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getUpdateCount(); + } + + @Test + public void testResultSetGetResultSet() { + StatementResult subject = StatementResultImpl.of(mock(ResultSet.class)); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(subject.getResultSet(), is(notNullValue())); + } + + @Test + public void testResultSetGetUpdateCount() { + StatementResult subject = StatementResultImpl.of(mock(ResultSet.class)); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getUpdateCount(); + } + + @Test + public void testUpdateCountGetResultSet() { + StatementResult subject = StatementResultImpl.of(1L); + assertThat(subject.getResultType(), is(equalTo(ResultType.UPDATE_COUNT))); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + subject.getResultSet(); + } + + @Test + public void testUpdateCountGetUpdateCount() { + StatementResult subject = StatementResultImpl.of(1L); + assertThat(subject.getResultType(), is(equalTo(ResultType.UPDATE_COUNT))); + assertThat(subject.getUpdateCount(), is(notNullValue())); + } + + @Test + public void testBooleanResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet("foo", Boolean.TRUE, ClientSideStatementType.SHOW_AUTOCOMMIT); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), is(equalTo(ClientSideStatementType.SHOW_AUTOCOMMIT))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat(subject.getResultSet().getBoolean("foo"), is(true)); + assertThat(subject.getResultSet().next(), is(false)); + } + + @Test + public void testLongResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet("foo", 10L, ClientSideStatementType.SHOW_READ_ONLY_STALENESS); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), + is(equalTo(ClientSideStatementType.SHOW_READ_ONLY_STALENESS))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat(subject.getResultSet().getLong("foo"), is(equalTo(10L))); + assertThat(subject.getResultSet().next(), is(false)); + } + + @Test + public void testLongArrayResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet( + "foo", new long[] {1L, 2L, 3L}, ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), + is(equalTo(ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat(subject.getResultSet().getLongArray("foo"), is(equalTo(new long[] {1L, 2L, 3L}))); + assertThat(subject.getResultSet().next(), is(false)); + } + + @Test + public void testStringResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet( + "foo", "bar", ClientSideStatementType.SHOW_READ_ONLY_STALENESS); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), + is(equalTo(ClientSideStatementType.SHOW_READ_ONLY_STALENESS))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat(subject.getResultSet().getString("foo"), is(equalTo("bar"))); + assertThat(subject.getResultSet().next(), is(false)); + } + + @Test + public void testEnumResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet( + "foo", TransactionMode.READ_ONLY_TRANSACTION, ClientSideStatementType.SHOW_READONLY); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), is(equalTo(ClientSideStatementType.SHOW_READONLY))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat( + subject.getResultSet().getString("foo"), + is(equalTo(TransactionMode.READ_ONLY_TRANSACTION.toString()))); + assertThat(subject.getResultSet().next(), is(false)); + } + + @Test + public void testTimestampResultSetGetResultSet() { + StatementResult subject = + StatementResultImpl.resultSet( + "foo", + Timestamp.ofTimeSecondsAndNanos(10L, 10), + ClientSideStatementType.SHOW_READ_TIMESTAMP); + assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat( + subject.getClientSideStatementType(), + is(equalTo(ClientSideStatementType.SHOW_READ_TIMESTAMP))); + assertThat(subject.getResultSet(), is(notNullValue())); + assertThat(subject.getResultSet().next(), is(true)); + assertThat( + subject.getResultSet().getTimestamp("foo"), + is(equalTo(Timestamp.ofTimeSecondsAndNanos(10L, 10)))); + assertThat(subject.getResultSet().next(), is(false)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java new file mode 100644 index 000000000000..9c308e396325 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java @@ -0,0 +1,1173 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.TransactionContext; +import com.google.cloud.spanner.TransactionManager; +import com.google.cloud.spanner.TransactionManager.TransactionState; +import com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.ConnectionConsumer; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.util.Arrays; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Matchers; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +@RunWith(JUnit4.class) +public class StatementTimeoutTest { + private static final String URI = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + private static final String SLOW_SELECT = "SELECT foo FROM bar"; + private static final String INVALID_SELECT = "SELECT FROM bar"; // missing columns / * + private static final String FAST_SELECT = "SELECT fast_column FROM fast_table"; + private static final String SLOW_DDL = "CREATE TABLE foo"; + private static final String FAST_DDL = "CREATE TABLE fast_table"; + private static final String SLOW_UPDATE = "UPDATE foo SET col1=1 WHERE id=2"; + private static final String FAST_UPDATE = "UPDATE fast_table SET foo=1 WHERE bar=2"; + + private enum CommitRollbackBehavior { + FAST, + SLOW_COMMIT, + SLOW_ROLLBACK; + } + + @Rule public ExpectedException expected = ExpectedException.none(); + + private static final class DelayedQueryExecution implements Answer { + @Override + public ResultSet answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(10000L); + return mock(ResultSet.class); + } + } + + private DdlClient createDefaultMockDdlClient(final long waitForMillis) { + try { + DdlClient ddlClient = mock(DdlClient.class); + UpdateDatabaseDdlMetadata metadata = UpdateDatabaseDdlMetadata.getDefaultInstance(); + ApiFuture futureMetadata = ApiFutures.immediateFuture(metadata); + @SuppressWarnings("unchecked") + final OperationFuture operation = + mock(OperationFuture.class); + if (waitForMillis > 0L) { + when(operation.get()) + .thenAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(waitForMillis); + return null; + } + }); + } else { + when(operation.get()).thenReturn(null); + } + when(operation.getMetadata()).thenReturn(futureMetadata); + when(ddlClient.executeDdl(SLOW_DDL)).thenCallRealMethod(); + when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); + + @SuppressWarnings("unchecked") + final OperationFuture fastOperation = + mock(OperationFuture.class); + when(fastOperation.isDone()).thenReturn(true); + when(fastOperation.get()).thenReturn(null); + when(fastOperation.getMetadata()).thenReturn(futureMetadata); + when(ddlClient.executeDdl(FAST_DDL)).thenReturn(fastOperation); + when(ddlClient.executeDdl(Arrays.asList(FAST_DDL))).thenReturn(fastOperation); + return ddlClient; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private ConnectionImpl createConnection(ConnectionOptions options) { + return createConnection(options, CommitRollbackBehavior.FAST); + } + + /** + * Creates a connection on which the statements {@link StatementTimeoutTest#SLOW_SELECT} and + * {@link StatementTimeoutTest#SLOW_DDL} will take at least 10,000 milliseconds + */ + private ConnectionImpl createConnection( + ConnectionOptions options, final CommitRollbackBehavior commitRollbackBehavior) { + DatabaseClient dbClient = mock(DatabaseClient.class); + Spanner spanner = mock(Spanner.class); + SpannerPool spannerPool = mock(SpannerPool.class); + when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) + .thenReturn(spanner); + DdlClient ddlClient = createDefaultMockDdlClient(10000L); + final ResultSet invalidResultSet = mock(ResultSet.class); + when(invalidResultSet.next()) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "invalid query")); + + ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); + when(singleUseReadOnlyTx.executeQuery(Statement.of(SLOW_SELECT))) + .thenAnswer(new DelayedQueryExecution()); + when(singleUseReadOnlyTx.executeQuery(Statement.of(FAST_SELECT))) + .thenReturn(mock(ResultSet.class)); + when(singleUseReadOnlyTx.executeQuery(Statement.of(INVALID_SELECT))) + .thenReturn(invalidResultSet); + when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) + .thenReturn(singleUseReadOnlyTx); + + ReadOnlyTransaction readOnlyTx = mock(ReadOnlyTransaction.class); + when(readOnlyTx.executeQuery(Statement.of(SLOW_SELECT))) + .thenAnswer(new DelayedQueryExecution()); + when(readOnlyTx.executeQuery(Statement.of(FAST_SELECT))).thenReturn(mock(ResultSet.class)); + when(readOnlyTx.executeQuery(Statement.of(INVALID_SELECT))).thenReturn(invalidResultSet); + when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))).thenReturn(readOnlyTx); + + when(dbClient.transactionManager()) + .thenAnswer( + new Answer() { + @Override + public TransactionManager answer(InvocationOnMock invocation) throws Throwable { + TransactionManager txManager = mock(TransactionManager.class); + when(txManager.getState()).thenReturn(null, TransactionState.STARTED); + when(txManager.begin()) + .thenAnswer( + new Answer() { + @Override + public TransactionContext answer(InvocationOnMock invocation) + throws Throwable { + TransactionContext txContext = mock(TransactionContext.class); + when(txContext.executeQuery(Statement.of(SLOW_SELECT))) + .thenAnswer(new DelayedQueryExecution()); + when(txContext.executeQuery(Statement.of(FAST_SELECT))) + .thenReturn(mock(ResultSet.class)); + when(txContext.executeQuery(Statement.of(INVALID_SELECT))) + .thenReturn(invalidResultSet); + when(txContext.executeUpdate(Statement.of(SLOW_UPDATE))) + .thenAnswer( + new Answer() { + @Override + public Long answer(InvocationOnMock invocation) + throws Throwable { + Thread.sleep(10000L); + return 1L; + } + }); + when(txContext.executeUpdate(Statement.of(FAST_UPDATE))).thenReturn(1L); + return txContext; + } + }); + if (commitRollbackBehavior == CommitRollbackBehavior.SLOW_COMMIT) { + doAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(10000L); + return null; + } + }) + .when(txManager) + .commit(); + } + if (commitRollbackBehavior == CommitRollbackBehavior.SLOW_ROLLBACK) { + doAnswer( + new Answer() { + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(10000L); + return null; + } + }) + .when(txManager) + .rollback(); + } + + return txManager; + } + }); + when(dbClient.executePartitionedUpdate(Statement.of(FAST_UPDATE))).thenReturn(1L); + when(dbClient.executePartitionedUpdate(Statement.of(SLOW_UPDATE))) + .thenAnswer( + new Answer() { + @Override + public Long answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(10000L); + return 1L; + } + }); + return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); + } + + @Test + public void testTimeoutExceptionReadOnlyAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testTimeoutExceptionReadOnlyAutocommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionReadOnlyTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testTimeoutExceptionReadOnlyTransactionMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // do a rollback without any chance of a timeout + connection.clearStatementTimeout(); + connection.rollback(); + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitSlowUpdate() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.execute(Statement.of(SLOW_UPDATE)); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitSlowUpdateMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.execute(Statement.of(SLOW_UPDATE)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new update that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.execute(Statement.of(FAST_UPDATE)).getUpdateCount(), is(equalTo(1L))); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitSlowCommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(), + CommitRollbackBehavior.SLOW_COMMIT)) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + // first verify that the fast update does not timeout when in transactional mode (as it is the + // commit that is slow) + connection.setAutocommit(false); + connection.execute(Statement.of(FAST_UPDATE)); + connection.rollback(); + + connection.setAutocommit(true); + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.execute(Statement.of(FAST_UPDATE)); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitSlowCommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(), + CommitRollbackBehavior.SLOW_COMMIT)) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.execute(Statement.of(FAST_UPDATE)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionReadWriteAutocommitPartitioned() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); + // first verify that the fast update does not timeout + connection.execute(Statement.of(FAST_UPDATE)); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.execute(Statement.of(SLOW_UPDATE)); + } + } + + @Test + public void testTimeoutExceptionReadWriteTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testTimeoutExceptionReadWriteTransactionMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // Assert that multiple statements after each other will timeout the first time, and then + // throw a SpannerException with code FAILED_PRECONDITION. + boolean timedOut = false; + for (int i = 0; i < 2; i++) { + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + if (i == 0) { + assertThat(e.getErrorCode(), is(equalTo(ErrorCode.DEADLINE_EXCEEDED))); + timedOut = true; + } else { + assertThat(e.getErrorCode(), is(equalTo(ErrorCode.FAILED_PRECONDITION))); + } + } + } + assertThat(timedOut, is(true)); + // do a rollback without any chance of a timeout + connection.clearStatementTimeout(); + connection.rollback(); + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionReadWriteTransactionalSlowCommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(), + CommitRollbackBehavior.SLOW_COMMIT)) { + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + connection.executeQuery(Statement.of(FAST_SELECT)); + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.commit(); + } + } + + @Test + public void testTimeoutExceptionReadWriteTransactionalSlowRollback() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(), + CommitRollbackBehavior.SLOW_ROLLBACK)) { + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + connection.executeQuery(Statement.of(FAST_SELECT)); + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.rollback(); + } + } + + private static final class ConnectionReadOnlyAutocommit implements ConnectionConsumer { + @Override + public void accept(Connection t) { + t.setReadOnly(true); + } + } + + @Test + public void testInterruptedExceptionReadOnlyAutocommit() + throws InterruptedException, ExecutionException { + testInterruptedException(new ConnectionReadOnlyAutocommit()); + } + + private static final class ConnectionReadOnlyTransactional implements ConnectionConsumer { + @Override + public void accept(Connection t) { + t.setReadOnly(true); + t.setAutocommit(false); + } + } + + @Test + public void testInterruptedExceptionReadOnlyTransactional() + throws InterruptedException, ExecutionException { + testInterruptedException(new ConnectionReadOnlyTransactional()); + } + + private static final class ConnectionReadWriteAutocommit implements ConnectionConsumer { + @Override + public void accept(Connection t) {} + } + + @Test + public void testInterruptedExceptionReadWriteAutocommit() + throws InterruptedException, ExecutionException { + testInterruptedException(new ConnectionReadWriteAutocommit()); + } + + private static final class ConnectionReadWriteTransactional implements ConnectionConsumer { + @Override + public void accept(Connection t) { + t.setAutocommit(false); + } + } + + @Test + public void testInterruptedExceptionReadWriteTransactional() + throws InterruptedException, ExecutionException { + testInterruptedException(new ConnectionReadWriteTransactional()); + } + + private void testInterruptedException(final ConnectionConsumer consumer) + throws InterruptedException, ExecutionException { + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = + executor.submit( + new Callable() { + @Override + public Boolean call() throws Exception { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + consumer.accept(connection); + connection.setStatementTimeout(10000L, TimeUnit.MILLISECONDS); + + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + if (e.getErrorCode() == ErrorCode.CANCELLED) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + return Boolean.FALSE; + } + }); + // wait a little bit to ensure that the task has started + Thread.sleep(10L); + executor.shutdownNow(); + assertThat(future.get(), is(true)); + } + + @Test + public void testInvalidQueryReadOnlyAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setUri(URI) + .setCredentials(NoCredentials.getInstance()) + .build())) { + connection.setReadOnly(true); + connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); + connection.executeQuery(Statement.of(INVALID_SELECT)); + } + } + + @Test + public void testInvalidQueryReadOnlyTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setAutocommit(false); + connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); + connection.executeQuery(Statement.of(INVALID_SELECT)); + } + } + + @Test + public void testInvalidQueryReadWriteAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); + connection.executeQuery(Statement.of(INVALID_SELECT)); + } + } + + @Test + public void testInvalidQueryReadWriteTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); + connection.executeQuery(Statement.of(INVALID_SELECT)); + } + } + + @Test + public void testCancelReadOnlyAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testCancelReadOnlyAutocommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + boolean cancelled = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + cancelled = e.getErrorCode() == ErrorCode.CANCELLED; + } + assertThat(cancelled, is(true)); + + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testCancelReadOnlyTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setAutocommit(false); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testCancelReadOnlyTransactionalMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setReadOnly(true); + connection.setAutocommit(false); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + boolean cancelled = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + cancelled = e.getErrorCode() == ErrorCode.CANCELLED; + } + assertThat(cancelled, is(true)); + + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + // rollback and do another fast query + connection.rollback(); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testCancelReadWriteAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testCancelReadWriteAutocommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + boolean cancelled = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + cancelled = e.getErrorCode() == ErrorCode.CANCELLED; + } + assertThat(cancelled, is(true)); + + // try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testCancelReadWriteAutocommitSlowUpdate() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.execute(Statement.of(SLOW_UPDATE)); + } + } + + @Test + public void testCancelReadWriteAutocommitSlowCommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build(), + CommitRollbackBehavior.SLOW_COMMIT)) { + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.execute(Statement.of(FAST_UPDATE)); + } + } + + @Test + public void testCancelReadWriteTransactional() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.executeQuery(Statement.of(SLOW_SELECT)); + } + } + + @Test + public void testCancelReadWriteTransactionalMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + boolean cancelled = false; + try { + connection.executeQuery(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + cancelled = e.getErrorCode() == ErrorCode.CANCELLED; + } + assertThat(cancelled, is(true)); + // Rollback the transaction as it is no longer usable. + connection.rollback(); + + // Try to do a new query that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); + } + } + + @Test + public void testCancelDdlBatch() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.startBatchDdl(); + connection.execute(Statement.of(SLOW_DDL)); + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.runBatch(); + } + } + + @Test + public void testCancelDdlAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + Executors.newSingleThreadScheduledExecutor() + .schedule( + new Runnable() { + @Override + public void run() { + connection.cancel(); + } + }, + 100, + TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); + connection.execute(Statement.of(SLOW_DDL)); + } + } + + @Test + public void testTimeoutExceptionDdlAutocommit() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.execute(Statement.of(SLOW_DDL)); + } + } + + @Test + public void testTimeoutExceptionDdlAutocommitMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + try { + connection.execute(Statement.of(SLOW_DDL)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new DDL statement that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); + } + } + + @Test + public void testTimeoutExceptionDdlBatch() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.startBatchDdl(); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // the following statement will NOT timeout as the statement is only buffered locally + connection.execute(Statement.of(SLOW_DDL)); + // the commit sends the statement to the server and should timeout + expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + connection.runBatch(); + } + } + + @Test + public void testTimeoutExceptionDdlBatchMultipleStatements() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + connection.setAutocommit(false); + connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + + // assert that multiple statements after each other also time out + for (int i = 0; i < 2; i++) { + boolean timedOut = false; + connection.startBatchDdl(); + connection.execute(Statement.of(SLOW_DDL)); + try { + connection.runBatch(); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + // try to do a new DDL statement that is fast. + connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.startBatchDdl(); + assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); + connection.runBatch(); + } + } + + @Test + public void testTimeoutDifferentTimeUnits() { + try (Connection connection = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { + connection.setStatementTimeout(1L, unit); + boolean timedOut = false; + try { + connection.execute(Statement.of(SLOW_SELECT)); + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java new file mode 100644 index 000000000000..8e14e608709a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.TransactionModeConverter; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class TransactionModeConverterTest { + + @Test + public void testConvert() throws CompileException { + String allowedValues = + ReadOnlyStalenessConverterTest.getAllowedValues(TransactionModeConverter.class); + assertThat(allowedValues, is(notNullValue())); + TransactionModeConverter converter = new TransactionModeConverter(allowedValues); + assertThat( + converter.convert("read write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat( + converter.convert("READ WRITE"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat( + converter.convert("Read Write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat( + converter.convert("read write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat( + converter.convert("READ\nWRITE"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + assertThat( + converter.convert("Read\tWrite"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); + + assertThat(converter.convert("read only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat(converter.convert("READ ONLY"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat(converter.convert("Read Only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat( + converter.convert("read only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat(converter.convert("READ\nONLY"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + assertThat(converter.convert("Read\tOnly"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); + + assertThat(converter.convert(""), is(nullValue())); + assertThat(converter.convert(" "), is(nullValue())); + assertThat(converter.convert("random string"), is(nullValue())); + assertThat(converter.convert("read_write"), is(nullValue())); + assertThat(converter.convert("Read_Write"), is(nullValue())); + assertThat(converter.convert("READ_WRITE"), is(nullValue())); + assertThat(converter.convert("read_only"), is(nullValue())); + assertThat(converter.convert("Read_Only"), is(nullValue())); + assertThat(converter.convert("READ_ONLY"), is(nullValue())); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java new file mode 100644 index 000000000000..a99b5ada67c5 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test opening multiple generic (not JDBC) Spanner connections. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITBulkConnectionTest extends ITAbstractSpannerTest { + private static final int NUMBER_OF_TEST_CONNECTIONS = 250; + + @Test + public void testBulkCreateConnectionsSingleThreaded() { + List connections = new ArrayList<>(); + for (int i = 0; i < NUMBER_OF_TEST_CONNECTIONS; i++) { + connections.add(createConnection()); + } + for (ITConnection connection : connections) { + try (ResultSet rs = connection.executeQuery(Statement.of("select 1"))) { + assertThat(rs.next(), is(true)); + assertThat(connection.getReadTimestamp(), is(notNullValue())); + } + } + for (ITConnection connection : connections) { + connection.close(); + } + // close Spanner instances explicitly. This method will throw an exception if there are any + // connections still open in the pool + closeSpanner(); + } + + @Test + public void testBulkCreateConnectionsMultiThreaded() throws InterruptedException { + ExecutorService executor = Executors.newFixedThreadPool(50); + for (int i = 0; i < NUMBER_OF_TEST_CONNECTIONS; i++) { + executor.submit( + new Callable() { + @Override + public Void call() throws Exception { + try (ITConnection connection = createConnection()) { + try (ResultSet rs = connection.executeQuery(Statement.of("select 1"))) { + assertThat(rs.next(), is(true)); + assertThat(connection.getReadTimestamp(), is(notNullValue())); + } + } + return null; + } + }); + } + executor.shutdown(); + executor.awaitTermination(10L, TimeUnit.SECONDS); + // close Spanner instances explicitly. This method will throw an exception if there are any + // connections still open in the pool + closeSpanner(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java new file mode 100644 index 000000000000..c59d2fe668a1 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Execute DDL statements using the generic connection API. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITDdlTest extends ITAbstractSpannerTest { + + @Test + public void testSqlScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); + verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class, true); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java new file mode 100644 index 000000000000..cef3148e3111 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcDataSource; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; +import javax.sql.DataSource; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * There are three different possibilities to specify the properties of a jdbc connection: + * + *
    + *
  1. Specify properties in the connection URL + *
  2. Pass a {@link Properties} object to the {@link DriverManager} + *
  3. Set the properties on a {@link DataSource} + *
+ * + * This class tests all three possibilities. + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcConnectTest extends ITAbstractJdbcTest { + + private String createBaseUrl() { + StringBuilder url = + new StringBuilder("jdbc:cloudspanner:/").append(getDatabase().getId().getName()); + return url.toString(); + } + + private void testDefaultConnection(Connection connection) throws SQLException { + assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class), is(true)); + CloudSpannerJdbcConnection cs = connection.unwrap(CloudSpannerJdbcConnection.class); + assertThat(cs.getAutoCommit(), is(true)); + assertThat(cs.isReadOnly(), is(false)); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(1))); + } + cs.setAutoCommit(false); + assertThat(cs.isRetryAbortsInternally(), is(true)); + } + + private void testNonDefaultConnection(Connection connection) throws SQLException { + assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class), is(true)); + CloudSpannerJdbcConnection cs = connection.unwrap(CloudSpannerJdbcConnection.class); + assertThat(cs.getAutoCommit(), is(false)); + assertThat(cs.isReadOnly(), is(true)); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(1))); + } + connection.commit(); + cs.setReadOnly(false); + assertThat(cs.isRetryAbortsInternally(), is(false)); + } + + @Test + public void testConnectWithURLWithDefaultValues() throws SQLException { + String url = createBaseUrl(); + if (hasValidKeyFile()) { + url = url + "?credentials=" + getKeyFile(); + } + try (Connection connection = DriverManager.getConnection(url)) { + testDefaultConnection(connection); + } + } + + @Test + public void testConnectWithURLWithNonDefaultValues() throws SQLException { + String url = createBaseUrl(); + url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + if (hasValidKeyFile()) { + url = url + ";credentials=" + getKeyFile(); + } + try (Connection connection = DriverManager.getConnection(url)) { + testNonDefaultConnection(connection); + } + } + + @Test + public void testConnectWithPropertiesWithDefaultValues() throws SQLException { + String url = createBaseUrl(); + Properties properties = new Properties(); + if (hasValidKeyFile()) { + properties.setProperty("credentials", getKeyFile()); + } + try (Connection connection = DriverManager.getConnection(url, properties)) { + testDefaultConnection(connection); + } + } + + @Test + public void testConnectWithPropertiesWithNonDefaultValues() throws SQLException { + String url = createBaseUrl(); + Properties properties = new Properties(); + if (hasValidKeyFile()) { + properties.setProperty("credentials", getKeyFile()); + } + properties.setProperty("autocommit", "false"); + properties.setProperty("readonly", "true"); + properties.setProperty("retryAbortsInternally", "false"); + try (Connection connection = DriverManager.getConnection(url, properties)) { + testNonDefaultConnection(connection); + } + } + + @Test + public void testConnectWithPropertiesWithConflictingValues() throws SQLException { + String url = createBaseUrl(); + url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + if (hasValidKeyFile()) { + url = url + ";credentials=" + getKeyFile(); + } + Properties properties = new Properties(); + properties.setProperty("autocommit", "true"); + properties.setProperty("readonly", "false"); + properties.setProperty("retryAbortsInternally", "true"); + try (Connection connection = DriverManager.getConnection(url, properties)) { + testNonDefaultConnection(connection); + } + } + + @Test + public void testConnectWithDataSourceWithDefaultValues() throws SQLException { + JdbcDataSource ds = new JdbcDataSource(); + ds.setUrl(createBaseUrl()); + if (hasValidKeyFile()) { + ds.setCredentials(getKeyFile()); + } + try (Connection connection = ds.getConnection()) { + testDefaultConnection(connection); + } + } + + @Test + public void testConnectWithDataSourceWithNonDefaultValues() throws SQLException { + JdbcDataSource ds = new JdbcDataSource(); + ds.setUrl(createBaseUrl()); + if (hasValidKeyFile()) { + ds.setCredentials(getKeyFile()); + } + ds.setAutocommit(false); + ds.setReadonly(true); + ds.setRetryAbortsInternally(false); + try (Connection connection = ds.getConnection()) { + testNonDefaultConnection(connection); + } + } + + @Test + public void testConnectWithDataSourceWithConflictingValues() throws SQLException { + // Try with non-default values in URL and default values in data source. The values in the URL + // should take precedent. + String url = createBaseUrl(); + url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + if (hasValidKeyFile()) { + url = url + ";credentials=" + getKeyFile(); + } + JdbcDataSource ds = new JdbcDataSource(); + ds.setUrl(url); + ds.setAutocommit(true); + ds.setReadonly(false); + ds.setRetryAbortsInternally(true); + try (Connection connection = ds.getConnection()) { + testNonDefaultConnection(connection); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java new file mode 100644 index 000000000000..794f8338afe6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Execute DDL statements using JDBC. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcDdlTest extends ITAbstractJdbcTest { + + @Test + public void testSqlScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class, true); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java new file mode 100644 index 000000000000..3bab287c6c85 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.math.BigInteger; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** This test class runs a SQL script for testing a connection in read-only mode. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcReadOnlyTest extends ITAbstractJdbcTest { + private static final long TEST_ROWS_COUNT = 1000L; + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Override + protected void appendConnectionUri(StringBuilder url) { + url.append(";readOnly=true"); + } + + @Before + public void createTestTables() throws Exception { + try (CloudSpannerJdbcConnection connection = createConnection()) { + if (!(tableExists(connection, "NUMBERS") && tableExists(connection, "PRIME_NUMBERS"))) { + // create tables + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + verifier.verifyStatementsInFile( + "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class, true); + + // fill tables with data + connection.setAutoCommit(false); + connection.setReadOnly(false); + for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { + connection.bufferedWrite( + Mutation.newInsertBuilder("NUMBERS") + .set("number") + .to(number) + .set("name") + .to(Long.toBinaryString(number)) + .build()); + } + for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { + if (BigInteger.valueOf(number).isProbablePrime(Integer.MAX_VALUE)) { + connection.bufferedWrite( + Mutation.newInsertBuilder("PRIME_NUMBERS") + .set("prime_number") + .to(number) + .set("binary_representation") + .to(Long.toBinaryString(number)) + .build()); + } + } + connection.commit(); + } + } + } + + @Test + public void testSqlScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class, true); + } + + @Test + public void testMultipleOpenResultSets() throws InterruptedException, SQLException { + try (Connection connection = createConnection()) { + final java.sql.ResultSet rs1 = + connection.createStatement().executeQuery("SELECT * FROM PRIME_NUMBERS"); + final java.sql.ResultSet rs2 = + connection.createStatement().executeQuery("SELECT * FROM NUMBERS"); + ExecutorService exec = Executors.newFixedThreadPool(2); + exec.submit( + new Runnable() { + @Override + public void run() { + try { + while (rs1.next()) {} + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }); + exec.submit( + new Runnable() { + @Override + public void run() { + try { + while (rs2.next()) {} + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + }); + exec.shutdown(); + exec.awaitTermination(1000L, TimeUnit.SECONDS); + rs1.close(); + rs2.close(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java new file mode 100644 index 000000000000..752cb868d30c --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITJdbcReadWriteAutocommitTest extends ITAbstractJdbcTest { + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Override + protected void appendConnectionUri(StringBuilder uri) { + uri.append(";autocommit=true"); + } + + @Override + public boolean doCreateDefaultTestTable() { + return true; + } + + @Test + public void test01_SqlScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + verifier.verifyStatementsInFile( + "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class, true); + } + + @Test + public void test02_WriteMutation() throws Exception { + try (CloudSpannerJdbcConnection connection = createConnection()) { + connection.write( + Mutation.newInsertBuilder("TEST").set("ID").to(9999L).set("NAME").to("FOO").build()); + java.sql.Statement statement = connection.createStatement(); + statement.execute("SHOW VARIABLE COMMIT_TIMESTAMP"); + try (java.sql.ResultSet rs = statement.getResultSet()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getTimestamp(1), is(notNullValue())); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java new file mode 100644 index 000000000000..43cfb43c0754 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -0,0 +1,238 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +/** + * Integration test that creates and fills a test database entirely using only sql scripts, and then + * performs all possible operations on this test database using only sql scripts. This test uses the + * JDBC driver for Spanner. + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITJdbcSqlScriptTest extends ITAbstractJdbcTest { + private static final String CREATE_TABLES_FILE = "ITSqlScriptTest_CreateTables.sql"; + private static final String INSERT_AND_VERIFY_TEST_DATA = "ITSqlScriptTest_InsertTestData.sql"; + private static final String TEST_GET_READ_TIMESTAMP = "ITSqlScriptTest_TestGetReadTimestamp.sql"; + private static final String TEST_GET_COMMIT_TIMESTAMP = + "ITSqlScriptTest_TestGetCommitTimestamp.sql"; + private static final String TEST_TEMPORARY_TRANSACTIONS = + "ITSqlScriptTest_TestTemporaryTransactions.sql"; + private static final String TEST_TRANSACTION_MODE = "ITSqlScriptTest_TestTransactionMode.sql"; + private static final String TEST_TRANSACTION_MODE_READ_ONLY = + "ITSqlScriptTest_TestTransactionMode_ReadOnly.sql"; + private static final String TEST_READ_ONLY_STALENESS = + "ITSqlScriptTest_TestReadOnlyStaleness.sql"; + private static final String TEST_AUTOCOMMIT_DML_MODE = + "ITSqlScriptTest_TestAutocommitDmlMode.sql"; + private static final String TEST_AUTOCOMMIT_READ_ONLY = + "ITSqlScriptTest_TestAutocommitReadOnly.sql"; + private static final String TEST_STATEMENT_TIMEOUT = "ITSqlScriptTest_TestStatementTimeout.sql"; + private static final String TEST_SET_STATEMENTS = "ITSqlScriptTest_TestSetStatements.sql"; + private static final String TEST_INVALID_STATEMENTS = "ITSqlScriptTest_TestInvalidStatements.sql"; + + private final JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(); + + /** Create test tables and verify their existence */ + @Test + public void test01_CreateTables() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class, true); + } + } + + /** Insert some test data */ + @Test + public void test02_InsertTestData() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + INSERT_AND_VERIFY_TEST_DATA, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test03_TestGetReadTimestamp() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_GET_READ_TIMESTAMP, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test04_TestGetCommitTimestamp() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_GET_COMMIT_TIMESTAMP, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test05_TestTemporaryTransactions() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_TEMPORARY_TRANSACTIONS, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test06_TestTransactionMode() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_TRANSACTION_MODE, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test07_TestTransactionModeReadOnly() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_TRANSACTION_MODE_READ_ONLY, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test08_TestReadOnlyStaleness() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_READ_ONLY_STALENESS, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test09_TestAutocommitDmlMode() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_AUTOCOMMIT_DML_MODE, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test10_TestAutocommitReadOnly() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_AUTOCOMMIT_READ_ONLY, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test11_TestStatementTimeout() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_STATEMENT_TIMEOUT, + SqlScriptVerifier.class, + true); + } + try (Connection connection = createConnection()) { + // Create a statement with a query timeout, but do not set a statement timeout on the + // connection. SHOW STATEMENT_TIMEOUT should then return a null value. + Statement statement = connection.createStatement(); + statement.setQueryTimeout(1); + statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); + try (ResultSet rs = statement.getResultSet()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("STATEMENT_TIMEOUT"), is(nullValue())); + } + + // Now set a STATEMENT_TIMEOUT on the connection that is different from the query timeout of + // the statement. SHOW STATEMENT_TIMEOUT should now return the STATEMENT_TIMEOUT of the + // connection. + statement.execute("SET STATEMENT_TIMEOUT='100ms'"); + statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); + try (ResultSet rs = statement.getResultSet()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("STATEMENT_TIMEOUT"), is(equalTo("100ms"))); + } + + // Remove the statement timeout again, and verify that SHOW STATEMENT_TIMEOUT once again + // returns null. + statement.execute("SET STATEMENT_TIMEOUT=NULL"); + statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); + try (ResultSet rs = statement.getResultSet()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("STATEMENT_TIMEOUT"), is(nullValue())); + } + } + } + + @Test + public void test12_TestSetStatements() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class, true); + } + } + + @Test + public void test13_TestInvalidStatements() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), + TEST_INVALID_STATEMENTS, + SqlScriptVerifier.class, + true); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java new file mode 100644 index 000000000000..8e46ceceebd1 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java @@ -0,0 +1,225 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SpannerExceptionMatcher; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.math.BigInteger; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * This test class runs a SQL script for testing a connection in read-only mode, but also contains a + * number of separate test methods that cannot be expressed in a pure SQL test. + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITReadOnlySpannerTest extends ITAbstractSpannerTest { + private static final Logger logger = Logger.getLogger(ITReadOnlySpannerTest.class.getName()); + private static final long TEST_ROWS_COUNT = 1000L; + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Override + protected void appendConnectionUri(StringBuilder url) { + url.append(";readOnly=true"); + } + + @Before + public void createTestTables() throws Exception { + try (ITConnection connection = createConnection()) { + if (!(tableExists(connection, "NUMBERS") && tableExists(connection, "PRIME_NUMBERS"))) { + // create tables + SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); + verifier.verifyStatementsInFile( + "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class, true); + + // fill tables with data + connection.setAutocommit(false); + connection.setReadOnly(false); + for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { + connection.bufferedWrite( + Mutation.newInsertBuilder("NUMBERS") + .set("number") + .to(number) + .set("name") + .to(Long.toBinaryString(number)) + .build()); + } + for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { + if (BigInteger.valueOf(number).isProbablePrime(Integer.MAX_VALUE)) { + connection.bufferedWrite( + Mutation.newInsertBuilder("PRIME_NUMBERS") + .set("prime_number") + .to(number) + .set("binary_representation") + .to(Long.toBinaryString(number)) + .build()); + } + } + connection.commit(); + } + } + } + + @Test + public void testSqlScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); + verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class, true); + } + + @Test + public void testStatementTimeoutTransactional() throws Exception { + try (ITConnection connection = createConnection()) { + connection.beginTransaction(); + connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + try (ResultSet rs = + connection.executeQuery( + Statement.of( + "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) {} + // should never be reached + connection.commit(); + } + } + + @Test + public void testStatementTimeoutTransactionalMultipleStatements() throws Exception { + long startTime = System.currentTimeMillis(); + try (ITConnection connection = createConnection()) { + connection.beginTransaction(); + for (int i = 0; i < 3; i++) { + boolean timedOut = false; + connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); + try (ResultSet rs = + connection.executeQuery( + Statement.of( + "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) { + } catch (SpannerException e) { + timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; + } + assertThat(timedOut, is(true)); + } + connection.commit(); + } + long endTime = System.currentTimeMillis(); + long executionTime = endTime - startTime; + if (executionTime > 25L) { + logger.warning("Total test execution time exceeded 25 milliseconds: " + executionTime); + } else { + logger.info("Total test execution time: " + executionTime); + } + } + + @Test + public void testStatementTimeoutAutocommit() throws Exception { + try (ITConnection connection = createConnection()) { + assertThat(connection.isAutocommit(), is(true)); + connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); + try (ResultSet rs = + connection.executeQuery( + Statement.of( + "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) {} + } + } + + @Test + public void testAnalyzeQuery() { + try (ITConnection connection = createConnection()) { + for (QueryAnalyzeMode mode : QueryAnalyzeMode.values()) { + try (ResultSet rs = + connection.analyzeQuery( + Statement.of( + "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"), + mode)) { + // next has not yet returned false + assertThat(rs.getStats(), is(nullValue())); + while (rs.next()) { + // ignore + } + assertThat(rs.getStats(), is(notNullValue())); + } + } + } + } + + @Test + public void testQueryWithOptions() { + try (ITConnection connection = createConnection()) { + try (ResultSet rs = + connection.executeQuery( + Statement.of( + "SELECT (SELECT CAST(COUNT(*) AS FLOAT64) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"), + Options.prefetchChunks(100000))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getDouble(0), is(notNullValue())); + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testMultipleOpenResultSets() throws InterruptedException { + try (ITConnection connection = createConnection()) { + final ResultSet rs1 = connection.executeQuery(Statement.of("SELECT * FROM PRIME_NUMBERS")); + final ResultSet rs2 = connection.executeQuery(Statement.of("SELECT * FROM NUMBERS")); + ExecutorService exec = Executors.newFixedThreadPool(2); + exec.submit( + new Runnable() { + @Override + public void run() { + while (rs1.next()) {} + } + }); + exec.submit( + new Runnable() { + @Override + public void run() { + while (rs2.next()) {} + } + }); + exec.shutdown(); + exec.awaitTermination(1000L, TimeUnit.SECONDS); + rs1.close(); + rs2.close(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java new file mode 100644 index 000000000000..f08e6226721a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITReadWriteAutocommitSpannerTest extends ITAbstractSpannerTest { + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Override + protected void appendConnectionUri(StringBuilder uri) { + uri.append(";autocommit=true"); + } + + @Override + public boolean doCreateDefaultTestTable() { + return true; + } + + @Test + public void test01_SqlScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); + verifier.verifyStatementsInFile( + "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class, true); + } + + @Test + public void test02_WriteMutation() throws Exception { + try (ITConnection connection = createConnection()) { + connection.write( + Mutation.newInsertBuilder("TEST").set("ID").to(9999L).set("NAME").to("FOO").build()); + assertThat(connection.getCommitTimestamp(), is(notNullValue())); + } + } + + @Test + public void test03_MultipleStatements_WithTimeouts() throws InterruptedException { + try (ITConnection connection = createConnection()) { + // do an insert that should succeed + assertThat( + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1000, 'test')")), + is(equalTo(1L))); + // check that the insert succeeded + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1000"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("test"))); + assertThat(rs.next(), is(false)); + } + + // do an update that should time out + connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); + try { + connection.executeUpdate(Statement.of("UPDATE TEST SET NAME='test18' WHERE ID=1000")); + } catch (SpannerException e) { + if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { + throw e; + } + } + // remove the timeout setting + connection.clearStatementTimeout(); + + // do a delete that should succeed + connection.executeUpdate(Statement.of("DELETE FROM TEST WHERE ID=1000")); + // verify that the delete did succeed + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1000"))) { + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void test04_BatchUpdate() { + try (ITConnection connection = createConnection()) { + long[] updateCounts = + connection.executeBatchUpdate( + Arrays.asList( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (10, 'Batch value 1')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (11, 'Batch value 2')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (12, 'Batch value 3')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (13, 'Batch value 4')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (14, 'Batch value 5')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (15, 'Batch value 6')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (16, 'Batch value 7')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (17, 'Batch value 8')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (18, 'Batch value 9')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (19, 'Batch value 10')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (20, 'Batch value 11')"))); + assertThat( + updateCounts, is(equalTo(new long[] {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L}))); + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=10 AND ID<=20"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(0), is(equalTo(11L))); + } + } + } + + @Test + public void test05_BatchUpdateWithException() { + try (ITConnection con1 = createConnection(); + ITConnection con2 = createConnection()) { + try { + con1.executeBatchUpdate( + Arrays.asList( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (21, 'Batch value 1')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (22, 'Batch value 2')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (23, 'Batch value 3')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (24, 'Batch value 4')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (25, 'Batch value 5')"), + Statement.of("INSERT INTO TEST_NOT_FOUND (ID, NAME) VALUES (26, 'Batch value 6')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (27, 'Batch value 7')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (28, 'Batch value 8')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (29, 'Batch value 9')"), + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (30, 'Batch value 10')"))); + fail("Missing batch update exception"); + } catch (SpannerBatchUpdateException e) { + assertThat(e.getUpdateCounts(), is(equalTo(new long[] {1L, 1L, 1L, 1L, 1L}))); + } + // Verify that the values cannot be read on the connection that did the insert. + try (ResultSet rs = + con1.executeQuery(Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=21 AND ID<=30"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(0), is(equalTo(0L))); + } + // Verify that the values can also not be read on another connection. + try (ResultSet rs = + con2.executeQuery(Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=21 AND ID<=30"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(0), is(equalTo(0L))); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java new file mode 100644 index 000000000000..be20ec3c4591 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java @@ -0,0 +1,203 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +/** + * Integration test that creates and fills a test database entirely using only sql scripts, and then + * performs all possible operations on this test database using only sql scripts. This test uses the + * generic connection API. + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITSqlScriptTest extends ITAbstractSpannerTest { + private static final String CREATE_TABLES_FILE = "ITSqlScriptTest_CreateTables.sql"; + private static final String INSERT_AND_VERIFY_TEST_DATA = "ITSqlScriptTest_InsertTestData.sql"; + private static final String TEST_GET_READ_TIMESTAMP = "ITSqlScriptTest_TestGetReadTimestamp.sql"; + private static final String TEST_GET_COMMIT_TIMESTAMP = + "ITSqlScriptTest_TestGetCommitTimestamp.sql"; + private static final String TEST_TEMPORARY_TRANSACTIONS = + "ITSqlScriptTest_TestTemporaryTransactions.sql"; + private static final String TEST_TRANSACTION_MODE = "ITSqlScriptTest_TestTransactionMode.sql"; + private static final String TEST_TRANSACTION_MODE_READ_ONLY = + "ITSqlScriptTest_TestTransactionMode_ReadOnly.sql"; + private static final String TEST_READ_ONLY_STALENESS = + "ITSqlScriptTest_TestReadOnlyStaleness.sql"; + private static final String TEST_AUTOCOMMIT_DML_MODE = + "ITSqlScriptTest_TestAutocommitDmlMode.sql"; + private static final String TEST_AUTOCOMMIT_READ_ONLY = + "ITSqlScriptTest_TestAutocommitReadOnly.sql"; + private static final String TEST_STATEMENT_TIMEOUT = "ITSqlScriptTest_TestStatementTimeout.sql"; + private static final String TEST_SET_STATEMENTS = "ITSqlScriptTest_TestSetStatements.sql"; + private static final String TEST_INVALID_STATEMENTS = "ITSqlScriptTest_TestInvalidStatements.sql"; + + private final SqlScriptVerifier verifier = new SqlScriptVerifier(); + + @Test + public void test01_CreateTables() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + CREATE_TABLES_FILE, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test02_InsertTestData() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + INSERT_AND_VERIFY_TEST_DATA, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test03_TestGetReadTimestamp() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_GET_READ_TIMESTAMP, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test04_TestGetCommitTimestamp() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_GET_COMMIT_TIMESTAMP, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test05_TestTemporaryTransactions() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_TEMPORARY_TRANSACTIONS, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test06_TestTransactionMode() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_TRANSACTION_MODE, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test07_TestTransactionModeReadOnly() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_TRANSACTION_MODE_READ_ONLY, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test08_TestReadOnlyStaleness() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_READ_ONLY_STALENESS, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test09_TestAutocommitDmlMode() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_AUTOCOMMIT_DML_MODE, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test10_TestAutocommitReadOnly() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_AUTOCOMMIT_READ_ONLY, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test11_TestStatementTimeout() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_STATEMENT_TIMEOUT, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test12_TestSetStatements() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_SET_STATEMENTS, + SqlScriptVerifier.class, + true); + } + } + + @Test + public void test13_TestInvalidStatements() throws Exception { + try (ITConnection connection = createConnection()) { + verifier.verifyStatementsInFile( + SpannerGenericConnection.of(connection), + TEST_INVALID_STATEMENTS, + SqlScriptVerifier.class, + true); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java new file mode 100644 index 000000000000..7e3959e8449a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java @@ -0,0 +1,187 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SpannerExceptionMatcher; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITTransactionModeTest extends ITAbstractSpannerTest { + @Rule public ExpectedException exception = ExpectedException.none(); + + @Override + public void appendConnectionUri(StringBuilder uri) { + uri.append("?autocommit=false"); + } + + @Override + public boolean doCreateDefaultTestTable() { + return true; + } + + @Test + public void testSqlScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); + verifier.verifyStatementsInFile("ITTransactionModeTest.sql", SqlScriptVerifier.class, true); + } + + @Test + public void testDoAllowBufferedWriteInReadWriteTransaction() { + try (ITConnection connection = createConnection()) { + assertThat(connection.isAutocommit(), is(false)); + connection.bufferedWrite( + Mutation.newInsertBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST").build()); + connection.commit(); + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST"))); + assertThat(rs.next(), is(false)); + } + connection.bufferedWrite( + Mutation.newUpdateBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST2").build()); + connection.commit(); + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST2"))); + assertThat(rs.next(), is(false)); + } + connection.bufferedWrite(Mutation.delete("TEST", Key.of(1L))); + connection.commit(); + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testDoAllowBufferedWriteIterableInReadWriteTransaction() { + try (ITConnection connection = createConnection()) { + assertThat(connection.isAutocommit(), is(false)); + connection.bufferedWrite( + Arrays.asList( + Mutation.newInsertBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST-1").build(), + Mutation.newInsertBuilder("TEST").set("ID").to(2L).set("NAME").to("TEST-2").build())); + connection.commit(); + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST-1"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST-2"))); + assertThat(rs.next(), is(false)); + } + connection.bufferedWrite( + Arrays.asList( + Mutation.newUpdateBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST-1-2").build(), + Mutation.newUpdateBuilder("TEST") + .set("ID") + .to(2L) + .set("NAME") + .to("TEST-2-2") + .build())); + connection.commit(); + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST-1-2"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("TEST-2-2"))); + assertThat(rs.next(), is(false)); + } + connection.bufferedWrite( + Arrays.asList(Mutation.delete("TEST", Key.of(1L)), Mutation.delete("TEST", Key.of(2L)))); + connection.commit(); + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testDoNotAllowBufferedWriteInReadOnlyTransaction() { + try (ITConnection connection = createConnection()) { + connection.execute(Statement.of("SET TRANSACTION READ ONLY")); + assertThat(connection.isAutocommit(), is(false)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); + } + } + + @Test + public void testDoNotAllowBufferedWriteIterableInReadOnlyTransaction() { + try (ITConnection connection = createConnection()) { + connection.execute(Statement.of("SET TRANSACTION READ ONLY")); + assertThat(connection.isAutocommit(), is(false)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.bufferedWrite( + Arrays.asList( + Mutation.newInsertBuilder("FOO").set("ID").to(1L).build(), + Mutation.newInsertBuilder("FOO").set("ID").to(2L).build())); + } + } + + @Test + public void testDoNotAllowBufferedWriteInDdlBatch() { + try (ITConnection connection = createConnection()) { + connection.startBatchDdl(); + assertThat(connection.isAutocommit(), is(false)); + assertThat(connection.isDdlBatchActive(), is(true)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); + } + } + + @Test + public void testDoNotAllowBufferedWriteIterableInDdlBatch() { + try (ITConnection connection = createConnection()) { + connection.startBatchDdl(); + assertThat(connection.isAutocommit(), is(false)); + assertThat(connection.isDdlBatchActive(), is(true)); + exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.bufferedWrite( + Arrays.asList( + Mutation.newInsertBuilder("FOO").set("ID").to(1L).build(), + Mutation.newInsertBuilder("FOO").set("ID").to(2L).build())); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java new file mode 100644 index 000000000000..18b8bcce3a42 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java @@ -0,0 +1,1586 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.TransactionRetryListener; +import java.sql.Connection; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * This integration test tests the different scenarios for automatically retrying read/write + * transactions, both when possible and when the transaction must abort because of a concurrent + * update. + */ +@RunWith(JUnit4.class) +public class ITTransactionRetryTest extends ITAbstractSpannerTest { + private static final Logger logger = Logger.getLogger(ITTransactionRetryTest.class.getName()); + + @Rule public TestName testName = new TestName(); + + @Override + protected void appendConnectionUri(StringBuilder uri) { + uri.append(";autocommit=false;retryAbortsInternally=true"); + } + + @Override + public boolean doCreateDefaultTestTable() { + return true; + } + + /** Clear the test table before each test run */ + @Before + public void clearTable() { + try (ITConnection connection = createConnection()) { + connection.bufferedWrite(Mutation.delete("TEST", KeySet.all())); + connection.commit(); + } + } + + @Before + public void clearStatistics() { + RETRY_STATISTICS.clear(); + } + + @Before + public void logStart() { + logger.fine( + "--------------------------------------------------------------\n" + + testName.getMethodName() + + " started"); + } + + @After + public void logFinished() { + logger.fine( + "--------------------------------------------------------------\n" + + testName.getMethodName() + + " finished"); + } + + /** Simple data structure to keep track of retry statistics */ + private static class RetryStatistics { + private int totalRetryAttemptsStarted; + private int totalRetryAttemptsFinished; + private int totalSuccessfulRetries; + private int totalErroredRetries; + private int totalNestedAborts; + private int totalMaxAttemptsExceeded; + private int totalConcurrentModifications; + + private void clear() { + totalRetryAttemptsStarted = 0; + totalRetryAttemptsFinished = 0; + totalSuccessfulRetries = 0; + totalErroredRetries = 0; + totalNestedAborts = 0; + totalMaxAttemptsExceeded = 0; + totalConcurrentModifications = 0; + } + } + + /** + * Static to allow access from the {@link CountTransactionRetryListener}. Statistics are + * automatically cleared before each test case. + */ + public static final RetryStatistics RETRY_STATISTICS = new RetryStatistics(); + + /** + * Simple {@link TransactionRetryListener} that keeps track of the total count of the different + * transaction retry events of a {@link Connection}. Note that as {@link + * TransactionRetryListener}s are instantiated once per connection, the listener keeps track of + * the total statistics of a connection and not only of the last transaction. + */ + public static class CountTransactionRetryListener implements TransactionRetryListener { + + @Override + public void retryStarting(Timestamp transactionStarted, long transactionId, int retryAttempt) { + RETRY_STATISTICS.totalRetryAttemptsStarted++; + } + + @Override + public void retryFinished( + Timestamp transactionStarted, long transactionId, int retryAttempt, RetryResult result) { + RETRY_STATISTICS.totalRetryAttemptsFinished++; + switch (result) { + case RETRY_ABORTED_AND_MAX_ATTEMPTS_EXCEEDED: + RETRY_STATISTICS.totalMaxAttemptsExceeded++; + break; + case RETRY_ABORTED_AND_RESTARTING: + RETRY_STATISTICS.totalNestedAborts++; + break; + case RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION: + RETRY_STATISTICS.totalConcurrentModifications++; + break; + case RETRY_ERROR: + RETRY_STATISTICS.totalErroredRetries++; + break; + case RETRY_SUCCESSFUL: + RETRY_STATISTICS.totalSuccessfulRetries++; + break; + default: + break; + } + } + } + + /** Test successful retry when the commit aborts */ + @Test + public void testCommitAborted() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // do an insert + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // do a commit that will first abort, and then on retry will succeed + connection.commit(); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalRetryAttemptsFinished, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalErroredRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalMaxAttemptsExceeded, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); + // verify that the insert succeeded + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry when an insert statement aborts */ + @Test + public void testInsertAborted() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // do an insert that will abort + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + // do a commit + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that the insert succeeded + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry when an update statement aborts */ + @Test + public void testUpdateAborted() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // insert a test record + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // do an update that will abort + connection.executeUpdate(Statement.of("UPDATE TEST SET NAME='update aborted' WHERE ID=1")); + // do a commit + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that the update succeeded + try (ResultSet rs = + connection.executeQuery( + Statement.of( + "SELECT COUNT(*) AS C FROM TEST WHERE ID=1 AND NAME='update aborted'"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry when a query aborts */ + @Test + public void testQueryAborted() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // insert a test record + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // do a query that will abort + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + // do a commit + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that the update succeeded + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry when a call to {@link ResultSet#next()} aborts */ + @Test + public void testNextCallAborted() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // do a query + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + // the first record should be accessible without any problems + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(1L))); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(2L))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // there should be only two records + assertThat(rs.next(), is(false)); + } + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that the transaction succeeded + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(2L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry after multiple aborts */ + @Test + public void testMultipleAborts() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // do three inserts which all will abort and retry + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(3))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); + // verify that the insert succeeded + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(3L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** + * Tests that a transaction retry can be successful after a select, as long as the select returns + * the same results during the retry + */ + @Test + public void testAbortAfterSelect() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // insert a test record + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + // select the test record + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(1L))); + assertThat(rs.getString("NAME"), is(equalTo("test 1"))); + assertThat(rs.next(), is(false)); + } + // do another insert that will abort and retry + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the first test record again + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(1L))); + assertThat(rs.getString("NAME"), is(equalTo("test 1"))); + assertThat(rs.next(), is(false)); + } + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + } + } + + /** + * Test a successful retry when a {@link ResultSet} has been consumed half way. The {@link + * ResultSet} should still be at the same position and still behave as if the original transaction + * did not abort. + */ + @Test + public void testAbortWithResultSetHalfway() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + // iterate one step + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(1L))); + // do another insert that will abort and retry + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + // iterate another step + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(2L))); + // ensure we are at the end of the result set + assertThat(rs.next(), is(false)); + } + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that all the inserts succeeded + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(3L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** Test successful retry after a {@link ResultSet} has been fully consumed. */ + @Test + public void testAbortWithResultSetFullyConsumed() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records and iterate over them + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing, just consume the result set + } + } + // do another insert that will abort and retry + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + // verify that all the inserts succeeded + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(3L))); + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testAbortWithConcurrentInsert() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records and consume the entire result set + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing + } + } + // open a new connection and transaction and do an additional insert + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + } + + @Test + public void testAbortWithConcurrentDelete() { + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // open a new connection and select the two test records + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // select the test records and consume the entire result set + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing + } + } + // open a new connection and transaction and remove one of the test records + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("DELETE FROM TEST WHERE ID=1")); + connection2.commit(); + } + // now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + } + + @Test + public void testAbortWithConcurrentUpdate() { + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // open a new connection and select the two test records + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // select the test records and consume the entire result set + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing + } + } + // open a new connection and transaction and update one of the test records + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("UPDATE TEST SET NAME='test updated' WHERE ID=2")); + connection2.commit(); + } + // now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + } + + /** + * Test that shows that a transaction retry is possible even when there is a concurrent insert + * that has an impact on a query that has been executed, as long as the user hasn't actually seen + * the relevant part of the result of the query + */ + @Test + public void testAbortWithUnseenConcurrentInsert() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records and consume part of the result set + ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID")); + assertThat(rs.next(), is(true)); + assertThat(rs.next(), is(true)); + // Open a new connection and transaction and do an additional insert. This insert will be + // included in a retry of the above query, but this has not yet been 'seen' by the user, + // hence is not a problem for retrying the transaction. + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // now try to do an insert that will abort. The retry should still succeed. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + // Consume the rest of the result set. The insert by the other transaction should now be + // included in the result set as the transaction retried. Although this means that the result + // is different after a retry, it is not different as seen by the user, as the user didn't + // know that the result set did not have any more results before the transaction retry. + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(3L))); + // record with id 4 should not be visible, as it was added to the transaction after the query + // was executed + assertThat(rs.next(), is(false)); + rs.close(); + connection.commit(); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + } + } + + /** + * This test shows what happens when an abort occurs on a call to {@link ResultSet#next()} on a + * {@link ResultSet} that has an concurrent insert. As long as the user hasn't consumed the {@link + * ResultSet} so far that the concurrent insert has been seen, the retry will succeed. When the + * user has consumed the {@link ResultSet} to the point where the concurrent insert is visible, + * the retry will fail. + */ + @Test + public void testAbortWithUnseenConcurrentInsertAbortOnNext() { + // no calls to next(), this should succeed + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(0), is(equalTo(1))); + // 1 call to next() should also succeed, as there were 2 records in the original result set + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(1), is(equalTo(1))); + // 2 calls to next() should also succeed, as there were 2 records in the original result set and + // the user doesn't know yet that the next call to next() will return true instead of false + // after the concurrent insert + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(2), is(equalTo(1))); + + boolean expectedException = false; + try { + // 3 calls to next() should fail, as the user would now see the inserted record + testAbortWithUnseenConcurrentInsertAbortOnNext(3); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + } + + private int testAbortWithUnseenConcurrentInsertAbortOnNext(int callsToNext) + throws AbortedDueToConcurrentModificationException { + int retries = 0; + clearTable(); + clearStatistics(); + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + int totalRecordsSeen = 0; + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records and consume part or all of the result set + ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID")); + for (int counter = 0; counter < callsToNext; counter++) { + if (rs.next()) { + totalRecordsSeen++; + } + } + // Open a new connection and transaction and do an additional insert. This insert will be + // included in a retry of the above query. Any transaction retry will fail/succeed depending + // on whether the user has consumed enough of the result set to potentially have seen this + // insert. + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // Now consume the rest of the result set, but trigger a transaction retry by aborting the + // first next() call. Without a retry, the result set should only contain 2 records. With a + // successful retry, the result set contains 3 results. The retry will only succeed as long + // as the user has not consumed enough of the result set to know whether there should have + // been a record with ID 3 or not. + + // First verify that the transaction has not yet retried. + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + + // Try to consume the rest of the result set. + // This will fail with an AbortedDueToConcurrentModificationException if the retry fails. + while (rs.next()) { + totalRecordsSeen++; + if (totalRecordsSeen == 3) { + assertThat(rs.getLong("ID"), is(equalTo(3L))); + } + } + // Verify that the transaction retried. + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + rs.close(); + connection.commit(); + retries = RETRY_STATISTICS.totalSuccessfulRetries; + } + return retries; + } + + /** + * Test that shows that a transaction that has aborted is considered to be rolled back, and new + * statements will be executed in a new transaction + */ + @Test + public void testAbortWithConcurrentInsertAndContinue() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // Select the test records and consume the entire result set. + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing + } + } + // Open a new connection and transaction and do an additional insert + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // Now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + + // the next statement should be in a new transaction as the previous transaction rolled back + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + // there should be one record from the transaction on connection2 + assertThat(rs.next(), is(true)); + assertThat(rs.next(), is(false)); + } + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. The transaction aborts at commit + *
  2. A retry starts and succeeds + *
  3. The commit is applied again and aborts again + *
  4. The retry is started again and then succeeds + *
+ */ + @Test + public void testAbortTwiceOnCommit() { + AbortInterceptor interceptor = + new AbortInterceptor(0) { + private int commitCount = 0; + + @Override + protected boolean shouldAbort(String statement, ExecutionStep step) { + if ("COMMIT".equalsIgnoreCase(statement)) { + commitCount++; + return commitCount <= 2; + } + return false; + } + }; + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + connection.commit(); + // Assert that the transaction was retried twice. + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(2))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); + // Verify that the insert succeeded. + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. The transaction aborts at commit + *
  2. A retry starts and then aborts at the insert statement + *
  3. The retry is restarted and then succeeds + *
+ */ + @Test + public void testNestedAbortOnInsert() { + AbortInterceptor interceptor = + new AbortInterceptor(0) { + private int commitCount = 0; + private int insertCount = 0; + + @Override + protected boolean shouldAbort(String statement, ExecutionStep step) { + if ("COMMIT".equalsIgnoreCase(statement)) { + commitCount++; + return commitCount == 1; + } else if (statement.startsWith("INSERT INTO TEST")) { + insertCount++; + return insertCount == 2; + } + return false; + } + }; + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + connection.commit(); + // Assert that the transaction was retried (a restarted retry is counted as one successful + // retry). + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); + // Verify that the insert succeeded. + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. The transaction aborts at commit + *
  2. A retry starts and then aborts at a next call in a result set + *
  3. The retry is restarted and then succeeds + *
+ */ + @Test + public void testNestedAbortOnNextCall() { + AbortInterceptor interceptor = + new AbortInterceptor(0) { + private int nextCallsDuringRetry = 0; + private int commitCount = 0; + + @Override + protected boolean shouldAbort(String statement, ExecutionStep step) { + if ("COMMIT".equalsIgnoreCase(statement)) { + // Note that commit always has ExecutionStep == EXECUTE_STATEMENT, as a commit can + // never + // really be retried (it is always the last statement in a transaction, and if it + // fails + // because of an aborted exception, the entire transaction is retried, and the commit + // statement is then applied again). + commitCount++; + return commitCount == 1; + } else if (statement.equals("SELECT * FROM TEST ORDER BY ID") + && step == ExecutionStep.RETRY_NEXT_ON_RESULT_SET) { + nextCallsDuringRetry++; + return nextCallsDuringRetry == 1; + } + return false; + } + }; + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // Insert two test records. + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // Select the test records. + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + // Iterate one step. This step should abort during the retry the first time. + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(1L))); + // Do another insert that will not be visible to the result set. + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + // iterate another step + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("ID"), is(equalTo(2L))); + // Ensure we are at the end of the result set. + assertThat(rs.next(), is(false)); + } + connection.commit(); + // Verify that the transaction retried. + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); + // Verify that all the inserts succeeded. + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(3L))); + assertThat(rs.next(), is(false)); + } + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. Transaction 1 does two inserts in table TEST + *
  2. Transaction 1 selects all records from table TEST + *
  3. Transaction 2 inserts a record into TEST + *
  4. Transaction 1 does another insert into TEST that aborts + *
  5. Transaction 1 starts a retry that aborts at the SELECT statement (i.e. before the + * concurrent modification has been seen) + *
  6. Transaction 1 restarts the retry that now aborts due to a concurrent modification + * exception + *
+ */ + @Test + public void testNestedAbortWithConcurrentInsert() { + AbortInterceptor interceptor = + new AbortInterceptor(0) { + private boolean alreadyAborted = false; + + @Override + protected boolean shouldAbort(String statement, ExecutionStep step) { + // Abort during retry on the select statement. + if (!alreadyAborted + && statement.equals("SELECT * FROM TEST ORDER BY ID") + && step == ExecutionStep.RETRY_STATEMENT) { + alreadyAborted = true; + return true; + } + return super.shouldAbort(statement, step); + } + }; + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert two test records + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + // select the test records and consume the entire result set + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing + } + } + // open a new connection and transaction and do an additional insert + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // Now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(expectedException, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit + *
  2. Transaction 1 updates the names of all records in the TEST table + *
  3. Transaction 2 inserts a record in the TEST table and commits + *
  4. Transaction 1 does another insert into TEST that aborts + *
  5. Transaction 1 starts a retry that aborts due to a concurrent modification exception as + * the number of updated records will be different + *
+ */ + @Test + public void testAbortWithDifferentUpdateCount() { + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // open a new connection and update one of the records + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + connection.executeUpdate( + Statement.of("UPDATE TEST SET NAME='test update that will fail' WHERE TRUE")); + // open a new connection and transaction and update the same test record + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + connection2.commit(); + } + // Now try to do an insert that will abort. The retry should now fail as there has been a + // concurrent modification. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertThat(expectedException, is(true)); + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit + *
  2. Try to query a non-existing table. This will lead to an exception. + *
  3. Query all the records from the TEST table and consume the result set + *
  4. Insert another record into TEST that aborts + *
  5. The transaction successfully retries + *
+ */ + @Test + public void testAbortWithExceptionOnSelect() { + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // do a select that will fail + boolean expectedException = false; + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { + while (rs.next()) { + // do nothing + } + } catch (SpannerException e) { + // expected + expectedException = true; + } + assertThat(expectedException, is(true)); + // do a select that will succeed + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // now try to do an insert that will abort. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + } + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit. + *
  2. Try to query the non-existing table FOO. This will lead to an exception. + *
  3. Query all the records from the TEST table and consume the result set. + *
  4. Open another connection and create the table FOO. + *
  5. Insert another record into TEST that aborts. + *
  6. The transaction is internally retried. The retry fails as the SELECT statement on FOO + * will now succeed. + *
+ */ + @Test + public void testAbortWithExceptionOnSelectAndConcurrentModification() { + boolean abortedDueToConcurrentModification = false; + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // do a select that will fail + boolean expectedException = false; + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { + while (rs.next()) { + // do nothing + } + } catch (SpannerException e) { + // expected + expectedException = true; + } + assertThat(expectedException, is(true)); + // do a select that will succeed + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // CREATE FOO + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + } + // Now try to do an insert that will abort. The subsequent retry will fail as the SELECT * + // FROM FOO now returns a result. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + abortedDueToConcurrentModification = true; + } + } + // DROP FOO regardless of the result to avoid any interference with other test cases + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute(Statement.of("DROP TABLE FOO")); + } + assertThat(abortedDueToConcurrentModification, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit. + *
  2. Try to insert a record in the non-existing table FOO. This will lead to an exception. + *
  3. Query all the records from the TEST table and consume the result set. + *
  4. Open another connection and create the table FOO. + *
  5. Insert another record into TEST that aborts. + *
  6. The transaction is internally retried. The retry fails as the insert statement on FOO + * will now succeed. + *
+ */ + @Test + public void testAbortWithExceptionOnInsertAndConcurrentModification() { + boolean abortedDueToConcurrentModification = false; + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // do an insert that will fail + boolean expectedException = false; + try { + connection.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); + } catch (SpannerException e) { + // expected + expectedException = true; + } + assertThat(expectedException, is(true)); + // do a select that will succeed + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // CREATE FOO + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + } + // Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO + // FOO now succeeds. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + abortedDueToConcurrentModification = true; + } + } + // DROP FOO regardless of the result to avoid any interference with other test cases + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute(Statement.of("DROP TABLE FOO")); + } + assertThat(abortedDueToConcurrentModification, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit. + *
  2. Create the table FOO and insert a test record. + *
  3. Query the table FOO. + *
  4. Query all the records from the TEST table and consume the result set. + *
  5. Open another connection and drop the table FOO. + *
  6. Insert another record into TEST that aborts. + *
  7. The transaction is internally retried. The retry fails as the SELECT statement on FOO + * will now fail. + *
+ */ + @Test + public void testAbortWithDroppedTableConcurrentModification() { + boolean abortedDueToConcurrentModification = false; + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // CREATE FOO + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { + while (rs.next()) { + // do nothing + } + } + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // DROP FOO using a different connection + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute(Statement.of("DROP TABLE FOO")); + } + // Now try to do an insert that will abort. The subsequent retry will fail as the SELECT * + // FROM FOO now fails. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + abortedDueToConcurrentModification = true; + } + } + assertThat(abortedDueToConcurrentModification, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit. + *
  2. Create the table FOO and insert a test record and commit. + *
  3. Insert another record into the table FOO. + *
  4. Query all the records from the TEST table and consume the result set. + *
  5. Open another connection and drop the table FOO. + *
  6. Insert another record into TEST that aborts. + *
  7. The transaction is internally retried. The retry fails as the INSERT statement on FOO + * will now fail. + *
+ */ + @Test + public void testAbortWithInsertOnDroppedTableConcurrentModification() { + boolean abortedDueToConcurrentModification = false; + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // CREATE FOO + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert a record into FOO + connection.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (2, 'test 2')")); + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // DROP FOO using a different connection + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute(Statement.of("DROP TABLE FOO")); + } + // Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO + // FOO now fails. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + try { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); + } catch (AbortedDueToConcurrentModificationException e) { + abortedDueToConcurrentModification = true; + } + } + assertThat(abortedDueToConcurrentModification, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + + /** + * Test that shows the following: + * + *
    + *
  1. Insert two records into table TEST and commit. + *
  2. Create the table FOO and insert two test records and commit. + *
  3. Query all the records from the TEST table and consume the result set. + *
  4. Query all the records from the FOO table and consume only part of the result set. + *
  5. Open another connection and drop the table FOO. + *
  6. Try to consume the rest of the FOO result set. This aborts. + *
  7. The transaction is internally retried. The retry fails as the SELECT statement on FOO + * will now fail. + *
+ */ + @Test + public void testAbortWithCursorHalfwayDroppedTableConcurrentModification() { + boolean abortedDueToConcurrentModification = false; + AbortInterceptor interceptor = new AbortInterceptor(0); + // first insert two test records + try (ITConnection connection = createConnection()) { + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); + connection.commit(); + } + // CREATE FOO + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); + connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (2, 'test 2')")); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { + while (rs.next()) { + // do nothing + } + } + // SELECT FROM FOO and consume part of the result set + ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO")); + assertThat(rs.next(), is(true)); + // DROP FOO using a different connection + try (ITConnection connection2 = createConnection()) { + connection2.setAutocommit(true); + connection2.execute(Statement.of("DROP TABLE FOO")); + } + // try to continue to consume the result set, but this will now abort. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + try { + // This will fail as the retry will not succeed. + rs.next(); + } catch (AbortedDueToConcurrentModificationException e) { + abortedDueToConcurrentModification = true; + } finally { + rs.close(); + } + } + assertThat(abortedDueToConcurrentModification, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + } + + /** Test the successful retry of a transaction with a large {@link ResultSet} */ + @Test + public void testRetryLargeResultSet() { + final int NUMBER_OF_TEST_RECORDS = 100000; + final long UPDATED_RECORDS = 1000L; + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = createConnection()) { + // insert test records + for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) { + connection.bufferedWrite( + Mutation.newInsertBuilder("TEST").set("ID").to(i).set("NAME").to("test " + i).build()); + if (i % 1000 == 0) { + connection.commit(); + } + } + connection.commit(); + } + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // select the test records and iterate over them + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing, just consume the result set + } + } + // Do an update that will abort and retry. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + connection.executeUpdate( + Statement.newBuilder("UPDATE TEST SET NAME='updated' WHERE ID<@max_id") + .bind("max_id") + .to(UPDATED_RECORDS) + .build()); + connection.commit(); + // verify that the update succeeded + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE NAME='updated'"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(UPDATED_RECORDS))); + assertThat(rs.next(), is(false)); + } + // Verify that the transaction retried. + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + } + } + + /** Test the successful retry of a transaction with a high chance of multiple aborts */ + @Test + public void testRetryHighAbortRate() { + final int NUMBER_OF_TEST_RECORDS = 10000; + final long UPDATED_RECORDS = 1000L; + // abort on 25% of all statements + AbortInterceptor interceptor = new AbortInterceptor(0.25D); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // insert test records + for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) { + connection.bufferedWrite( + Mutation.newInsertBuilder("TEST").set("ID").to(i).set("NAME").to("test " + i).build()); + if (i % 1000 == 0) { + connection.commit(); + } + } + connection.commit(); + // select the test records and iterate over them + // reduce the abort rate to 0.01% as each next() call could abort + interceptor.setProbability(0.0001D); + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + while (rs.next()) { + // do nothing, just consume the result set + } + } + // increase the abort rate to 50% + interceptor.setProbability(0.50D); + connection.executeUpdate( + Statement.newBuilder("UPDATE TEST SET NAME='updated' WHERE ID<@max_id") + .bind("max_id") + .to(UPDATED_RECORDS) + .build()); + connection.commit(); + // verify that the update succeeded + try (ResultSet rs = + connection.executeQuery( + Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE NAME='updated'"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(UPDATED_RECORDS))); + assertThat(rs.next(), is(false)); + } + connection.commit(); + } catch (AbortedException e) { + // This could happen if the number of aborts exceeds the max number of retries. + logger.log(Level.FINE, "testRetryHighAbortRate aborted because of too many retries", e); + } + logger.fine("Total number of retries started: " + RETRY_STATISTICS.totalRetryAttemptsStarted); + logger.fine("Total number of retries finished: " + RETRY_STATISTICS.totalRetryAttemptsFinished); + logger.fine("Total number of retries successful: " + RETRY_STATISTICS.totalSuccessfulRetries); + logger.fine("Total number of retries aborted: " + RETRY_STATISTICS.totalNestedAborts); + logger.fine( + "Total number of times the max retry count was exceeded: " + + RETRY_STATISTICS.totalMaxAttemptsExceeded); + } + + @Test + public void testAbortWithConcurrentInsertOnEmptyTable() { + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // select the test records but do not consume the result set + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + // Open a new connection and transaction and do an insert. This insert will be + // included in a retry of the above query, but this has not yet been 'seen' by the user, + // hence is not a problem for retrying the transaction. + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection2.commit(); + } + // Now try to consume the result set, but the call to next() will throw an AbortedException. + // The retry should still succeed. + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + assertThat(rs.next(), is(true)); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(rs.next(), is(false)); + } + connection.commit(); + + // Now do the same, but this time we will consume the empty result set. The retry should now + // fail. + clearTable(); + clearStatistics(); + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { + assertThat(rs.next(), is(false)); + // Open a new connection and transaction and do an insert. This insert will be + // included in a retry of the above query, and this time it will cause the retry to fail. + try (ITConnection connection2 = createConnection()) { + connection2.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); + connection2.commit(); + } + // this time the abort will occur on the call to commit() + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + boolean expectedException = false; + try { + connection.commit(); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + // No successful retries. + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertThat(expectedException, is(true)); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql new file mode 100644 index 000000000000..fe8afd86e970 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql @@ -0,0 +1,11078 @@ +NEW_CONNECTION; +show variable autocommit; +NEW_CONNECTION; +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +show variable autocommit; +NEW_CONNECTION; + show variable autocommit; +NEW_CONNECTION; + show variable autocommit; +NEW_CONNECTION; + + + +show variable autocommit; +NEW_CONNECTION; +show variable autocommit ; +NEW_CONNECTION; +show variable autocommit ; +NEW_CONNECTION; +show variable autocommit + +; +NEW_CONNECTION; +show variable autocommit; +NEW_CONNECTION; +show variable autocommit; +NEW_CONNECTION; +show +variable +autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable autocommit; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-autocommit; +NEW_CONNECTION; +show variable readonly; +NEW_CONNECTION; +SHOW VARIABLE READONLY; +NEW_CONNECTION; +show variable readonly; +NEW_CONNECTION; + show variable readonly; +NEW_CONNECTION; + show variable readonly; +NEW_CONNECTION; + + + +show variable readonly; +NEW_CONNECTION; +show variable readonly ; +NEW_CONNECTION; +show variable readonly ; +NEW_CONNECTION; +show variable readonly + +; +NEW_CONNECTION; +show variable readonly; +NEW_CONNECTION; +show variable readonly; +NEW_CONNECTION; +show +variable +readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable readonly; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-readonly; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +SHOW VARIABLE RETRY_ABORTS_INTERNALLY; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; + show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; + show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; + + + +show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally ; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally ; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally + +; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +show +variable +retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally bar; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally%; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally_; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally&; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally$; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally@; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally!; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally*; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally(; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally); +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally-; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally+; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally-#; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally/; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally\; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally?; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally-/; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally/#; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable retry_aborts_internally; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable retry_aborts_internally/-; +NEW_CONNECTION; +set readonly=false; +set autocommit=false; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-retry_aborts_internally; +NEW_CONNECTION; +show variable autocommit_dml_mode; +NEW_CONNECTION; +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +show variable autocommit_dml_mode; +NEW_CONNECTION; + show variable autocommit_dml_mode; +NEW_CONNECTION; + show variable autocommit_dml_mode; +NEW_CONNECTION; + + + +show variable autocommit_dml_mode; +NEW_CONNECTION; +show variable autocommit_dml_mode ; +NEW_CONNECTION; +show variable autocommit_dml_mode ; +NEW_CONNECTION; +show variable autocommit_dml_mode + +; +NEW_CONNECTION; +show variable autocommit_dml_mode; +NEW_CONNECTION; +show variable autocommit_dml_mode; +NEW_CONNECTION; +show +variable +autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable autocommit_dml_mode; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-autocommit_dml_mode; +NEW_CONNECTION; +show variable statement_timeout; +NEW_CONNECTION; +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +show variable statement_timeout; +NEW_CONNECTION; + show variable statement_timeout; +NEW_CONNECTION; + show variable statement_timeout; +NEW_CONNECTION; + + + +show variable statement_timeout; +NEW_CONNECTION; +show variable statement_timeout ; +NEW_CONNECTION; +show variable statement_timeout ; +NEW_CONNECTION; +show variable statement_timeout + +; +NEW_CONNECTION; +show variable statement_timeout; +NEW_CONNECTION; +show variable statement_timeout; +NEW_CONNECTION; +show +variable +statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable statement_timeout; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-statement_timeout; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; + show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; + show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; + + + +show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp ; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp ; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp + +; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +show +variable +read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp bar; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp%; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp_; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp&; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp$; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp@; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp!; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp*; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp(; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp); +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp-; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp+; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp-#; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp/; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp\; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp?; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp-/; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp/#; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable read_timestamp; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_timestamp/-; +NEW_CONNECTION; +set readonly = true; +SELECT 1 AS TEST; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-read_timestamp; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; + show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; + show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; + + + +show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp ; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp ; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp + +; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +show +variable +commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp bar; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp%; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp_; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp&; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp$; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp@; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp!; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp*; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp(; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp); +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp-; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp+; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp-#; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp/; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp\; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp?; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp-/; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp/#; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable commit_timestamp; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable commit_timestamp/-; +NEW_CONNECTION; +update foo set bar=1; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-commit_timestamp; +NEW_CONNECTION; +show variable read_only_staleness; +NEW_CONNECTION; +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +show variable read_only_staleness; +NEW_CONNECTION; + show variable read_only_staleness; +NEW_CONNECTION; + show variable read_only_staleness; +NEW_CONNECTION; + + + +show variable read_only_staleness; +NEW_CONNECTION; +show variable read_only_staleness ; +NEW_CONNECTION; +show variable read_only_staleness ; +NEW_CONNECTION; +show variable read_only_staleness + +; +NEW_CONNECTION; +show variable read_only_staleness; +NEW_CONNECTION; +show variable read_only_staleness; +NEW_CONNECTION; +show +variable +read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable read_only_staleness; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-read_only_staleness; +NEW_CONNECTION; +begin; +NEW_CONNECTION; +BEGIN; +NEW_CONNECTION; +begin; +NEW_CONNECTION; + begin; +NEW_CONNECTION; + begin; +NEW_CONNECTION; + + + +begin; +NEW_CONNECTION; +begin ; +NEW_CONNECTION; +begin ; +NEW_CONNECTION; +begin + +; +NEW_CONNECTION; +begin; +NEW_CONNECTION; +begin; +NEW_CONNECTION; +begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-begin; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/-; +NEW_CONNECTION; +start; +NEW_CONNECTION; +START; +NEW_CONNECTION; +start; +NEW_CONNECTION; + start; +NEW_CONNECTION; + start; +NEW_CONNECTION; + + + +start; +NEW_CONNECTION; +start ; +NEW_CONNECTION; +start ; +NEW_CONNECTION; +start + +; +NEW_CONNECTION; +start; +NEW_CONNECTION; +start; +NEW_CONNECTION; +start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-start; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/-; +NEW_CONNECTION; +begin transaction; +NEW_CONNECTION; +BEGIN TRANSACTION; +NEW_CONNECTION; +begin transaction; +NEW_CONNECTION; + begin transaction; +NEW_CONNECTION; + begin transaction; +NEW_CONNECTION; + + + +begin transaction; +NEW_CONNECTION; +begin transaction ; +NEW_CONNECTION; +begin transaction ; +NEW_CONNECTION; +begin transaction + +; +NEW_CONNECTION; +begin transaction; +NEW_CONNECTION; +begin transaction; +NEW_CONNECTION; +begin +transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin%transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin_transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin&transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin$transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin@transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin!transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin*transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin(transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin)transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin+transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-#transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin\transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin?transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin-/transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/#transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-begin transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin transaction/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +begin/-transaction; +NEW_CONNECTION; +start transaction; +NEW_CONNECTION; +START TRANSACTION; +NEW_CONNECTION; +start transaction; +NEW_CONNECTION; + start transaction; +NEW_CONNECTION; + start transaction; +NEW_CONNECTION; + + + +start transaction; +NEW_CONNECTION; +start transaction ; +NEW_CONNECTION; +start transaction ; +NEW_CONNECTION; +start transaction + +; +NEW_CONNECTION; +start transaction; +NEW_CONNECTION; +start transaction; +NEW_CONNECTION; +start +transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start%transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start_transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start&transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start$transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start@transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start!transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start*transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start(transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start)transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start+transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-#transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start\transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start?transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start-/transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/#transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-start transaction; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start transaction/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start/-transaction; +NEW_CONNECTION; +begin transaction; +commit; +NEW_CONNECTION; +begin transaction; +COMMIT; +NEW_CONNECTION; +begin transaction; +commit; +NEW_CONNECTION; +begin transaction; + commit; +NEW_CONNECTION; +begin transaction; + commit; +NEW_CONNECTION; +begin transaction; + + + +commit; +NEW_CONNECTION; +begin transaction; +commit ; +NEW_CONNECTION; +begin transaction; +commit ; +NEW_CONNECTION; +begin transaction; +commit + +; +NEW_CONNECTION; +begin transaction; +commit; +NEW_CONNECTION; +begin transaction; +commit; +NEW_CONNECTION; +begin transaction; +commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit bar; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +%commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +_commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +&commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +$commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +@commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +!commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +*commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +(commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +)commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT ++commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +\commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +?commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-commit; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/-; +NEW_CONNECTION; +begin transaction; +commit transaction; +NEW_CONNECTION; +begin transaction; +COMMIT TRANSACTION; +NEW_CONNECTION; +begin transaction; +commit transaction; +NEW_CONNECTION; +begin transaction; + commit transaction; +NEW_CONNECTION; +begin transaction; + commit transaction; +NEW_CONNECTION; +begin transaction; + + + +commit transaction; +NEW_CONNECTION; +begin transaction; +commit transaction ; +NEW_CONNECTION; +begin transaction; +commit transaction ; +NEW_CONNECTION; +begin transaction; +commit transaction + +; +NEW_CONNECTION; +begin transaction; +commit transaction; +NEW_CONNECTION; +begin transaction; +commit transaction; +NEW_CONNECTION; +begin transaction; +commit +transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction bar; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +%commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit%transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +_commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit_transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +&commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit&transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +$commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit$transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +@commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit@transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +!commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit!transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +*commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit*transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +(commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit(transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +)commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit)transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT ++commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit+transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-#transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +\commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit\transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +?commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit?transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit-/transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/#transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-commit transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit transaction/-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +commit/-transaction; +NEW_CONNECTION; +begin transaction; +rollback; +NEW_CONNECTION; +begin transaction; +ROLLBACK; +NEW_CONNECTION; +begin transaction; +rollback; +NEW_CONNECTION; +begin transaction; + rollback; +NEW_CONNECTION; +begin transaction; + rollback; +NEW_CONNECTION; +begin transaction; + + + +rollback; +NEW_CONNECTION; +begin transaction; +rollback ; +NEW_CONNECTION; +begin transaction; +rollback ; +NEW_CONNECTION; +begin transaction; +rollback + +; +NEW_CONNECTION; +begin transaction; +rollback; +NEW_CONNECTION; +begin transaction; +rollback; +NEW_CONNECTION; +begin transaction; +rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback bar; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +%rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +_rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +&rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +$rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +@rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +!rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +*rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +(rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +)rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT ++rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +\rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +?rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-rollback; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/-; +NEW_CONNECTION; +begin transaction; +rollback transaction; +NEW_CONNECTION; +begin transaction; +ROLLBACK TRANSACTION; +NEW_CONNECTION; +begin transaction; +rollback transaction; +NEW_CONNECTION; +begin transaction; + rollback transaction; +NEW_CONNECTION; +begin transaction; + rollback transaction; +NEW_CONNECTION; +begin transaction; + + + +rollback transaction; +NEW_CONNECTION; +begin transaction; +rollback transaction ; +NEW_CONNECTION; +begin transaction; +rollback transaction ; +NEW_CONNECTION; +begin transaction; +rollback transaction + +; +NEW_CONNECTION; +begin transaction; +rollback transaction; +NEW_CONNECTION; +begin transaction; +rollback transaction; +NEW_CONNECTION; +begin transaction; +rollback +transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction bar; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +%rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction%; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback%transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +_rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction_; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback_transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +&rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction&; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback&transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +$rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction$; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback$transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +@rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction@; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback@transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +!rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction!; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback!transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +*rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction*; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback*transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +(rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction(; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback(transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +)rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction); +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback)transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT ++rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction+; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback+transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction-#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-#transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +\rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction\; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback\transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +?rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction?; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback?transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction-/; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback-/transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction/#; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/#transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-rollback transaction; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback transaction/-; +NEW_CONNECTION; +begin transaction; +@EXPECT EXCEPTION INVALID_ARGUMENT +rollback/-transaction; +NEW_CONNECTION; +start batch ddl; +NEW_CONNECTION; +START BATCH DDL; +NEW_CONNECTION; +start batch ddl; +NEW_CONNECTION; + start batch ddl; +NEW_CONNECTION; + start batch ddl; +NEW_CONNECTION; + + + +start batch ddl; +NEW_CONNECTION; +start batch ddl ; +NEW_CONNECTION; +start batch ddl ; +NEW_CONNECTION; +start batch ddl + +; +NEW_CONNECTION; +start batch ddl; +NEW_CONNECTION; +start batch ddl; +NEW_CONNECTION; +start +batch +ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch%ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch_ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch&ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch$ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch@ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch!ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch*ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch(ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch)ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch+ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-#ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch\ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch?ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-/ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/#ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-start batch ddl; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch ddl/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/-ddl; +NEW_CONNECTION; +start batch dml; +NEW_CONNECTION; +START BATCH DML; +NEW_CONNECTION; +start batch dml; +NEW_CONNECTION; + start batch dml; +NEW_CONNECTION; + start batch dml; +NEW_CONNECTION; + + + +start batch dml; +NEW_CONNECTION; +start batch dml ; +NEW_CONNECTION; +start batch dml ; +NEW_CONNECTION; +start batch dml + +; +NEW_CONNECTION; +start batch dml; +NEW_CONNECTION; +start batch dml; +NEW_CONNECTION; +start +batch +dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch%dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch_dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch&dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch$dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch@dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch!dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch*dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch(dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch)dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch+dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-#dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch\dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch?dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch-/dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/#dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-start batch dml; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch dml/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +start batch/-dml; +NEW_CONNECTION; +start batch ddl; +run batch; +NEW_CONNECTION; +start batch ddl; +RUN BATCH; +NEW_CONNECTION; +start batch ddl; +run batch; +NEW_CONNECTION; +start batch ddl; + run batch; +NEW_CONNECTION; +start batch ddl; + run batch; +NEW_CONNECTION; +start batch ddl; + + + +run batch; +NEW_CONNECTION; +start batch ddl; +run batch ; +NEW_CONNECTION; +start batch ddl; +run batch ; +NEW_CONNECTION; +start batch ddl; +run batch + +; +NEW_CONNECTION; +start batch ddl; +run batch; +NEW_CONNECTION; +start batch ddl; +run batch; +NEW_CONNECTION; +start batch ddl; +run +batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch bar; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +%run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch%; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run%batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +_run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch_; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run_batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +&run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch&; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run&batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +$run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch$; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run$batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +@run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch@; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run@batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +!run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch!; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run!batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +*run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch*; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run*batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +(run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch(; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run(batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +)run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch); +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run)batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch-; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run-batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT ++run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch+; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run+batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch-#; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run-#batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch/; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run/batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +\run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch\; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run\batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +?run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch?; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run?batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch-/; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run-/batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch/#; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run/#batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-run batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run batch/-; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +run/-batch; +NEW_CONNECTION; +start batch ddl; +abort batch; +NEW_CONNECTION; +start batch ddl; +ABORT BATCH; +NEW_CONNECTION; +start batch ddl; +abort batch; +NEW_CONNECTION; +start batch ddl; + abort batch; +NEW_CONNECTION; +start batch ddl; + abort batch; +NEW_CONNECTION; +start batch ddl; + + + +abort batch; +NEW_CONNECTION; +start batch ddl; +abort batch ; +NEW_CONNECTION; +start batch ddl; +abort batch ; +NEW_CONNECTION; +start batch ddl; +abort batch + +; +NEW_CONNECTION; +start batch ddl; +abort batch; +NEW_CONNECTION; +start batch ddl; +abort batch; +NEW_CONNECTION; +start batch ddl; +abort +batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch bar; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +%abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch%; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort%batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +_abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch_; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort_batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +&abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch&; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort&batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +$abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch$; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort$batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +@abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch@; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort@batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +!abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch!; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort!batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +*abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch*; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort*batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +(abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch(; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort(batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +)abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch); +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort)batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch-; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort-batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT ++abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch+; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort+batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch-#; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort-#batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch/; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort/batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +\abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch\; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort\batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +?abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch?; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort?batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch-/; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort-/batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch/#; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort/#batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-abort batch; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort batch/-; +NEW_CONNECTION; +start batch ddl; +@EXPECT EXCEPTION INVALID_ARGUMENT +abort/-batch; +NEW_CONNECTION; +set autocommit = true; +NEW_CONNECTION; +SET AUTOCOMMIT = TRUE; +NEW_CONNECTION; +set autocommit = true; +NEW_CONNECTION; + set autocommit = true; +NEW_CONNECTION; + set autocommit = true; +NEW_CONNECTION; + + + +set autocommit = true; +NEW_CONNECTION; +set autocommit = true ; +NEW_CONNECTION; +set autocommit = true ; +NEW_CONNECTION; +set autocommit = true + +; +NEW_CONNECTION; +set autocommit = true; +NEW_CONNECTION; +set autocommit = true; +NEW_CONNECTION; +set +autocommit += +true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =%true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =_true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =&true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =$true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =@true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =!true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =*true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =(true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =)true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =+true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-#true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =\true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =?true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-/true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/#true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set autocommit = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = true/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/-true; +NEW_CONNECTION; +set autocommit = false; +NEW_CONNECTION; +SET AUTOCOMMIT = FALSE; +NEW_CONNECTION; +set autocommit = false; +NEW_CONNECTION; + set autocommit = false; +NEW_CONNECTION; + set autocommit = false; +NEW_CONNECTION; + + + +set autocommit = false; +NEW_CONNECTION; +set autocommit = false ; +NEW_CONNECTION; +set autocommit = false ; +NEW_CONNECTION; +set autocommit = false + +; +NEW_CONNECTION; +set autocommit = false; +NEW_CONNECTION; +set autocommit = false; +NEW_CONNECTION; +set +autocommit += +false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =%false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =_false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =&false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =$false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =@false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =!false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =*false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =(false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =)false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =+false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-#false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =\false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =?false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =-/false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/#false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set autocommit = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit = false/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit =/-false; +NEW_CONNECTION; +set readonly = true; +NEW_CONNECTION; +SET READONLY = TRUE; +NEW_CONNECTION; +set readonly = true; +NEW_CONNECTION; + set readonly = true; +NEW_CONNECTION; + set readonly = true; +NEW_CONNECTION; + + + +set readonly = true; +NEW_CONNECTION; +set readonly = true ; +NEW_CONNECTION; +set readonly = true ; +NEW_CONNECTION; +set readonly = true + +; +NEW_CONNECTION; +set readonly = true; +NEW_CONNECTION; +set readonly = true; +NEW_CONNECTION; +set +readonly += +true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =%true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =_true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =&true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =$true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =@true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =!true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =*true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =(true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =)true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =+true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-#true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =\true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =?true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-/true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/#true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set readonly = true; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = true/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/-true; +NEW_CONNECTION; +set readonly = false; +NEW_CONNECTION; +SET READONLY = FALSE; +NEW_CONNECTION; +set readonly = false; +NEW_CONNECTION; + set readonly = false; +NEW_CONNECTION; + set readonly = false; +NEW_CONNECTION; + + + +set readonly = false; +NEW_CONNECTION; +set readonly = false ; +NEW_CONNECTION; +set readonly = false ; +NEW_CONNECTION; +set readonly = false + +; +NEW_CONNECTION; +set readonly = false; +NEW_CONNECTION; +set readonly = false; +NEW_CONNECTION; +set +readonly += +false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =%false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =_false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =&false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =$false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =@false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =!false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =*false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =(false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =)false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =+false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-#false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =\false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =?false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =-/false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/#false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set readonly = false; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly = false/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set readonly =/-false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +SET RETRY_ABORTS_INTERNALLY = TRUE; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + + + +set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true ; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true ; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true + +; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set +retry_aborts_internally += +true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true bar; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true%; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =%true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true_; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =_true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true&; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =&true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true$; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =$true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true@; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =@true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true!; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =!true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true*; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =*true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true(; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =(true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true); +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =)true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true-; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true+; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =+true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true-#; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-#true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true/; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true\; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =\true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true?; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =?true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true-/; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-/true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true/#; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/#true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set retry_aborts_internally = true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = true/-; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/-true; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +SET RETRY_ABORTS_INTERNALLY = FALSE; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; + + + +set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false ; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false ; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false + +; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +set +retry_aborts_internally += +false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false bar; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false%; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =%false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false_; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =_false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false&; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =&false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false$; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =$false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false@; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =@false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false!; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =!false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false*; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =*false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false(; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =(false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false); +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =)false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false-; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false+; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =+false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false-#; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-#false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false/; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false\; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =\false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false?; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =?false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false-/; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =-/false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false/#; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/#false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set retry_aborts_internally = false; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally = false/-; +NEW_CONNECTION; +set readonly = false; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set retry_aborts_internally =/-false; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +set autocommit_dml_mode='partitioned_non_atomic'; +NEW_CONNECTION; + set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; + set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; + + + +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC' ; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC' ; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC' + +; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +set +autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-autocommit_dml_mode='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +NEW_CONNECTION; +set autocommit_dml_mode='transactional'; +NEW_CONNECTION; + set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; + set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; + + + +set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL' ; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL' ; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL' + +; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +set +autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set autocommit_dml_mode='TRANSACTIONAL'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-autocommit_dml_mode='TRANSACTIONAL'; +NEW_CONNECTION; +set statement_timeout=null; +NEW_CONNECTION; +SET STATEMENT_TIMEOUT=NULL; +NEW_CONNECTION; +set statement_timeout=null; +NEW_CONNECTION; + set statement_timeout=null; +NEW_CONNECTION; + set statement_timeout=null; +NEW_CONNECTION; + + + +set statement_timeout=null; +NEW_CONNECTION; +set statement_timeout=null ; +NEW_CONNECTION; +set statement_timeout=null ; +NEW_CONNECTION; +set statement_timeout=null + +; +NEW_CONNECTION; +set statement_timeout=null; +NEW_CONNECTION; +set statement_timeout=null; +NEW_CONNECTION; +set +statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set statement_timeout=null; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout=null/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-statement_timeout=null; +NEW_CONNECTION; +set statement_timeout='1s'; +NEW_CONNECTION; +SET STATEMENT_TIMEOUT='1S'; +NEW_CONNECTION; +set statement_timeout='1s'; +NEW_CONNECTION; + set statement_timeout='1s'; +NEW_CONNECTION; + set statement_timeout='1s'; +NEW_CONNECTION; + + + +set statement_timeout='1s'; +NEW_CONNECTION; +set statement_timeout='1s' ; +NEW_CONNECTION; +set statement_timeout='1s' ; +NEW_CONNECTION; +set statement_timeout='1s' + +; +NEW_CONNECTION; +set statement_timeout='1s'; +NEW_CONNECTION; +set statement_timeout='1s'; +NEW_CONNECTION; +set +statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set statement_timeout='1s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='1s'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-statement_timeout='1s'; +NEW_CONNECTION; +set statement_timeout='100ms'; +NEW_CONNECTION; +SET STATEMENT_TIMEOUT='100MS'; +NEW_CONNECTION; +set statement_timeout='100ms'; +NEW_CONNECTION; + set statement_timeout='100ms'; +NEW_CONNECTION; + set statement_timeout='100ms'; +NEW_CONNECTION; + + + +set statement_timeout='100ms'; +NEW_CONNECTION; +set statement_timeout='100ms' ; +NEW_CONNECTION; +set statement_timeout='100ms' ; +NEW_CONNECTION; +set statement_timeout='100ms' + +; +NEW_CONNECTION; +set statement_timeout='100ms'; +NEW_CONNECTION; +set statement_timeout='100ms'; +NEW_CONNECTION; +set +statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set statement_timeout='100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='100ms'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-statement_timeout='100ms'; +NEW_CONNECTION; +set statement_timeout='10000us'; +NEW_CONNECTION; +SET STATEMENT_TIMEOUT='10000US'; +NEW_CONNECTION; +set statement_timeout='10000us'; +NEW_CONNECTION; + set statement_timeout='10000us'; +NEW_CONNECTION; + set statement_timeout='10000us'; +NEW_CONNECTION; + + + +set statement_timeout='10000us'; +NEW_CONNECTION; +set statement_timeout='10000us' ; +NEW_CONNECTION; +set statement_timeout='10000us' ; +NEW_CONNECTION; +set statement_timeout='10000us' + +; +NEW_CONNECTION; +set statement_timeout='10000us'; +NEW_CONNECTION; +set statement_timeout='10000us'; +NEW_CONNECTION; +set +statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set statement_timeout='10000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='10000us'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-statement_timeout='10000us'; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +SET STATEMENT_TIMEOUT='9223372036854775807NS'; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; + set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; + set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; + + + +set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns' ; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns' ; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns' + +; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +set +statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set statement_timeout='9223372036854775807ns'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-statement_timeout='9223372036854775807ns'; +NEW_CONNECTION; +set autocommit = false; +set transaction read only; +NEW_CONNECTION; +set autocommit = false; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +set autocommit = false; +set transaction read only; +NEW_CONNECTION; +set autocommit = false; + set transaction read only; +NEW_CONNECTION; +set autocommit = false; + set transaction read only; +NEW_CONNECTION; +set autocommit = false; + + + +set transaction read only; +NEW_CONNECTION; +set autocommit = false; +set transaction read only ; +NEW_CONNECTION; +set autocommit = false; +set transaction read only ; +NEW_CONNECTION; +set autocommit = false; +set transaction read only + +; +NEW_CONNECTION; +set autocommit = false; +set transaction read only; +NEW_CONNECTION; +set autocommit = false; +set transaction read only; +NEW_CONNECTION; +set autocommit = false; +set +transaction +read +only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only bar; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only%; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read%only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only_; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read_only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only&; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read&only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only$; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read$only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only@; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read@only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only!; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read!only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only*; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read*only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only(; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read(only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only); +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read)only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only+; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read+only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only-#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-#only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only\; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read\only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only?; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read?only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only-/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-/only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only/#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/#only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set transaction read only; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read only/-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/-only; +NEW_CONNECTION; +set autocommit = false; +set transaction read write; +NEW_CONNECTION; +set autocommit = false; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +set autocommit = false; +set transaction read write; +NEW_CONNECTION; +set autocommit = false; + set transaction read write; +NEW_CONNECTION; +set autocommit = false; + set transaction read write; +NEW_CONNECTION; +set autocommit = false; + + + +set transaction read write; +NEW_CONNECTION; +set autocommit = false; +set transaction read write ; +NEW_CONNECTION; +set autocommit = false; +set transaction read write ; +NEW_CONNECTION; +set autocommit = false; +set transaction read write + +; +NEW_CONNECTION; +set autocommit = false; +set transaction read write; +NEW_CONNECTION; +set autocommit = false; +set transaction read write; +NEW_CONNECTION; +set autocommit = false; +set +transaction +read +write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write bar; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write%; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read%write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write_; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read_write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write&; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read&write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write$; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read$write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write@; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read@write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write!; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read!write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write*; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read*write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write(; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read(write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write); +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read)write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write+; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read+write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write-#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-#write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write\; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read\write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write?; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read?write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write-/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read-/write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write/#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/#write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set transaction read write; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read write/-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction read/-write; +NEW_CONNECTION; +set read_only_staleness='STRONG'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +set read_only_staleness='strong'; +NEW_CONNECTION; + set read_only_staleness='STRONG'; +NEW_CONNECTION; + set read_only_staleness='STRONG'; +NEW_CONNECTION; + + + +set read_only_staleness='STRONG'; +NEW_CONNECTION; +set read_only_staleness='STRONG' ; +NEW_CONNECTION; +set read_only_staleness='STRONG' ; +NEW_CONNECTION; +set read_only_staleness='STRONG' + +; +NEW_CONNECTION; +set read_only_staleness='STRONG'; +NEW_CONNECTION; +set read_only_staleness='STRONG'; +NEW_CONNECTION; +set +read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='STRONG'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='STRONG'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-read_only_staleness='STRONG'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +set read_only_staleness='min_read_timestamp 2018-01-02t03:04:05.123-08:00'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; + + + +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00' + +; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +set +read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP%2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP_2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP&2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP$2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP@2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP!2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP*2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP(2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP)2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP+2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-#2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP\2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP?2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-/2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/#2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/-2018-01-02T03:04:05.123-08:00'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +set read_only_staleness='min_read_timestamp 2018-01-02t03:04:05.123z'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; + + + +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z' + +; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +set +read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP%2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP_2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP&2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP$2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP@2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP!2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP*2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP(2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP)2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP+2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-#2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP\2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP?2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-/2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/#2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/-2018-01-02T03:04:05.123Z'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +set read_only_staleness='min_read_timestamp 2018-01-02t03:04:05.123+07:45'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; + set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; + + + +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45' ; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45' + +; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +set +read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP%2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP_2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP&2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP$2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP@2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP!2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP*2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP(2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP)2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP+2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-#2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP\2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP?2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP-/2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/#2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MIN_READ_TIMESTAMP/-2018-01-02T03:04:05.123+07:45'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +set read_only_staleness='read_timestamp 2018-01-02t03:04:05.54321-07:00'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; + + + +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00' + +; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +set +read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP%2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP_2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP&2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP$2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP@2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP!2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP*2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP(2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP)2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP+2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-#2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP\2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP?2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-/2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/#2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/-2018-01-02T03:04:05.54321-07:00'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +set read_only_staleness='read_timestamp 2018-01-02t03:04:05.54321z'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; + + + +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z' + +; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +set +read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP%2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP_2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP&2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP$2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP@2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP!2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP*2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP(2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP)2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP+2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-#2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP\2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP?2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-/2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/#2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/-2018-01-02T03:04:05.54321Z'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +set read_only_staleness='read_timestamp 2018-01-02t03:04:05.54321+05:30'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; + set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; + + + +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30' ; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30' + +; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +set +read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP%2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP_2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP&2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP$2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP@2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP!2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP*2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP(2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP)2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP+2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-#2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP\2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP?2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP-/2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/#2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='READ_TIMESTAMP/-2018-01-02T03:04:05.54321+05:30'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 12S'; +NEW_CONNECTION; +set read_only_staleness='max_staleness 12s'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; + + + +set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s' + +; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +set +read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS%12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS_12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS&12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS$12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS@12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS!12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS*12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS(12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS)12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS+12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-#12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS\12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS?12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-/12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/#12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MAX_STALENESS 12s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 12s'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/-12s'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 100MS'; +NEW_CONNECTION; +set read_only_staleness='max_staleness 100ms'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; + + + +set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms' + +; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +set +read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS%100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS_100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS&100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS$100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS@100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS!100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS*100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS(100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS)100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS+100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-#100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS\100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS?100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-/100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/#100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MAX_STALENESS 100ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 100ms'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/-100ms'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 99999US'; +NEW_CONNECTION; +set read_only_staleness='max_staleness 99999us'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; + + + +set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us' + +; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +set +read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS%99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS_99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS&99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS$99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS@99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS!99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS*99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS(99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS)99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS+99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-#99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS\99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS?99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-/99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/#99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MAX_STALENESS 99999us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 99999us'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/-99999us'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10NS'; +NEW_CONNECTION; +set read_only_staleness='max_staleness 10ns'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; + set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; + + + +set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns' ; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns' + +; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +set +read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS%10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS_10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS&10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS$10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS@10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS!10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS*10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS(10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS)10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS+10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-#10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS\10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS?10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS-/10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/#10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='MAX_STALENESS 10ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS 10ns'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='MAX_STALENESS/-10ns'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 15S'; +NEW_CONNECTION; +set read_only_staleness='exact_staleness 15s'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; + + + +set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s' + +; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +set +read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS%15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS_15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS&15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS$15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS@15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS!15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS*15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS(15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS)15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS+15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-#15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS\15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS?15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-/15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/#15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='EXACT_STALENESS 15s'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15s'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/-15s'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1500MS'; +NEW_CONNECTION; +set read_only_staleness='exact_staleness 1500ms'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; + + + +set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms' + +; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +set +read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS%1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS_1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS&1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS$1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS@1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS!1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS*1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS(1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS)1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS+1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-#1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS\1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS?1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-/1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/#1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='EXACT_STALENESS 1500ms'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 1500ms'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/-1500ms'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 15000000US'; +NEW_CONNECTION; +set read_only_staleness='exact_staleness 15000000us'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; + + + +set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us' + +; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +set +read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS%15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS_15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS&15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS$15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS@15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS!15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS*15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS(15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS)15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS+15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-#15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS\15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS?15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-/15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/#15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='EXACT_STALENESS 15000000us'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 15000000us'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/-15000000us'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 9999NS'; +NEW_CONNECTION; +set read_only_staleness='exact_staleness 9999ns'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; + set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; + + + +set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns' ; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns' + +; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +set +read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS%9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS_9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS&9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS$9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS@9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS!9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS*9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS(9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS)9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS+9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-#9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS\9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS?9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS-/9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/#9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set read_only_staleness='EXACT_STALENESS 9999ns'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS 9999ns'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set read_only_staleness='EXACT_STALENESS/-9999ns'; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql new file mode 100644 index 000000000000..916a35d9ef18 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql @@ -0,0 +1,302 @@ +/* + * Copyright 2019 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. + */ + +@EXPECT 'SELECT 1'; +SELECT 1; +-- This is a single line comment +SELECT 1; +# This is a single line comment +SELECT 1; +/* This is a multi line comment on one line */ +SELECT 1; +/* This + is + a + multiline + comment +*/ +SELECT 1; +/* This + * is + * a + * multiline + * comment + */ +SELECT 1; +/** This is a javadoc style comment on one line*/ +SELECT 1; +/** This + is + a + javadoc + style + comment + on + multiple + lines +*/ +SELECT 1; +/** This + * is + * a + * javadoc + * style + * comment + * on + * multiple + * lines + */ +SELECT 1; + +@EXPECT 'SELECT +1'; +-- First comment +SELECT-- second comment +1; +# First comment +SELECT# second comment +1; +-- First comment +SELECT-- second comment +1--third comment +; +# First comment +SELECT# second comment +1#Third comment +; +/* First comment */ +SELECT/* second comment */ +1; +/* First comment */ +SELECT/* second comment */ +1/* Third comment */ +; + + +@EXPECT 'SELECT +1'; +-- First comment +SELECT -- second comment +1 ; +# First comment +SELECT # second comment +1 ; +-- First comment +SELECT -- second comment +1 --third comment +; +# First comment +SELECT # second comment +1 #Third comment +; +/* First comment */ +SELECT /* second comment */ +1 ; +/* First comment */ +SELECT /* second comment */ +1 /* Third comment */ +; + +@EXPECT 'SELECT "TEST -- This is not a comment"'; +SELECT "TEST -- This is not a comment"; +-- This is a comment +SELECT "TEST -- This is not a comment"; +-- This is a comment +SELECT "TEST -- This is not a comment" -- This is a comment; + +@EXPECT 'SELECT "TEST # This is not a comment"'; +SELECT "TEST # This is not a comment"; +# This is a comment +SELECT "TEST # This is not a comment"; +# This is a comment +SELECT "TEST # This is not a comment" # This is a comment; + +@EXPECT 'SELECT "TEST /* This is not a comment */"'; +SELECT "TEST /* This is not a comment */"; +/* This is a comment */ +SELECT "TEST /* This is not a comment */"; +/* This is a comment */ +SELECT "TEST /* This is not a comment */" /* This is a comment */; + +@EXPECT 'SELECT 'TEST -- This is not a comment''; +SELECT 'TEST -- This is not a comment'; +-- This is a comment +SELECT 'TEST -- This is not a comment'; +-- This is a comment +SELECT 'TEST -- This is not a comment' -- This is a comment; + +@EXPECT 'SELECT 'TEST # This is not a comment''; +SELECT 'TEST # This is not a comment'; +# This is a comment +SELECT 'TEST # This is not a comment'; +# This is a comment +SELECT 'TEST # This is not a comment' # This is a comment; + +@EXPECT 'SELECT 'TEST /* This is not a comment */''; +SELECT 'TEST /* This is not a comment */'; +/* This is a comment */ +SELECT 'TEST /* This is not a comment */'; +/* This is a comment */ +SELECT 'TEST /* This is not a comment */' /* This is a comment */; + +@EXPECT 'SELECT '''TEST +-- This is not a comment +''''; +SELECT '''TEST +-- This is not a comment +'''; +-- This is a comment +SELECT '''TEST +-- This is not a comment +'''; +-- This is a comment +SELECT '''TEST +-- This is not a comment +''' -- This is a comment; + +@EXPECT 'SELECT '''TEST +# This is not a comment +''''; +SELECT '''TEST +# This is not a comment +'''; +# This is a comment +SELECT '''TEST +# This is not a comment +'''; +# This is a comment +SELECT '''TEST +# This is not a comment +''' # This is a comment; + +@EXPECT 'SELECT '''TEST +/* This is not a comment */ +''''; +SELECT '''TEST +/* This is not a comment */ +'''; +/* This is a comment */ +SELECT '''TEST +/* This is not a comment */ +'''; +/* This is a comment */ +SELECT '''TEST +/* This is not a comment */ +''' /* This is a comment */; + + +@EXPECT 'SELECT """TEST +-- This is not a comment +"""'; +SELECT """TEST +-- This is not a comment +"""; +-- This is a comment +SELECT """TEST +-- This is not a comment +"""; +-- This is a comment +SELECT """TEST +-- This is not a comment +""" -- This is a comment; + +@EXPECT 'SELECT """TEST +# This is not a comment +"""'; +SELECT """TEST +# This is not a comment +"""; +# This is a comment +SELECT """TEST +# This is not a comment +"""; +# This is a comment +SELECT """TEST +# This is not a comment +""" # This is a comment; + +@EXPECT 'SELECT """TEST +/* This is not a comment */ +"""'; +SELECT """TEST +/* This is not a comment */ +"""; +/* This is a comment */ +SELECT """TEST +/* This is not a comment */ +"""; +/* This is a comment */ +SELECT """TEST +/* This is not a comment */ +""" /* This is a comment */; + + + +@EXPECT 'SELECT ```TEST +-- This is not a comment +```'; +SELECT ```TEST +-- This is not a comment +```; +-- This is a comment +SELECT ```TEST +-- This is not a comment +```; +-- This is a comment +SELECT ```TEST +-- This is not a comment +``` -- This is a comment; + +@EXPECT 'SELECT ```TEST +# This is not a comment +```'; +SELECT ```TEST +# This is not a comment +```; +# This is a comment +SELECT ```TEST +# This is not a comment +```; +# This is a comment +SELECT ```TEST +# This is not a comment +``` # This is a comment; + +@EXPECT 'SELECT ```TEST +/* This is not a comment */ +```'; +SELECT ```TEST +/* This is not a comment */ +```; +/* This is a comment */ +SELECT ```TEST +/* This is not a comment */ +```; +/* This is a comment */ +SELECT ```TEST +/* This is not a comment */ +``` /* This is a comment */; + + +@EXPECT 'SELECT 1'; +/* This is a comment /* this is still a comment */ +SELECT 1; +/** This is a javadoc style comment /* this is still a comment */ +SELECT 1; +/** This is a javadoc style comment /** this is still a comment */ +SELECT 1; +/** This is a javadoc style comment /** this is still a comment **/ +SELECT 1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql new file mode 100644 index 000000000000..c76508561647 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql @@ -0,0 +1,11201 @@ +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.524000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.524000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.915000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.915000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.970000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.970000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.029000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.029000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.104000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.104000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.262000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.262000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.291000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.291000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql new file mode 100644 index 000000000000..2dea04231515 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql @@ -0,0 +1,189 @@ +/* + * Copyright 2019 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. + */ + +NEW_CONNECTION; +-- Create table in autocommit mode + +@EXPECT RESULT_SET 'AUTOCOMMIT',true +SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'READONLY',false +SHOW VARIABLE READONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_DDL_AUTOCOMMIT'; + +CREATE TABLE VALID_DDL_AUTOCOMMIT (ID INT64 NOT NULL, BAR STRING(100)) PRIMARY KEY (ID); + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_DDL_AUTOCOMMIT'; + + +NEW_CONNECTION; +-- Try to create a table with an invalid SQL statement + +@EXPECT RESULT_SET 'AUTOCOMMIT',true +SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'READONLY',false +SHOW VARIABLE READONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='INVALID_DDL_AUTOCOMMIT'; + +@EXPECT EXCEPTION INVALID_ARGUMENT +CREATE TABLE INVALID_DDL_AUTOCOMMIT (ID INT64 NOT NULL, BAZ STRING(100), MISSING_DATA_TYPE_COL) PRIMARY KEY (ID); + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='INVALID_DDL_AUTOCOMMIT'; + + +NEW_CONNECTION; +-- Try to create a new table in a DDL_BATCH + +-- Check that the table is not present +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_SINGLE_DDL_IN_DDL_BATCH'; + +-- Change to DDL batch mode +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +-- Execute the create table statement, but do not commit yet +CREATE TABLE VALID_SINGLE_DDL_IN_DDL_BATCH (ID INT64 NOT NULL, BAR STRING(100)) PRIMARY KEY (ID); + +NEW_CONNECTION; +-- Transaction has not been committed, so the table should not be present +-- We do this in a new transaction, as selects are not allowed in a DDL_BATCH +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_SINGLE_DDL_IN_DDL_BATCH'; + +-- Change to DDL batch mode again +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +-- Execute the create table statement and do a commit +CREATE TABLE VALID_SINGLE_DDL_IN_DDL_BATCH (ID INT64 NOT NULL, BAR STRING(100)) PRIMARY KEY (ID); +RUN BATCH; + +-- Go back to AUTOCOMMIT mode and check that the table was created +SET AUTOCOMMIT = TRUE; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_SINGLE_DDL_IN_DDL_BATCH'; + + +NEW_CONNECTION; +-- Create two tables in one batch + +-- First ensure that the tables do not exist +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_1' OR TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_2'; + +-- Change to DDL batch mode +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +-- Create two tables +CREATE TABLE VALID_MULTIPLE_DDL_IN_DDL_BATCH_1 (ID INT64 NOT NULL, BAR STRING(100)) PRIMARY KEY (ID); +CREATE TABLE VALID_MULTIPLE_DDL_IN_DDL_BATCH_2 (ID INT64 NOT NULL, BAR STRING(100)) PRIMARY KEY (ID); +-- Run the batch +RUN BATCH; + +-- Switch to autocommit and verify that both tables exist +SET AUTOCOMMIT = TRUE; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_1' OR TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_2'; + + +NEW_CONNECTION; +/* + * Do a test that shows that a DDL batch might only execute some of the statements, + * for example if data in a table prevents a unique index from being created. + */ +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +CREATE TABLE TEST1 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); +CREATE TABLE TEST2 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); +RUN BATCH; + +SET AUTOCOMMIT = TRUE; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='TEST1' OR TABLE_NAME='TEST2'; + +-- Fill the second table with some data that will prevent us from creating a unique index on +-- the name column. +INSERT INTO TEST2 (ID, NAME) VALUES (1, 'TEST'); +INSERT INTO TEST2 (ID, NAME) VALUES (2, 'TEST'); + +-- Ensure the indices that we are to create do not exist +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE (TABLE_NAME='TEST1' AND INDEX_NAME='IDX_TEST1') + OR (TABLE_NAME='TEST2' AND INDEX_NAME='IDX_TEST2'); + +-- Try to create two unique indices in one batch +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +CREATE UNIQUE INDEX IDX_TEST1 ON TEST1 (NAME); +CREATE UNIQUE INDEX IDX_TEST2 ON TEST2 (NAME); + +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; + +SET AUTOCOMMIT = TRUE; + +-- Ensure that IDX_TEST1 was created and IDX_TEST2 was not. +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE TABLE_NAME='TEST1' AND INDEX_NAME='IDX_TEST1'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE TABLE_NAME='TEST2' AND INDEX_NAME='IDX_TEST2'; + +NEW_CONNECTION; +/* Verify that empty DDL batches are accepted. */ +START BATCH DDL; +RUN BATCH; + +START BATCH DDL; +ABORT BATCH; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql new file mode 100644 index 000000000000..8f8f6694481d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql @@ -0,0 +1,261 @@ +/* + * Copyright 2019 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. + */ + +NEW_CONNECTION; + +-- Test a couple of count queries to ensure the presence of the data +@EXPECT RESULT_SET 'READONLY',true +SHOW VARIABLE READONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +-- Assert that there is a read timestamp +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +NEW_CONNECTION; +-- Test two selects in one temporary transaction +@EXPECT RESULT_SET 'READONLY',true +SHOW VARIABLE READONLY; + +BEGIN; + +@EXPECT RESULT_SET 'NUMBER',1 +SELECT NUMBER +FROM NUMBERS +WHERE NUMBER=1; + +@PUT 'READ_TIMESTAMP1' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET 'PRIME_NUMBER',13 +SELECT PRIME_NUMBER +FROM PRIME_NUMBERS +WHERE PRIME_NUMBER=13; + +@PUT 'READ_TIMESTAMP2' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT EQUAL 'READ_TIMESTAMP1','READ_TIMESTAMP2'; + +COMMIT; + +NEW_CONNECTION; + +/* + * ------------------------------------------------------------------------------------------------ + * | Test different read only staleness values in autocommit mode | + * ------------------------------------------------------------------------------------------------ + */ + +--TimestampBound.ofReadTimestamp(Timestamp.now()), + +@PUT 'CURRENT_TIMESTAMP' +SELECT CURRENT_TIMESTAMP(); + +SET READ_ONLY_STALENESS = 'READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@PUT 'READ_TIMESTAMP1' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@PUT 'READ_TIMESTAMP2' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT EQUAL 'READ_TIMESTAMP1','READ_TIMESTAMP2'; +@EXPECT EQUAL 'READ_TIMESTAMP1','CURRENT_TIMESTAMP'; + +NEW_CONNECTION; +--TimestampBound.ofMinReadTimestamp(Timestamp.now()), + +@PUT 'CURRENT_TIMESTAMP' +SELECT CURRENT_TIMESTAMP(); + +SET READ_ONLY_STALENESS = 'MIN_READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +--TimestampBound.ofExactStaleness(100, TimeUnit.MILLISECONDS), + +SET READ_ONLY_STALENESS = 'EXACT_STALENESS 100ms'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +--TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS) + +SET READ_ONLY_STALENESS = 'MAX_STALENESS 10s'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +--TimestampBound.strong() + +SET READ_ONLY_STALENESS = 'STRONG'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +/* + * ------------------------------------------------------------------------------------------------ + * | Test the same read only staleness values in transactional mode | + * ------------------------------------------------------------------------------------------------ + */ + +--TimestampBound.ofReadTimestamp(Timestamp.now()), + +@PUT 'CURRENT_TIMESTAMP' +SELECT CURRENT_TIMESTAMP(); + +SET AUTOCOMMIT = FALSE; + +SET READ_ONLY_STALENESS = 'READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@PUT 'READ_TIMESTAMP1' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@PUT 'READ_TIMESTAMP2' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT EQUAL 'READ_TIMESTAMP1','READ_TIMESTAMP2'; +@EXPECT EQUAL 'READ_TIMESTAMP1','CURRENT_TIMESTAMP'; + +COMMIT; + +NEW_CONNECTION; +--TimestampBound.ofMinReadTimestamp(Timestamp.now()), + +@PUT 'CURRENT_TIMESTAMP' +SELECT CURRENT_TIMESTAMP(); + +SET AUTOCOMMIT = FALSE; + +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS = 'MIN_READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; + + +NEW_CONNECTION; +--TimestampBound.ofExactStaleness(100, TimeUnit.MILLISECONDS), +SET AUTOCOMMIT = FALSE; + +SET READ_ONLY_STALENESS = 'EXACT_STALENESS 100ms'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@PUT 'READ_TIMESTAMP1' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@PUT 'READ_TIMESTAMP2' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT EQUAL 'READ_TIMESTAMP1','READ_TIMESTAMP2'; + +COMMIT; + + +NEW_CONNECTION; +--TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS) +SET AUTOCOMMIT = FALSE; + +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS = 'MAX_STALENESS 10s'; + + +NEW_CONNECTION; +--TimestampBound.strong() +SET AUTOCOMMIT = FALSE; + +SET READ_ONLY_STALENESS = 'STRONG'; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; + +@PUT 'READ_TIMESTAMP1' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; + +@PUT 'READ_TIMESTAMP2' +SHOW VARIABLE READ_TIMESTAMP; + +@EXPECT EQUAL 'READ_TIMESTAMP1','READ_TIMESTAMP2'; + +COMMIT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql new file mode 100644 index 000000000000..5ba95f80d45d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql @@ -0,0 +1,24 @@ +/* + * Copyright 2019 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. + */ + +NEW_CONNECTION; + +SET READONLY = FALSE; +START BATCH DDL; + +CREATE TABLE NUMBERS (NUMBER INT64 NOT NULL, NAME STRING(200) NOT NULL) PRIMARY KEY (NUMBER); +CREATE TABLE PRIME_NUMBERS (PRIME_NUMBER INT64 NOT NULL, BINARY_REPRESENTATION STRING(MAX) NOT NULL) PRIMARY KEY (PRIME_NUMBER); +RUN BATCH; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql new file mode 100644 index 000000000000..1a5a5cb8d4d8 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql @@ -0,0 +1,216 @@ +/* + * Copyright 2019 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. + */ + +NEW_CONNECTION; + +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +INSERT INTO TEST (ID, NAME) VALUES (1, 'test'); + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + + +NEW_CONNECTION; + +@EXPECT RESULT_SET 'ID',1 +SELECT * +FROM TEST; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + + +NEW_CONNECTION; +@EXPECT UPDATE_COUNT 1 +INSERT INTO TEST (ID, NAME) VALUES (2, 'FOO'); + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED FROM TEST; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Do an update in partioned_non_atomic mode +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; + +@EXPECT UPDATE_COUNT 1 +UPDATE TEST SET NAME = 'partitioned' WHERE ID=2; + +-- Reset dml mode to transactional +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; + +@EXPECT RESULT_SET 'NAME','partitioned' +SELECT NAME FROM TEST WHERE ID=2; + +-- Set a statement timeout that should never be reached +SET STATEMENT_TIMEOUT = '10000s'; + +@EXPECT RESULT_SET 'NAME','partitioned' +SELECT NAME FROM TEST WHERE ID=2; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Set a statement timeout that should always be exceeded +SET STATEMENT_TIMEOUT = '1ns'; + +@EXPECT EXCEPTION DEADLINE_EXCEEDED +SELECT NAME FROM TEST WHERE ID=2; + +-- Turn off statement timeouts +SET STATEMENT_TIMEOUT = null; +-- There should be no read timestamp available +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +-- Set a statement timeout that should never be reached +SET STATEMENT_TIMEOUT = '10000s'; + +@EXPECT UPDATE_COUNT 1 +INSERT INTO TEST (ID, NAME) VALUES (3, 'test'); + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Set a statement timeout that should always be exceeded +SET STATEMENT_TIMEOUT = '1ns'; +-- And then try to do an insert +@EXPECT EXCEPTION DEADLINE_EXCEEDED +INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); + +-- Turn off statement timeouts +SET STATEMENT_TIMEOUT = null; +-- Delete record with id 4 if it exists (even though the statement timed out, +-- there is still a small chance that the statement did succeed) +DELETE FROM TEST WHERE ID=4; + +-- Verify that a timeout means there's no commit timestamp +SET STATEMENT_TIMEOUT = '1ns'; + +@EXPECT EXCEPTION DEADLINE_EXCEEDED +INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); + +SET STATEMENT_TIMEOUT = null; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + + +NEW_CONNECTION; +-- Execute a number of statements on one connection +DELETE FROM TEST WHERE ID=4; + +@EXPECT UPDATE_COUNT 1 +INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); + +@EXPECT RESULT_SET 'NAME','test' +SELECT * FROM TEST WHERE ID=4; + +@EXPECT UPDATE_COUNT 1 +UPDATE TEST SET NAME='test18' WHERE ID=4; + +@EXPECT RESULT_SET 'NAME','test18' +SELECT * FROM TEST WHERE ID=4; + +@EXPECT UPDATE_COUNT 1 +DELETE FROM TEST WHERE ID=4; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM TEST +WHERE ID=4; + + +NEW_CONNECTION; +-- Test primary key violation + +@EXPECT UPDATE_COUNT 1 +INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); + +@EXPECT EXCEPTION ALREADY_EXISTS +INSERT INTO TEST (ID, NAME) VALUES (4, 'should not be there'); + +--Check that the second insert failed +@EXPECT RESULT_SET 'NAME','test' +SELECT * FROM TEST WHERE ID=4; + + +NEW_CONNECTION; +-- Test multiple timeouts after each other on the same connection +SET STATEMENT_TIMEOUT = '1ns'; + +@EXPECT EXCEPTION DEADLINE_EXCEEDED +SELECT NAME FROM TEST WHERE ID=2; + +@EXPECT EXCEPTION DEADLINE_EXCEEDED +SELECT NAME FROM TEST WHERE ID=2; + +@EXPECT EXCEPTION DEADLINE_EXCEEDED +SELECT NAME FROM TEST WHERE ID=2; + + +NEW_CONNECTION; +-- Execute a DML batch. +START BATCH DML; +@EXPECT UPDATE_COUNT -1 +INSERT INTO TEST (ID, NAME) VALUES (10, 'Batched insert 1'); +@EXPECT UPDATE_COUNT -1 +INSERT INTO TEST (ID, NAME) VALUES (11, 'Batched insert 2'); +@EXPECT UPDATE_COUNT -1 +INSERT INTO TEST (ID, NAME) VALUES (12, 'Batched insert 3'); +@EXPECT RESULT_SET 'UPDATE_COUNTS',[1,1,1] +RUN BATCH; + +-- Verify that the records were inserted. +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 3 AS EXPECTED +FROM TEST +WHERE ID IN (10,11,12); + + +-- Execute a DML batch with an error. +START BATCH DML; +@EXPECT UPDATE_COUNT -1 +DELETE FROM TEST WHERE ID IN (10,11,12); +@EXPECT UPDATE_COUNT -1 +DELETE FROM TEST_NOT_FOUND WHERE ID IN (10,11,12); +-- Returns an error because of the second statement. +@EXPECT EXCEPTION INVALID_ARGUMENT +RUN BATCH; + +-- Verify that the records were not deleted. +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 3 AS EXPECTED +FROM TEST +WHERE ID IN (10,11,12); + +START BATCH DML; +@EXPECT UPDATE_COUNT -1 +DELETE FROM TEST WHERE ID=10; +DELETE FROM TEST WHERE ID=11; +DELETE FROM TEST WHERE ID=12; +@EXPECT RESULT_SET 'UPDATE_COUNTS',[1,1,1] +RUN BATCH; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql new file mode 100644 index 000000000000..b72560b55f8c --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql @@ -0,0 +1,98 @@ +/* + * Copyright 2019 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. + */ + +/* + * Test script that creates a couple of test tables in one transaction. + */ + +-- Turn off autocommit (and verify) +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; + +-- Turn off readonly (and verify) +@EXPECT NO_RESULT +SET READONLY = FALSE; +@EXPECT RESULT_SET 'READONLY',false +SHOW VARIABLE READONLY; + +-- Start a DDL batch to execute a number of DDL statements as one operation. +@EXPECT NO_RESULT +START BATCH DDL; + +-- Create a couple of test tables +@EXPECT NO_RESULT +CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX) +) PRIMARY KEY (SingerId); + +@EXPECT NO_RESULT +CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) +) PRIMARY KEY (SingerId, AlbumId), +-- interleave this table in the Singers table +INTERLEAVE IN PARENT Singers ON DELETE CASCADE; + +-- Create a secondary index +@EXPECT NO_RESULT +CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); + +-- Run the DDL batch +RUN BATCH; + +-- Reset the statement timeout +SET STATEMENT_TIMEOUT=null; + +/* + * Verify that the test tables have been created + */ +@EXPECT NO_RESULT +SET AUTOCOMMIT = TRUE; +@EXPECT NO_RESULT +SET READONLY = TRUE; + +-- Check that the table has been created +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Singers'; + +-- Check for all columns +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 4 AS EXPECTED +FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_NAME='Singers' +/** + * List all expected column names + */ +AND COLUMN_NAME IN ( + 'SingerId', + 'FirstName', + 'LastName', + 'SingerInfo' +); + +-- Check for index +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE TABLE_NAME='Albums' AND INDEX_NAME='AlbumsByAlbumTitle'; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql new file mode 100644 index 000000000000..03c561885aab --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql @@ -0,0 +1,79 @@ +/* + * Copyright 2019 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. + */ + +/* + * Insert test data into test tables + */ + +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; +@EXPECT NO_RESULT +SET READONLY = FALSE; + +@EXPECT UPDATE_COUNT 3 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES(1, 'Marc', 'Richards'), + (2, 'Catalina', 'Smith'), + (3, 'Alice', 'Trentor'); + +@EXPECT UPDATE_COUNT 3 +INSERT INTO Singers (SingerId, FirstName, LastName) +SELECT 4, 'Lea', 'Martin' +UNION ALL +SELECT 5, 'David', 'Lomond' +UNION ALL +SELECT 6, 'Elena', 'Campbell'; + +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (10, 'Virginia', 'Watson'); +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (11, 'Timothy', 'Campbell'); + +@EXPECT UPDATE_COUNT 5 +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) +VALUES + (1, 1, 'Total Junk'), + (1, 2, 'Go, Go, Go'), + (2, 1, 'Green'), + (2, 2, 'Forever Hold Your Peace'), + (2, 3, 'Terrified'); + +@EXPECT NO_RESULT +COMMIT; + +-- Try to insert a record that already exists +@EXPECT EXCEPTION ALREADY_EXISTS +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (10, 'Virginia', 'Watson'); + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE FirstName='Virginia' AND LastName='Watson'; + +@EXPECT NO_RESULT +ROLLBACK; + +-- Verify the contents of the tables +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 5 AS EXPECTED +FROM Albums; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 8 AS EXPECTED +FROM Singers; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql new file mode 100644 index 000000000000..de9ab155a214 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql @@ -0,0 +1,87 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script that tests the different possible autocommit dml modes + */ + +SET AUTOCOMMIT = FALSE; +SET READONLY = FALSE; + +-- First verify that the mode cannot be set when not in autocommit mode +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode while not in autocommit mode or while a transaction is active' +SET AUTOCOMMIT_DML_MODE = 'Transactional'; + +-- Turn on autocommit and set mode to transactional +SET AUTOCOMMIT = TRUE; + +@EXPECT NO_RESULT +SET AUTOCOMMIT_DML_MODE = 'Transactional'; + +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; + +-- Verify that executing an update statement is possible +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Anderson' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +-- Reset to original value in partioned mode +@EXPECT NO_RESULT +SET AUTOCOMMIT_DML_MODE = 'partitioned_non_atomic'; + +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; + +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Richards' +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +-- Verify that trying to set the mode to an invalid value will throw an exception +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT_DML_MODE: 'None'' +SET AUTOCOMMIT_DML_MODE = 'None'; + +-- Verify that setting the mode in read-only mode will throw an exception +SET READONLY = TRUE; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode for a read-only connection' +SET AUTOCOMMIT_DML_MODE = 'Transactional'; + +-- Back to read-write mode +SET READONLY = FALSE; + +-- Verify that turning off autocommit and on again will not reset the AUTOCOMMIT_DML_MODE value +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT = FALSE; +SET AUTOCOMMIT = TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; + +-- Reset to default value +SET AUTOCOMMIT_DML_MODE = 'Transactional'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql new file mode 100644 index 000000000000..58f33838ee26 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql @@ -0,0 +1,64 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script that tests a connection in read-only and autocommit mode + */ + +SET AUTOCOMMIT = TRUE; +SET READONLY = TRUE; + +-- First verify that the autocommit dml mode cannot be set when in read-only mode +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode for a read-only connection' +SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'; + +-- Verify that executing an update statement fails +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' +UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +-- Verify the same for INSERT and DELETE statements +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' +INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (9999, 'Morten', 'Harket'); + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' +DELETE FROM Singers; + +-- Verify that the same error message is given even if the update statements references a non-existent table +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' +/* The referenced table does not exist */ +update Artists set LastName='Anderson' +where ArtistId=1; + +-- Verify that DDL statements will also cause an exception +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL statements are not allowed in read-only mode' +CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID); + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL statements are not allowed in read-only mode' +/* The statement is recognized even if it is preceeded + * by a multi-line comment */ +-- And a single line comment, and some spaces + + DROP TABLE Singers; + +-- And verify that alter table statements also fail +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL statements are not allowed in read-only mode' +alter table Singers add column test string(100); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql new file mode 100644 index 000000000000..67b236f1a6fa --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql @@ -0,0 +1,138 @@ +/* + * Copyright 2019 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. + */ + +/* + * Test SHOW VARIABLE COMMIT_TIMESTAMP in different modes + */ + +-- Select query in autocommit and read-only mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = TRUE; +@EXPECT NO_RESULT +SET READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Select query in autocommit and read-write mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Select query in transactional and read-only mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; +@EXPECT NO_RESULT +SET READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Select query in transactional and read-write mode should yield a commit timestamp +@EXPECT NO_RESULT +SET READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Update statement in transactional and read-write mode should yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; + +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Perry' +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Reset the value to its original value +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Richards' +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +-- Select query in transactional and read-write mode that rollbacks should not yield a commit timestamp +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +ROLLBACK; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Update statement in transactional and read-write mode that rollbacks should not yield a commit timestamp +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Perry' +WHERE SingerId=1; + +@EXPECT NO_RESULT +ROLLBACK; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Invalid select query in transactional and read-write mode should yield a commit timestamp +-- The (invalid) query is sent to the server, initiating a transaction, that is committed afterwards +SET AUTOCOMMIT = FALSE; +SET READONLY = FALSE; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM NonExistentTable +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql new file mode 100644 index 000000000000..0d709c64cffe --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql @@ -0,0 +1,112 @@ +/* + * Copyright 2019 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. + */ + +/* + * Test SHOW VARIABLE READ_TIMESTAMP in different modes + */ + +-- Select query in autocommit and read-only mode should yield a read timestamp +SET AUTOCOMMIT = TRUE; +SET READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Select query in autocommit and read-write mode should yield a read timestamp +SET READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Select query in transactional and read-only mode should yield a read timestamp +SET AUTOCOMMIT = FALSE; +SET READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +COMMIT; + +-- Select query in transactional and read-write mode should NOT yield a read timestamp +SET READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +COMMIT; + +-- Update statement in transactional and read-write mode should NOT yield a read timestamp +SET AUTOCOMMIT = FALSE; + +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Perry' +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +ROLLBACK; + +-- Verify that the rollback actually worked +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + +COMMIT; + +-- Invalid select query in autocommit and read-only mode should not yield a read timestamp +SET AUTOCOMMIT = TRUE; +SET READONLY = TRUE; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM NonExistentTable +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +-- Invalid select query in autocommit and read-write mode should not yield a read timestamp +SET READONLY = FALSE; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM NonExistentTable +WHERE SingerId=1; + +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql new file mode 100644 index 000000000000..551d5c07ce7b --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script for testing invalid/unrecognized statements + */ +-- EXPLAIN statement +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: EXPLAIN' +EXPLAIN SELECT * +FROM Singers; + +-- EXPLAIN ANALYZE statement +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: EXPLAIN ANALYZE' +EXPLAIN ANALYZE SELECT * +FROM Singers; + +-- SET unknown property +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: SET some_property' +SET some_property='value'; \ No newline at end of file diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql new file mode 100644 index 000000000000..6feb7894bf7d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql @@ -0,0 +1,262 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script that tests the different possible read-only staleness modes + */ + +-- First test in autocommit mode. READONLY mode is not strictly necessary +SET AUTOCOMMIT = TRUE; +SET READONLY = FALSE; + +--------------------- STRONG ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set STRONG with a timestamp value +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' +SET READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; + +-- Try to set STRONG with a duration value +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 10s'' +SET READ_ONLY_STALENESS='STRONG 10s'; + +--------------------- MIN_READ_TIMESTAMP ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Min_Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set MIN_READ_TIMESTAMP without a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP'; + +-- Try to set MIN_READ_TIMESTAMP with a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 10s'; + +--------------------- READ_TIMESTAMP ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set READ_TIMESTAMP without a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP'' +SET READ_ONLY_STALENESS='READ_TIMESTAMP'; + +-- Try to set READ_TIMESTAMP with a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; + +--------------------- MAX_STALENESS ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Max_Staleness 1000ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='max_staleness 10001ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10001ns' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set MAX_STALENESS without a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS'' +SET READ_ONLY_STALENESS='MAX_STALENESS'; + +-- Try to set MAX_STALENESS with a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25+07:45'' +SET READ_ONLY_STALENESS='MAX_STALENESS 2018-11-15T13:09:25+07:45'; + +--------------------- EXACT_STALENESS ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Exact_Staleness 1001ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='exact_staleness 1000000000ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set EXACT_STALENESS without a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS'' +SET READ_ONLY_STALENESS='EXACT_STALENESS'; + +-- Try to set EXACT_STALENESS with a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' +SET READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; + + +------------------------------------------------------------------------------------------------------------------------------ + + +-- Then test in transactional read-only mode. +SET AUTOCOMMIT = FALSE; +SET READONLY = TRUE; + +--------------------- STRONG ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set STRONG with a timestamp value +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' +SET READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; + +-- Try to set STRONG with a duration value +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 10s'' +SET READ_ONLY_STALENESS='STRONG 10s'; + +--------------------- MIN_READ_TIMESTAMP ---------------------------- +-- This is not allowed in transactional mode +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +--------------------- READ_TIMESTAMP ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set READ_TIMESTAMP without a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP'' +SET READ_ONLY_STALENESS='READ_TIMESTAMP'; + +-- Try to set READ_TIMESTAMP with a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; + +--------------------- MAX_STALENESS ---------------------------- +-- only allowed in autocommit mode +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode' +SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +--------------------- EXACT_STALENESS ---------------------------- +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='Exact_Staleness 1001ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='exact_staleness 1000000000ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Try to set EXACT_STALENESS without a duration +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS'' +SET READ_ONLY_STALENESS='EXACT_STALENESS'; + +-- Try to set EXACT_STALENESS with a timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' +SET READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; + + +---------------------------------------------------------------------------------------------------------------- + +-- Then test in transactional read-write mode. This should also work, although it has no effect on the current transaction, unless the transaction mode is explicitly set to read only +SET AUTOCOMMIT = FALSE; +SET READONLY = FALSE; + +@EXPECT NO_RESULT +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Then test while in an active transaction. This should not be allowed. +SET TRANSACTION READ ONLY; +SELECT * +FROM Singers; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set read-only staleness when a transaction has been started' +SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +-- Check that the staleness mode is still 'STRONG' +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +COMMIT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql new file mode 100644 index 000000000000..8502d9da136d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql @@ -0,0 +1,58 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script for testing setting invalid values for the different connection and transaction options + */ + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT: on' +set autocommit = on; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READONLY: on' +set readonly = on; + +SET AUTOCOMMIT = TRUE; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT_DML_MODE: 'non_atomic'' +set autocommit_dml_mode='non_atomic'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'weak'' +set read_only_staleness='weak'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'strong 2018-11-15T13:09:25Z'' +set read_only_staleness='strong 2018-11-15T13:09:25Z'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' +set read_only_staleness='MIN_READ_TIMESTAMP'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' +set read_only_staleness='MIN_READ_TIMESTAMP 10s'; +-- Missing timezone in timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 2018-11-15T13:09:25'' +set read_only_staleness='MIN_READ_TIMESTAMP 2018-11-15T13:09:25'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS'' +set read_only_staleness='MAX_STALENESS'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25Z'' +set read_only_staleness='MAX_STALENESS 2018-11-15T13:09:25Z'; +-- Missing time unit +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 10'' +set read_only_staleness='MAX_STALENESS 10'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for STATEMENT_TIMEOUT: -1' +set statement_timeout=-1; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for STATEMENT_TIMEOUT: '1'' +set statement_timeout='1'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for TRANSACTION: readonly' +set transaction readonly; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql new file mode 100644 index 000000000000..a66956f4e500 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql @@ -0,0 +1,255 @@ +/* + * Copyright 2019 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. + */ + +/* + * Test setting statement timeout and verify that statements actually do timeout + */ + +-- Ensure we know what mode we are in +SET AUTOCOMMIT = TRUE; +SET AUTOCOMMIT_DML_MODE='Transactional'; +SET READONLY = FALSE; + +-- Verify that setting a negative timeout value is not allowed +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for STATEMENT_TIMEOUT: '-1ms'' +SET STATEMENT_TIMEOUT='-1ms'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for STATEMENT_TIMEOUT: '1'' +SET STATEMENT_TIMEOUT='1'; + +-- First set the statement timeout to null, which means no timeout +SET STATEMENT_TIMEOUT=null; + +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Do a somewhat complex query that should not timeout +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM ( + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) RES +; + +-- Set the statement timeout to 1 nanosecond that should cause basically any statement to timeout +SET STATEMENT_TIMEOUT='1ns'; + +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Do a somewhat complex query that should now timeout +@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM ( + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) RES +; + +-- Try to execute an update that should also timeout +@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +WHERE SingerId=1 +OR LastName IN ( + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) +; + +-- Verify that the record was not updated +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; + + +----------------------------------------------------------------------------------------------------- + +-- Repeat test in transactional mode +SET AUTOCOMMIT = FALSE; +-- First set the statement timeout to null, which means no timeout +SET STATEMENT_TIMEOUT=null; + +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Do a somewhat complex query that should not timeout +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM ( + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) RES +; + +-- Set the statement timeout to 1 nanosecond that should cause basically any statement to timeout +SET STATEMENT_TIMEOUT='1ns'; + +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Do a somewhat complex query that should now timeout +@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM ( + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT * + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) RES +; +-- We need to rollback the transaction as it is no longer usable. +@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +ROLLBACK; + +-- Try to execute an update that should also timeout +@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +WHERE SingerId=1 +OR LastName IN ( + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + UNION ALL + SELECT LastName + FROM Singers + WHERE LastName IN (SELECT AlbumTitle FROM Albums) + OR LastName IN (SELECT CAST(SingerId AS STRING) FROM Singers) + OR FirstName IN (SELECT AlbumTitle FROM Albums) + OR FirstName IN (SELECT CAST(SingerId AS STRING) FROM Singers) +) +; + +/* As we are in a transaction, the statement *could* continue in the background and will not + * automatically be rollbacked by the connection. Whether the statement will continue to + * execute in the background depends on what the reason for the timeout was. If the timeout + * was caused because the statement took too long to execute on the server, the statement + * will continue to run server side. If the timeout was caused by a network problem that + * prevented the statement to be delivered to the server in a timely fashion, the statement + * has never reached the server and hence will not be executed in the background. + * + * It is the responsibility of the user to rollback the transaction. If the user does nothing, + * the transaction will automatically abort server side and the change will not be committed. + */ + +-- Now rollback the transaction and verify that there was no permanent change +SET STATEMENT_TIMEOUT=null; +ROLLBACK; + +@EXPECT RESULT_SET +SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +FROM Singers +WHERE SingerId=1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql new file mode 100644 index 000000000000..106434be74ee --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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. + */ + +/* + * Test script for temporary transactions (i.e. autocommit mode with explicit BEGIN [TRANSACTION] statements) + */ + +SET AUTOCOMMIT = TRUE; +SET READONLY = FALSE; + +-- Insert a new singer in a temporary transaction and commit +BEGIN; +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (9999, 'Vegard', 'Ylvisåker'); +COMMIT; + +-- Verify that the record is there +@EXPECT RESULT_SET +SELECT FirstName AS ACTUAL, 'Vegard' AS EXPECTED +FROM Singers +WHERE SingerId=9999 +UNION ALL +SELECT LastName AS ACTUAL, 'Ylvisåker' AS EXPECTED +FROM Singers +WHERE SingerId=9999; + +-- Insert another singer in a temporary transaction and rollback +BEGIN; +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (9998, 'Bård', 'Ylvisåker'); +ROLLBACK; + +-- Verify that the record is not there +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=9998; + +-- Delete the initial test record in autocommit mode +@EXPECT UPDATE_COUNT 1 +DELETE FROM Singers +WHERE SingerId=9999; + +-- Verify that a rollback is not possible, as we are in autocommit mode +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: This connection has no transaction' +ROLLBACK; + +-- Verify that the record has been removed +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=9999; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql new file mode 100644 index 000000000000..3e5aec2139a2 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql @@ -0,0 +1,152 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script that tests the different possible transaction modes in read-write mode + */ + +SET AUTOCOMMIT = FALSE; +SET READONLY = FALSE; + +-- Insert a test record +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (9999, 'Vegard', 'Ylvisåker'); +COMMIT; + +---------------------------------------- Test read only transactions --------------------------------------------- +SET TRANSACTION READ ONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=9999; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' +-- try to update a record in a read-only transaction +UPDATE Singers SET FirstName='Peter' WHERE SingerId=9999; + +-- We are in a read-only transaction that has returned a query, so there should be a read-timestamp +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Finish the transaction with a rollback. This removes the read timestamp +ROLLBACK; + +-- Read timestamp from the previous transaction should no longer be available as it rolled back +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +-- Start a new read only transaction and SHOW VARIABLE the read timestamp after a commit +SET TRANSACTION READ ONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=9999; + +COMMIT; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Try to execute DDL in a read-only transaction +SET TRANSACTION READ ONLY; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL statements are not allowed for read-only transactions' +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); + +ROLLBACK; + +---------------------------------------- Test read/write transactions --------------------------------------------- +SET TRANSACTION READ WRITE; + +@EXPECT UPDATE_COUNT 1 +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (9998, 'Bård', 'Ylvisåker'); + +COMMIT; + +-- Verify the existence of the record +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=9998; + +COMMIT; + +-- try to delete the record, then rollback the transaction +@EXPECT UPDATE_COUNT 1 +DELETE FROM Singers WHERE SingerId=9998; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=9998; + +ROLLBACK; + +-- Verify that the rollback succeeded +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=9998; + +-- Try to execute DDL in a read/write transaction +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL-statements are not allowed inside a read/write transaction.' +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); + +ROLLBACK; + +---------------------------------------- Test DDL batches --------------------------------------------- +START BATCH DDL; + +-- Verify that queries and updates fail +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Executing queries is not allowed for DDL batches.' +SELECT * +FROM Singers; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Executing updates is not allowed for DDL batches.' +UPDATE Singers SET LastName='Foo'; + +-- Verify that DDL statements are allowed +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); +alter table FOO add column bar timestamp; +RUN BATCH; + +-- Verify the existence of the table and the column +SET AUTOCOMMIT = TRUE; +@EXPECT RESULT_SET +SELECT TABLE_NAME AS ACTUAL, 'FOO' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='FOO'; + +@EXPECT RESULT_SET +SELECT COLUMN_NAME AS ACTUAL, 'bar' AS EXPECTED +FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_NAME='FOO' AND COLUMN_NAME='bar'; + +SET AUTOCOMMIT = FALSE; + +-- Remove the table +START BATCH DDL; +DROP TABLE FOO; +RUN BATCH; + +-- Remove the test records +@EXPECT UPDATE_COUNT 2 +DELETE FROM Singers WHERE SingerId IN (9999, 9998); +COMMIT; \ No newline at end of file diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql new file mode 100644 index 000000000000..0d93454eb291 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql @@ -0,0 +1,80 @@ +/* + * Copyright 2019 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. + */ + +/* + * Script that tests the different possible transaction modes in read-only mode + */ + +SET AUTOCOMMIT = FALSE; +SET READONLY = TRUE; + +-- Verify that trying to insert a test record will fail +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' +INSERT INTO Singers (SingerId, FirstName, LastName) +VALUES (9999, 'Vegard', 'Ylvisåker'); +COMMIT; + +---------------------------------------- Test read only transactions --------------------------------------------- +SET TRANSACTION READ ONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' +-- try to update a record in a read-only transaction +UPDATE Singers SET FirstName='Peter' WHERE SingerId=9999; + +-- We are in a read-only transaction that has returned a query, so there should be a read-timestamp +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Finish the transaction with a rollback. This removes the read timestamp +ROLLBACK; + +-- Read timestamp from the previous transaction should no longer be available as it rolled back +@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SHOW VARIABLE READ_TIMESTAMP; + +-- Start a new read only transaction and SHOW VARIABLE the read timestamp after a commit +SET TRANSACTION READ ONLY; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=1; + +COMMIT; + +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- Try to execute DDL in a read-only transaction +SET TRANSACTION READ ONLY; + +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: DDL statements are not allowed for read-only transactions' +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID); + +ROLLBACK; + +---------------------------------------- Test read/write transactions --------------------------------------------- +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: The transaction mode can only be READ_ONLY when the connection is in read_only mode' +SET TRANSACTION READ WRITE; + +---------------------------------------- Test DDL batches --------------------------------------------- +@EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot start a DDL batch when the connection is in read-only mode' +START BATCH DDL; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql new file mode 100644 index 000000000000..7bb0f80943a4 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql @@ -0,0 +1,114 @@ +/* + * Copyright 2019 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. + */ + +NEW_CONNECTION; + +-- Test that DDL statements are allowed in DDL batches +START BATCH DDL; + +-- Try to execute a DDL statement +@EXPECT NO_RESULT +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100) PRIMARY KEY (ID); +-- Abort batch as creating a table takes quite some time +ABORT BATCH; + + +NEW_CONNECTION; + +-- Test that DDL statements are not allowed in read/write transactions +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'READONLY',false +SHOW VARIABLE READONLY; + +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100) PRIMARY KEY (ID); + + +NEW_CONNECTION; + +-- Test that DDL statements are not allowed in read-only transactions +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; + +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE FOO (ID INT64 NOT NULL, NAME STRING(100) PRIMARY KEY (ID); + + +NEW_CONNECTION; + +-- Test that DML statements are allowed in read/write transactions +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'READONLY',false +SHOW VARIABLE READONLY; + +@EXPECT UPDATE_COUNT 1 +INSERT INTO TEST (ID, NAME) VALUES (1, 'TEST'); +@EXPECT UPDATE_COUNT 1 +UPDATE TEST SET NAME='TEST2' WHERE ID=1; +@EXPECT UPDATE_COUNT 1 +DELETE FROM TEST WHERE ID=1; +COMMIT; + + +NEW_CONNECTION; + +-- Test that DML statements are not allowed in read-only transactions +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; + +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE FOO SET BAR=1 WHERE ID=2; + + +NEW_CONNECTION; + +-- Test that DML statements are not allowed in DDL batches +START BATCH DDL; + +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE FOO SET BAR=1 WHERE ID=2; + + +NEW_CONNECTION; + +-- Test that queries are allowed in read/write transactions +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; + +SELECT * FROM TEST; + + +NEW_CONNECTION; + +-- Test that queries are allowed in read-only transactions +@EXPECT RESULT_SET 'AUTOCOMMIT',false +SHOW VARIABLE AUTOCOMMIT; +SET TRANSACTION READ ONLY; + +SELECT * FROM TEST; + + +NEW_CONNECTION; + +-- Test that queries are not allowed in DDL batches +START BATCH DDL; + +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT * FROM TEST; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql new file mode 100644 index 000000000000..e545753c34e5 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql @@ -0,0 +1,575 @@ +/* + * Copyright 2019 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. + */ + +-- Test valid values for strong +SET READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS='Strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS = 'strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS = 'strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS += +'strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; +SET READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; + +-- Test invalid values for strong +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='strongg'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='sstrong'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='strng'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' strong'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='strong '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' strong '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' strong'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='strong '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' strong '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=strong; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS="strong"; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=`strong`; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='''strong'''; + + +-- Test valid values for min_read_timestamp +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='Min_Read_Timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2000-02-29T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2000-02-29T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2004-02-29T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2004-02-29T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+01:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T12:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01-01:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T14:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+06:30'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-07T07:06:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+24:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-12-06T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + + +-- Test invalid values for min_read_timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestampp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='mmin_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_red_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min read timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min-read-timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min%read%timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' min_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' min_read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' min_read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' min_read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=min_read_timestamp 2018-12-07T13:36:00.01Z; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS="min_read_timestamp 2018-12-07T13:36:00.01Z"; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=`min_read_timestamp 2018-12-07T13:36:00.01Z`; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='''min_read_timestamp 2018-12-07T13:36:00.01Z'''; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07 13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T3:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.9999999999Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-7T13:36:00.01Z'; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+8'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+08'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+08:0'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.0108:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+08:00.0'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+08:000'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01+100:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01*08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01%08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01 08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='min_read_timestamp 2018-12-07T13:36:00.01Z+08:00'; + + + + +-- Test valid values for read_timestamp +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='Read_Timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2000-02-29T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2000-02-29T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2004-02-29T13:36:00.01Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2004-02-29T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2019-01-01T00:00:00Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-01-01T00:00:00Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+01:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T12:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01-01:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T14:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+06:30'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-07T07:06:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+24:00'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-12-06T13:36:00.010000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; + + +-- Test invalid values for read_timestamp +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestampp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='mread_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='red_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read-timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read%timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' read_timestamp 2018-12-07T13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' read_timestamp 2018-12-07T13:36:00.01Z '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=read_timestamp 2018-12-07T13:36:00.01Z; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS="read_timestamp 2018-12-07T13:36:00.01Z"; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=`read_timestamp 2018-12-07T13:36:00.01Z`; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='''read_timestamp 2018-12-07T13:36:00.01Z'''; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07 13:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T3:36:00.01Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.9999999999Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-7T13:36:00.01Z'; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+8'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+08'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+08:0'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.0108:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+08:00.0'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+08:000'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01+100:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01*08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01%08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01 08:00'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='read_timestamp 2018-12-07T13:36:00.01Z+08:00'; + + +-- Test valid values for exact_staleness +SET READ_ONLY_STALENESS='exact_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='Exact_Staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1ns' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 9999s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 9999s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1000ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1001ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' +SHOW VARIABLE READ_ONLY_STALENESS; + + +SET READ_ONLY_STALENESS='exact_staleness 1000us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1001us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1000ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='exact_staleness 1001ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ns' +SHOW VARIABLE READ_ONLY_STALENESS; + + +-- Test invalid values for exact_staleness +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_stalenesss 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='eexact_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exct_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact-staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact%staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' exact_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' exact_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' exact_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' exact_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=exact_staleness 10s; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS="exact_staleness 10s"; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=`exact_staleness 10s`; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='''exact_staleness 10s'''; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness 10'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness 10mus'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness 999999999999s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness not_a_number'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='exact_staleness'; + + + +-- Test valid values for max_staleness +SET READ_ONLY_STALENESS='max_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_Staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1ns' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 9999s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 9999s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1000ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1001ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1001ms' +SHOW VARIABLE READ_ONLY_STALENESS; + + +SET READ_ONLY_STALENESS='max_staleness 1000us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1ms' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1001us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1001us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1000ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1us' +SHOW VARIABLE READ_ONLY_STALENESS; + +SET READ_ONLY_STALENESS='max_staleness 1001ns'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1001ns' +SHOW VARIABLE READ_ONLY_STALENESS; + + +-- Test invalid values for max_staleness +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_stalenesss 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='emax_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='mx_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max-staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max%staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' max_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' max_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' max_staleness 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=' max_staleness 10s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=max_staleness 10s; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS="max_staleness 10s"; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS=`max_staleness 10s`; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='''max_staleness 10s'''; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness 10'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness 10mus'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness 999999999999s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness not_a_number'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET READ_ONLY_STALENESS='max_staleness'; + diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql new file mode 100644 index 000000000000..d74be83acf4b --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql @@ -0,0 +1,158 @@ +/* + * Copyright 2019 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. + */ + +-- Test valid values +-- Null (no timeout) +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Seconds +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT = '2s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','2s' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1S'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Milliseconds +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1Ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1mS'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1MS'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Microseconds +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1Us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1uS'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1US'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Nanoseconds +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1Ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1nS'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1NS'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +-- Test flip to higher time unit +SET STATEMENT_TIMEOUT='1000ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1001ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1001ns' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1000us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1001us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1001us' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1000ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1001ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1001ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1000000ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1000000000ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; + +SET STATEMENT_TIMEOUT='1000000us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; + + +-- Invalid suffixes +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1m'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1mi'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1h'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1mus'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1n'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1u'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1'; + +-- Invalid numbers +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='-1s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='a1s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0xas'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0x1s'; + +-- Invalid because of spaces +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1 s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT=' 1s'; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1s '; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='1m s'; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql new file mode 100644 index 000000000000..06dc96fb8693 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql @@ -0,0 +1,54 @@ +/* + * Copyright 2019 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. + */ + +-- check that the default is null +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; +-- set a new value +SET STATEMENT_TIMEOUT='1000ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- do a simple select and verify that the timeout does not change +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- set a value that contains a fraction of a second +SET STATEMENT_TIMEOUT='1800ms'; +-- check that the jdbc driver reports the value that is set, although under water the JDBC connection will round it to a whole second +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1800ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- set a value that is just above a whole second +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- set a value that contains a whole second +SET STATEMENT_TIMEOUT='3s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','3s' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- set a value to a higher value +SET STATEMENT_TIMEOUT='2999ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','2999ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +-- Check that setting the value to 0 is not allowed +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +-- Set a timeout value and then reset it to null +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=null; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json new file mode 100644 index 000000000000..3e849240609d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "app-default-test-project", + "private_key_id": "some-key-id", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgFkCu/z3Sn8Py\nIHcUSSyCOjZ17AB/0F5IvhuGtTZTIJ33ltxeYmb69qK0m4QSk75HH5eX1OgF7/6E\nraqDaKlgi8ecSot1XrMRKyIY+LlTLMWeNtG54vymwjeH9wrMWQWfHJUCVUgUE8hL\nxQMEbU2Hn8t6P1JaGkfsm8cLiD0ve25iw/P2OPDdJukBlE2+47OL8RndyziVnLkW\n1y1kfujd83Cnf0sJp78fBKI7IRBWyXTS1C6/reZlkPq+D9ImCvn4YHpI6J1rsSDD\nitDbA0v/8l7KLyJoOK9vsFym4yhs4Q+Nzathv/ozvdHhob8I6JVizb5+D4QJ0GZ4\n9bMIzpV3AgMBAAECggEANbrCQvnP2h1dOqrCzMAyfBLlrHZlRIC+5FNKEdBIR2Yv\nHqY3mEYWoiydN1jq3wFPX7euvXrr1PJTzlwrWqeKEalYeZBbdi0ulJiRfSgdq1jf\nitaDVYxll+KfmLbFnQhT5q9FI99Trcll9GhPNvEokFiFhqYyEaO4eCVgjPJQ9tpC\njnKl9eLeHkhYK1pOKxJVBqzPcZI3F9jNvXWYTO1F7lFMom9I89W+NtBRAeYZnVao\nfH52GDJProB5A9BtRXkuLDzmFFjGjr8oT4E32wLuiu2UvNHgIZe7Hz+fMGGHsDHS\nc5jogukVwgt7QrfKVtoRTk8h2jyIrpRy4AQLfJZ4QQKBgQDT0X3+mp+tbEncLFBW\nXLT1k/1VWumi1TipiVsMpUcAZjWTGO8/WJF83IcNBAFqBJGyTAwplXIyUeI8CGg0\nOkBPY1Cy/dtTyiav05vRPZPkT44mhBua2tyhaE12DVo1/6ezF88yTPQkO9EjlvLs\nW32XlhqGQ8O587xjNaB/rqsjXwKBgQDBenKlO3eDBSfVb/te/xwqeVnKBgEYIAOJ\nN+FE49aH05n8DYQij1m8+Ck6sFBZywWliIQdS6d6J4NE69Ok7bfowwVqoumX8LWD\ntstMkOE2FmPCF4nbxkAFYbcuep1iItA2LVSwh3ChAA6aexA/fV6bMauhJPJTSnwX\nItnKvPMc6QKBgBrwZtTNt4cn4ZDl9eW17rHY+3wyjspN0eIF/RVzo78SQLgPkMX+\nrqoxpd9q5f8ky57gex+CyT5LGbnG2/HggrNWDzpkfNOAP0FXaVbIPRnpYEvXu2cL\ndMn2aPudoR6DAEIPwiNElDxTezrKhOS4khWIWqE+1xK8Q/ZeKKZ0gYGDAoGAcc3p\no6FgAfRFYvl0fYNHeQBaPUfc2ujxy4PQAKqXpNtlhuoYYA+79DhwX/IXwUl3L9Am\nDelTQLn/L8oberbNZ59XD0t2ZYYT7r7VxFqv7hWrZh5cW6a4P7IjgrZi3reli0iM\nuS1hpYIYFOvwObgvrs+/qZDG7REx/pXkT6lmwwkCgYEAub91mMF6YR76ETPAdFLs\nfTAP+Q06Ate+gw1Ob6Cf+biF6TXe/B3Ql1R4FzPF9xG1rS/BfI+bUi3W68/jDill\nHnDPvFxX9Q82/KNCY9LlzbuQLWjziyQk6BgXtcKWT1K1zy4tsZZy5WVvXEXdF+XV\n3MMUkEaBHE5iddCl7Kkbvfg=\n-----END PRIVATE KEY-----\n", + "client_email": "test@app-default-test-project.iam.gserviceaccount.com", + "client_id": "1234567890", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test%40app-default-test-project.iam.gserviceaccount.com" +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json new file mode 100644 index 000000000000..cf2157696a80 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "gs-test-project", + "private_key_id": "cloud-storage-key-id", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgFkCu/z3Sn8Py\nIHcUSSyCOjZ17AB/0F5IvhuGtTZTIJ33ltxeYmb69qK0m4QSk75HH5eX1OgF7/6E\nraqDaKlgi8ecSot1XrMRKyIY+LlTLMWeNtG54vymwjeH9wrMWQWfHJUCVUgUE8hL\nxQMEbU2Hn8t6P1JaGkfsm8cLiD0ve25iw/P2OPDdJukBlE2+47OL8RndyziVnLkW\n1y1kfujd83Cnf0sJp78fBKI7IRBWyXTS1C6/reZlkPq+D9ImCvn4YHpI6J1rsSDD\nitDbA0v/8l7KLyJoOK9vsFym4yhs4Q+Nzathv/ozvdHhob8I6JVizb5+D4QJ0GZ4\n9bMIzpV3AgMBAAECggEANbrCQvnP2h1dOqrCzMAyfBLlrHZlRIC+5FNKEdBIR2Yv\nHqY3mEYWoiydN1jq3wFPX7euvXrr1PJTzlwrWqeKEalYeZBbdi0ulJiRfSgdq1jf\nitaDVYxll+KfmLbFnQhT5q9FI99Trcll9GhPNvEokFiFhqYyEaO4eCVgjPJQ9tpC\njnKl9eLeHkhYK1pOKxJVBqzPcZI3F9jNvXWYTO1F7lFMom9I89W+NtBRAeYZnVao\nfH52GDJProB5A9BtRXkuLDzmFFjGjr8oT4E32wLuiu2UvNHgIZe7Hz+fMGGHsDHS\nc5jogukVwgt7QrfKVtoRTk8h2jyIrpRy4AQLfJZ4QQKBgQDT0X3+mp+tbEncLFBW\nXLT1k/1VWumi1TipiVsMpUcAZjWTGO8/WJF83IcNBAFqBJGyTAwplXIyUeI8CGg0\nOkBPY1Cy/dtTyiav05vRPZPkT44mhBua2tyhaE12DVo1/6ezF88yTPQkO9EjlvLs\nW32XlhqGQ8O587xjNaB/rqsjXwKBgQDBenKlO3eDBSfVb/te/xwqeVnKBgEYIAOJ\nN+FE49aH05n8DYQij1m8+Ck6sFBZywWliIQdS6d6J4NE69Ok7bfowwVqoumX8LWD\ntstMkOE2FmPCF4nbxkAFYbcuep1iItA2LVSwh3ChAA6aexA/fV6bMauhJPJTSnwX\nItnKvPMc6QKBgBrwZtTNt4cn4ZDl9eW17rHY+3wyjspN0eIF/RVzo78SQLgPkMX+\nrqoxpd9q5f8ky57gex+CyT5LGbnG2/HggrNWDzpkfNOAP0FXaVbIPRnpYEvXu2cL\ndMn2aPudoR6DAEIPwiNElDxTezrKhOS4khWIWqE+1xK8Q/ZeKKZ0gYGDAoGAcc3p\no6FgAfRFYvl0fYNHeQBaPUfc2ujxy4PQAKqXpNtlhuoYYA+79DhwX/IXwUl3L9Am\nDelTQLn/L8oberbNZ59XD0t2ZYYT7r7VxFqv7hWrZh5cW6a4P7IjgrZi3reli0iM\nuS1hpYIYFOvwObgvrs+/qZDG7REx/pXkT6lmwwkCgYEAub91mMF6YR76ETPAdFLs\nfTAP+Q06Ate+gw1Ob6Cf+biF6TXe/B3Ql1R4FzPF9xG1rS/BfI+bUi3W68/jDill\nHnDPvFxX9Q82/KNCY9LlzbuQLWjziyQk6BgXtcKWT1K1zy4tsZZy5WVvXEXdF+XV\n3MMUkEaBHE5iddCl7Kkbvfg=\n-----END PRIVATE KEY-----\n", + "client_email": "cloud-storage@gs-test-project.iam.gserviceaccount.com", + "client_id": "1234567890", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cloud-storage%40gs-test-project.iam.gserviceaccount.com" +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key.json b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key.json new file mode 100644 index 000000000000..b7f5351350a2 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/test-key.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "test-project", + "private_key_id": "some-key-id", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgFkCu/z3Sn8Py\nIHcUSSyCOjZ17AB/0F5IvhuGtTZTIJ33ltxeYmb69qK0m4QSk75HH5eX1OgF7/6E\nraqDaKlgi8ecSot1XrMRKyIY+LlTLMWeNtG54vymwjeH9wrMWQWfHJUCVUgUE8hL\nxQMEbU2Hn8t6P1JaGkfsm8cLiD0ve25iw/P2OPDdJukBlE2+47OL8RndyziVnLkW\n1y1kfujd83Cnf0sJp78fBKI7IRBWyXTS1C6/reZlkPq+D9ImCvn4YHpI6J1rsSDD\nitDbA0v/8l7KLyJoOK9vsFym4yhs4Q+Nzathv/ozvdHhob8I6JVizb5+D4QJ0GZ4\n9bMIzpV3AgMBAAECggEANbrCQvnP2h1dOqrCzMAyfBLlrHZlRIC+5FNKEdBIR2Yv\nHqY3mEYWoiydN1jq3wFPX7euvXrr1PJTzlwrWqeKEalYeZBbdi0ulJiRfSgdq1jf\nitaDVYxll+KfmLbFnQhT5q9FI99Trcll9GhPNvEokFiFhqYyEaO4eCVgjPJQ9tpC\njnKl9eLeHkhYK1pOKxJVBqzPcZI3F9jNvXWYTO1F7lFMom9I89W+NtBRAeYZnVao\nfH52GDJProB5A9BtRXkuLDzmFFjGjr8oT4E32wLuiu2UvNHgIZe7Hz+fMGGHsDHS\nc5jogukVwgt7QrfKVtoRTk8h2jyIrpRy4AQLfJZ4QQKBgQDT0X3+mp+tbEncLFBW\nXLT1k/1VWumi1TipiVsMpUcAZjWTGO8/WJF83IcNBAFqBJGyTAwplXIyUeI8CGg0\nOkBPY1Cy/dtTyiav05vRPZPkT44mhBua2tyhaE12DVo1/6ezF88yTPQkO9EjlvLs\nW32XlhqGQ8O587xjNaB/rqsjXwKBgQDBenKlO3eDBSfVb/te/xwqeVnKBgEYIAOJ\nN+FE49aH05n8DYQij1m8+Ck6sFBZywWliIQdS6d6J4NE69Ok7bfowwVqoumX8LWD\ntstMkOE2FmPCF4nbxkAFYbcuep1iItA2LVSwh3ChAA6aexA/fV6bMauhJPJTSnwX\nItnKvPMc6QKBgBrwZtTNt4cn4ZDl9eW17rHY+3wyjspN0eIF/RVzo78SQLgPkMX+\nrqoxpd9q5f8ky57gex+CyT5LGbnG2/HggrNWDzpkfNOAP0FXaVbIPRnpYEvXu2cL\ndMn2aPudoR6DAEIPwiNElDxTezrKhOS4khWIWqE+1xK8Q/ZeKKZ0gYGDAoGAcc3p\no6FgAfRFYvl0fYNHeQBaPUfc2ujxy4PQAKqXpNtlhuoYYA+79DhwX/IXwUl3L9Am\nDelTQLn/L8oberbNZ59XD0t2ZYYT7r7VxFqv7hWrZh5cW6a4P7IjgrZi3reli0iM\nuS1hpYIYFOvwObgvrs+/qZDG7REx/pXkT6lmwwkCgYEAub91mMF6YR76ETPAdFLs\nfTAP+Q06Ate+gw1Ob6Cf+biF6TXe/B3Ql1R4FzPF9xG1rS/BfI+bUi3W68/jDill\nHnDPvFxX9Q82/KNCY9LlzbuQLWjziyQk6BgXtcKWT1K1zy4tsZZy5WVvXEXdF+XV\n3MMUkEaBHE5iddCl7Kkbvfg=\n-----END PRIVATE KEY-----\n", + "client_email": "test@test-project.iam.gserviceaccount.com", + "client_id": "1234567890", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://accounts.google.com/o/oauth2/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test%40test-project.iam.gserviceaccount.com" +} From effec32065600630963a4dd12379cb64984302ec Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Mon, 5 Aug 2019 15:27:40 -0400 Subject: [PATCH 0003/1979] Change JDBC version number to 0.0.1-SNAPSHOT for release prep. (#6021) * Change JDBC version number to 0.0.1-SNAPSHOT for release prep. * remove examples section until it is added --- java-spanner-jdbc/README.md | 12 ------------ java-spanner-jdbc/pom.xml | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 26c755f9d03a..bd12b5994aef 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -70,18 +70,6 @@ See the [Authentication](https://github.com/googleapis/google-cloud-java#authentication) section in the base directory's README for more information. -## Examples - -The google-cloud-spanner-jdbc-examples project contains a number of examples on how to use the JDBC Driver. These include: - -* JdbcConnectExamples: Contains examples on how to obtain a JDBC connection for Cloud Spanner. -* JdbcAutocommitExamples: Contains examples on how to use a JDBC connection in autocommit mode. -* JdbcTransactionExamples: Contains examples on how to use the JDBC connection with read/write and read-only transactions. -* JdbcBatchExamples: Shows the batching capabilities of the Cloud Spanner JDBC Driver. -* JdbcVariablesExamples: Shows how to use custom SQL statements to read and write variables from a JDBC connection. -* JdbcCustomMethodsExample: Shows how to use the custom methods that are exposed by the `com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection` interface. - - ## Shaded JAR You can build a shaded JAR of the JDBC Driver to use with third-party tools using the following command: diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b32661ac5142..f9664df51f8f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.1.0 + 0.0.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc From 28022dd193d79fdb65c556c02c27844c3c95bf3e Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 6 Aug 2019 02:19:14 +0300 Subject: [PATCH 0004/1979] Update dependency org.apache.maven.plugins:maven-jar-plugin to v3 (#6020) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f9664df51f8f..ab812d44964a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.5 + 3.1.2 From a87dd065b8cef5f1429a21fff6858a27a7248e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 6 Aug 2019 16:44:44 +0200 Subject: [PATCH 0005/1979] use standard data model for tests (#6032) --- .../spanner/jdbc/StatementParserTest.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java index 38def439eeea..7e17c6d3f052 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java @@ -103,23 +103,25 @@ public void testStatementWithCommentContainingSlash() { + "\n" + "-- MERGE into test comment MERGE -- \n" + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO wines w\n" + + "MERGE INTO Singers s\n" + "/*** test ****/" - + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" - + "ON v.column1 = w.winename\n" + + "USING (VALUES (1, 'John', 'Doe')) v\n" + + "ON v.column1 = s.SingerId\n" + "WHEN NOT MATCHED \n" - + " INSERT VALUES(v.column1, v.column2)\n" + + " INSERT VALUES (v.column1, v.column2, v.column3)\n" + "WHEN MATCHED\n" - + " UPDATE SET stock = stock + v.column2;\n"; + + " UPDATE SET FirstName = v.column2,\n" + + " LastName = v.column3;"; String sqlWithoutComments = "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO wines w\n" - + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" - + "ON v.column1 = w.winename\n" + + "MERGE INTO Singers s\n" + + "USING (VALUES (1, 'John', 'Doe')) v\n" + + "ON v.column1 = s.SingerId\n" + "WHEN NOT MATCHED \n" - + " INSERT VALUES(v.column1, v.column2)\n" + + " INSERT VALUES (v.column1, v.column2, v.column3)\n" + "WHEN MATCHED\n" - + " UPDATE SET stock = stock + v.column2;"; + + " UPDATE SET FirstName = v.column2,\n" + + " LastName = v.column3"; ParsedStatement statement = parser.parse(Statement.of(sql)); assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); } @@ -134,23 +136,25 @@ public void testStatementWithCommentContainingSlashAndNoAsteriskOnNewLine() { + "\n" + "-- MERGE INTO test comment MERGE\n" + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO wines w\n" - + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" - + "ON v.column1 = w.winename\n" + + "MERGE INTO Singers s\n" + + "USING (VALUES (1, 'John', 'Doe')) v\n" + + "ON v.column1 = s.SingerId\n" + "-- test again --\n" + "WHEN NOT MATCHED \n" - + " INSERT VALUES(v.column1, v.column2)\n" + + " INSERT VALUES (v.column1, v.column2, v.column3)\n" + "WHEN MATCHED\n" - + " UPDATE SET stock = stock + v.column2;\n"; + + " UPDATE SET FirstName = v.column2,\n" + + " LastName = v.column3;"; String sqlWithoutComments = "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO wines w\n" - + "USING (VALUES('Chateau Lafite 2003', '24')) v\n" - + "ON v.column1 = w.winename\n" + + "MERGE INTO Singers s\n" + + "USING (VALUES (1, 'John', 'Doe')) v\n" + + "ON v.column1 = s.SingerId\n" + "\nWHEN NOT MATCHED \n" - + " INSERT VALUES(v.column1, v.column2)\n" + + " INSERT VALUES (v.column1, v.column2, v.column3)\n" + "WHEN MATCHED\n" - + " UPDATE SET stock = stock + v.column2;"; + + " UPDATE SET FirstName = v.column2,\n" + + " LastName = v.column3"; ParsedStatement statement = parser.parse(Statement.of(sql)); assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); } From 68414664cda493fc2177ef937bff95964a9a36df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 7 Aug 2019 04:55:41 +0200 Subject: [PATCH 0006/1979] spanner-jdbc: Fix potential flaky integration test (#6036) * fix potential flaky test This integration test could be flaky as it assumed that a transaction would abort an exact number of times, but fact is that Spanner could abort a transaction at any time. The test case has therefore been changed to check that AT LEAST the expected number of aborts occurred. More than the expected number of aborts is also accepted. * fix comparison --- .../jdbc/it/ITTransactionRetryTest.java | 141 ++++++++---------- 1 file changed, 65 insertions(+), 76 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java index 18b8bcce3a42..0ece44ed05f7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java @@ -179,13 +179,12 @@ public void testCommitAborted() { interceptor.setOnlyInjectOnce(true); // do a commit that will first abort, and then on retry will succeed connection.commit(); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalRetryAttemptsFinished, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= 1, is(true)); + assertThat(RETRY_STATISTICS.totalRetryAttemptsFinished >= 1, is(true)); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); assertThat(RETRY_STATISTICS.totalErroredRetries, is(equalTo(0))); assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(0))); assertThat(RETRY_STATISTICS.totalMaxAttemptsExceeded, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); // verify that the insert succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { @@ -217,7 +216,7 @@ public void testInsertAborted() { Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); // do a commit connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that the insert succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { @@ -251,7 +250,7 @@ public void testUpdateAborted() { connection.executeUpdate(Statement.of("UPDATE TEST SET NAME='update aborted' WHERE ID=1")); // do a commit connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that the update succeeded try (ResultSet rs = connection.executeQuery( @@ -292,7 +291,7 @@ public void testQueryAborted() { } // do a commit connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that the update succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { @@ -317,19 +316,18 @@ public void testNextCallAborted() { // the first record should be accessible without any problems assertThat(rs.next(), is(true)); assertThat(rs.getLong("ID"), is(equalTo(1L))); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); // indicate that the next statement should abort interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); assertThat(rs.next(), is(true)); assertThat(rs.getLong("ID"), is(equalTo(2L))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // there should be only two records assertThat(rs.next(), is(false)); } connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that the transaction succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { assertThat(rs.next(), is(true)); @@ -364,8 +362,10 @@ public void testMultipleAborts() { connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(3))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 3, is(true)); + assertThat( + RETRY_STATISTICS.totalNestedAborts, + is(equalTo(RETRY_STATISTICS.totalSuccessfulRetries - 3))); // verify that the insert succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { assertThat(rs.next(), is(true)); @@ -412,7 +412,7 @@ public void testAbortAfterSelect() { assertThat(rs.next(), is(false)); } connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); } } @@ -445,7 +445,7 @@ public void testAbortWithResultSetHalfway() { assertThat(rs.next(), is(false)); } connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that all the inserts succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { assertThat(rs.next(), is(true)); @@ -475,7 +475,7 @@ public void testAbortWithResultSetFullyConsumed() { interceptor.setOnlyInjectOnce(true); connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); // verify that all the inserts succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { assertThat(rs.next(), is(true)); @@ -515,9 +515,7 @@ public void testAbortWithConcurrentInsert() { expectedException = true; } assertThat(expectedException, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } } @@ -555,9 +553,7 @@ public void testAbortWithConcurrentDelete() { expectedException = true; } assertThat(expectedException, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } } @@ -595,9 +591,7 @@ public void testAbortWithConcurrentUpdate() { expectedException = true; } assertThat(expectedException, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } } @@ -628,9 +622,9 @@ public void testAbortWithUnseenConcurrentInsert() { // now try to do an insert that will abort. The retry should still succeed. interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted; connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(currentRetryCount + 1))); // Consume the rest of the result set. The insert by the other transaction should now be // included in the result set as the transaction retried. Although this means that the result // is different after a retry, it is not different as seen by the user, as the user didn't @@ -642,7 +636,7 @@ public void testAbortWithUnseenConcurrentInsert() { assertThat(rs.next(), is(false)); rs.close(); connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); } } @@ -656,13 +650,13 @@ public void testAbortWithUnseenConcurrentInsert() { @Test public void testAbortWithUnseenConcurrentInsertAbortOnNext() { // no calls to next(), this should succeed - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(0), is(equalTo(1))); + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(0) >= 1, is(true)); // 1 call to next() should also succeed, as there were 2 records in the original result set - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(1), is(equalTo(1))); + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(1) >= 1, is(true)); // 2 calls to next() should also succeed, as there were 2 records in the original result set and // the user doesn't know yet that the next call to next() will return true instead of false // after the concurrent insert - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(2), is(equalTo(1))); + assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(2) >= 1, is(true)); boolean expectedException = false; try { @@ -708,7 +702,7 @@ private int testAbortWithUnseenConcurrentInsertAbortOnNext(int callsToNext) // been a record with ID 3 or not. // First verify that the transaction has not yet retried. - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted; interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); @@ -721,7 +715,7 @@ private int testAbortWithUnseenConcurrentInsertAbortOnNext(int callsToNext) } } // Verify that the transaction retried. - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries > currentRetryCount, is(true)); rs.close(); connection.commit(); retries = RETRY_STATISTICS.totalSuccessfulRetries; @@ -763,10 +757,7 @@ public void testAbortWithConcurrentInsertAndContinue() { expectedException = true; } assertThat(expectedException, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); - + assertRetryStatistics(1, 1, 0); // the next statement should be in a new transaction as the previous transaction rolled back try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { // there should be one record from the transaction on connection2 @@ -807,9 +798,7 @@ protected boolean shouldAbort(String statement, ExecutionStep step) { Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); connection.commit(); // Assert that the transaction was retried twice. - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(2))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(0))); + assertRetryStatistics(2, 0, 2); // Verify that the insert succeeded. try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { @@ -855,9 +844,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) { connection.commit(); // Assert that the transaction was retried (a restarted retry is counted as one successful // retry). - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); + assertRetryStatistics(2, 0, 1); + assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); // Verify that the insert succeeded. try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { @@ -923,9 +911,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) { } connection.commit(); // Verify that the transaction retried. - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); + assertRetryStatistics(2, 0, 1); + assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); // Verify that all the inserts succeeded. try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { assertThat(rs.next(), is(true)); @@ -994,10 +981,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) { expectedException = true; } assertThat(expectedException, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(2))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalNestedAborts, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(2, 1, 0); + assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); } } @@ -1042,8 +1027,7 @@ public void testAbortWithDifferentUpdateCount() { } catch (AbortedDueToConcurrentModificationException e) { expectedException = true; } - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); assertThat(expectedException, is(true)); } } @@ -1091,8 +1075,7 @@ public void testAbortWithExceptionOnSelect() { interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertRetryStatistics(1, 0, 1); } } @@ -1160,9 +1143,7 @@ public void testAbortWithExceptionOnSelectAndConcurrentModification() { connection2.execute(Statement.of("DROP TABLE FOO")); } assertThat(abortedDueToConcurrentModification, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } /** @@ -1227,9 +1208,7 @@ public void testAbortWithExceptionOnInsertAndConcurrentModification() { connection2.execute(Statement.of("DROP TABLE FOO")); } assertThat(abortedDueToConcurrentModification, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } /** @@ -1291,9 +1270,7 @@ public void testAbortWithDroppedTableConcurrentModification() { } } assertThat(abortedDueToConcurrentModification, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } /** @@ -1352,9 +1329,7 @@ public void testAbortWithInsertOnDroppedTableConcurrentModification() { } } assertThat(abortedDueToConcurrentModification, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } /** @@ -1417,9 +1392,7 @@ public void testAbortWithCursorHalfwayDroppedTableConcurrentModification() { } } assertThat(abortedDueToConcurrentModification, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); + assertRetryStatistics(1, 1, 0); } /** Test the successful retry of a transaction with a large {@link ResultSet} */ @@ -1465,8 +1438,7 @@ public void testRetryLargeResultSet() { assertThat(rs.next(), is(false)); } // Verify that the transaction retried. - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertRetryStatistics(1, 0, 1); } } @@ -1545,9 +1517,10 @@ public void testAbortWithConcurrentInsertOnEmptyTable() { // The retry should still succeed. interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); + int currentSuccessfulRetryCount = RETRY_STATISTICS.totalSuccessfulRetries; assertThat(rs.next(), is(true)); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(1))); + assertThat( + RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(currentSuccessfulRetryCount + 1))); assertThat(rs.next(), is(false)); } connection.commit(); @@ -1568,7 +1541,6 @@ public void testAbortWithConcurrentInsertOnEmptyTable() { // this time the abort will occur on the call to commit() interceptor.setProbability(1.0); interceptor.setOnlyInjectOnce(true); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(0))); boolean expectedException = false; try { connection.commit(); @@ -1576,11 +1548,28 @@ public void testAbortWithConcurrentInsertOnEmptyTable() { expectedException = true; } // No successful retries. - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(1))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(0))); + assertRetryStatistics(1, 1, 0); assertThat(expectedException, is(true)); } } } + + private void assertRetryStatistics( + int minAttemptsStartedExpected, + int concurrentModificationsExpected, + int successfulRetriesExpected) { + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= minAttemptsStartedExpected, is(true)); + assertThat( + RETRY_STATISTICS.totalConcurrentModifications, + is(equalTo(concurrentModificationsExpected))); + // There might be more retry attempts than expected. The number of successful retries should be + // equal to the actual difference between started and successful. + assertThat( + RETRY_STATISTICS.totalSuccessfulRetries, + is( + equalTo( + RETRY_STATISTICS.totalRetryAttemptsStarted + - minAttemptsStartedExpected + + successfulRetriesExpected))); + } } From 5c09380c3d7fd835686d1e582a6d21bdf2ffa534 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 7 Aug 2019 07:49:53 -0700 Subject: [PATCH 0007/1979] spanner-jdbc: Add beta note to README and cleanup pom.xml (#6047) * spanner-jdbc: Add beta note to README * Clean up pom.xml --- java-spanner-jdbc/README.md | 3 +++ java-spanner-jdbc/pom.xml | 12 ------------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index bd12b5994aef..3bd2cb5dddf6 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -3,6 +3,9 @@ JDBC Driver for [Google Cloud Spanner](https://cloud.google.com/spanner/). +> Note: This client is a work-in-progress, and may occasionally +> make backwards-incompatible changes. + ## Quickstart [//]: # ({x-version-update-start:google-cloud-spanner-jdbc:released}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ab812d44964a..9dbbd8c1928d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -55,18 +55,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 3.1.2 - - - - test-jar - - - - org.apache.maven.plugins maven-surefire-plugin From e8fa0ed9ca3fb082e8bd4f1c7abd752733e5b962 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 7 Aug 2019 10:00:27 -0700 Subject: [PATCH 0008/1979] Release v0.104.0 (#6048) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9dbbd8c1928d..8afb3052d7ea 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.0.1-SNAPSHOT + 0.1.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.103.1-alpha-SNAPSHOT + 0.104.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.30.1-SNAPSHOT + 1.31.0 test-jar test From 6f840ae074508df6b283a4c48ef9ac887c823ada Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 8 Aug 2019 12:07:43 -0700 Subject: [PATCH 0009/1979] Bump next snapshot (#6055) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8afb3052d7ea..77a24fc07e61 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.1.0 + 0.1.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.104.0-alpha + 0.104.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.31.0 + 1.31.1-SNAPSHOT test-jar test From b765348e50b7ba84f0e7f4d52a682f6f4d65d7b3 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 14 Aug 2019 15:10:32 -0400 Subject: [PATCH 0010/1979] Release v0.105.0 (#6077) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 3bd2cb5dddf6..73642fe7d2be 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -14,16 +14,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 0.1.0 + 0.2.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:0.1.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:0.2.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.1.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.2.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 77a24fc07e61..934e848271ce 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.1.1-SNAPSHOT + 0.2.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.104.1-alpha-SNAPSHOT + 0.105.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.31.1-SNAPSHOT + 1.32.0 test-jar test From ec760dd1fd483f9664b40dabeb17b42efcce06cd Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 14 Aug 2019 20:03:16 -0400 Subject: [PATCH 0011/1979] Bump next snapshot (#6079) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 934e848271ce..3dafde9e15de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.2.0 + 0.2.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.105.0-alpha + 0.105.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.32.0 + 1.32.1-SNAPSHOT test-jar test From f64aca849d59a2df2531d328f6543e3053401f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 16 Aug 2019 16:36:16 +0200 Subject: [PATCH 0012/1979] fix flaky timeouts in tests (#6094) --- .../spanner/jdbc/StatementTimeoutTest.java | 149 ++++++++++-------- 1 file changed, 84 insertions(+), 65 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java index 9c308e396325..03eb5a1b63da 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java @@ -72,6 +72,28 @@ public class StatementTimeoutTest { private static final String SLOW_UPDATE = "UPDATE foo SET col1=1 WHERE id=2"; private static final String FAST_UPDATE = "UPDATE fast_table SET foo=1 WHERE bar=2"; + /** Execution time for statements that have been defined as slow. */ + private static final long EXECUTION_TIME_SLOW_STATEMENT = 10_000L; + /** + * This timeout should be high enough that it will never be exceeded, even on a slow build + * environment, but still significantly lower than the expected execution time of the slow + * statements. + */ + private static final long TIMEOUT_FOR_FAST_STATEMENTS = 1000L; + + /** + * This timeout should be low enough that it will not make the test case unnecessarily slow, but + * still high enough that it would normally not be exceeded for a statement that is executed + * directly. + */ + private static final long TIMEOUT_FOR_SLOW_STATEMENTS = 20L; + /** + * The number of milliseconds to wait before cancelling a query should be high enough to not cause + * flakiness on a slow environment, but at the same time low enough that it does not slow down the + * test case unnecessarily. + */ + private static final int WAIT_BEFORE_CANCEL = 100; + private enum CommitRollbackBehavior { FAST, SLOW_COMMIT, @@ -83,7 +105,7 @@ private enum CommitRollbackBehavior { private static final class DelayedQueryExecution implements Answer { @Override public ResultSet answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10000L); + Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); return mock(ResultSet.class); } } @@ -142,7 +164,7 @@ private ConnectionImpl createConnection( SpannerPool spannerPool = mock(SpannerPool.class); when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) .thenReturn(spanner); - DdlClient ddlClient = createDefaultMockDdlClient(10000L); + DdlClient ddlClient = createDefaultMockDdlClient(EXECUTION_TIME_SLOW_STATEMENT); final ResultSet invalidResultSet = mock(ResultSet.class); when(invalidResultSet.next()) .thenThrow( @@ -192,7 +214,7 @@ public TransactionContext answer(InvocationOnMock invocation) @Override public Long answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10000L); + Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); return 1L; } }); @@ -205,7 +227,7 @@ public Long answer(InvocationOnMock invocation) new Answer() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10000L); + Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); return null; } }) @@ -217,7 +239,7 @@ public Void answer(InvocationOnMock invocation) throws Throwable { new Answer() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10000L); + Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); return null; } }) @@ -234,7 +256,7 @@ public Void answer(InvocationOnMock invocation) throws Throwable { new Answer() { @Override public Long answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10000L); + Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); return 1L; } }); @@ -250,8 +272,7 @@ public void testTimeoutExceptionReadOnlyAutocommit() { .setUri(URI) .build())) { connection.setReadOnly(true); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.executeQuery(Statement.of(SLOW_SELECT)); } @@ -266,8 +287,7 @@ public void testTimeoutExceptionReadOnlyAutocommitMultipleStatements() { .setUri(URI) .build())) { connection.setReadOnly(true); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { boolean timedOut = false; @@ -279,7 +299,7 @@ public void testTimeoutExceptionReadOnlyAutocommitMultipleStatements() { assertThat(timedOut, is(true)); } // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -294,8 +314,7 @@ public void testTimeoutExceptionReadOnlyTransactional() { .build())) { connection.setReadOnly(true); connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.executeQuery(Statement.of(SLOW_SELECT)); } @@ -311,8 +330,7 @@ public void testTimeoutExceptionReadOnlyTransactionMultipleStatements() { .build())) { connection.setReadOnly(true); connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { boolean timedOut = false; @@ -327,7 +345,7 @@ public void testTimeoutExceptionReadOnlyTransactionMultipleStatements() { connection.clearStatementTimeout(); connection.rollback(); // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -340,8 +358,7 @@ public void testTimeoutExceptionReadWriteAutocommit() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.executeQuery(Statement.of(SLOW_SELECT)); } @@ -355,8 +372,7 @@ public void testTimeoutExceptionReadWriteAutocommitMultipleStatements() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { boolean timedOut = false; @@ -368,7 +384,7 @@ public void testTimeoutExceptionReadWriteAutocommitMultipleStatements() { assertThat(timedOut, is(true)); } // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -381,7 +397,7 @@ public void testTimeoutExceptionReadWriteAutocommitSlowUpdate() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.execute(Statement.of(SLOW_UPDATE)); } @@ -395,7 +411,7 @@ public void testTimeoutExceptionReadWriteAutocommitSlowUpdateMultipleStatements( .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { @@ -408,7 +424,7 @@ public void testTimeoutExceptionReadWriteAutocommitSlowUpdateMultipleStatements( assertThat(timedOut, is(true)); } // try to do a new update that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.execute(Statement.of(FAST_UPDATE)).getUpdateCount(), is(equalTo(1L))); } } @@ -422,13 +438,16 @@ public void testTimeoutExceptionReadWriteAutocommitSlowCommit() { .setUri(URI) .build(), CommitRollbackBehavior.SLOW_COMMIT)) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - // first verify that the fast update does not timeout when in transactional mode (as it is the - // commit that is slow) + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); + // First verify that the fast update does not timeout when in transactional mode (as it is the + // commit that is slow). connection.setAutocommit(false); connection.execute(Statement.of(FAST_UPDATE)); connection.rollback(); + // Then verify that the update does timeout when executed in autocommit mode, as the commit + // gRPC call will be slow. + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); connection.setAutocommit(true); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.execute(Statement.of(FAST_UPDATE)); @@ -444,8 +463,7 @@ public void testTimeoutExceptionReadWriteAutocommitSlowCommitMultipleStatements( .setUri(URI) .build(), CommitRollbackBehavior.SLOW_COMMIT)) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { boolean timedOut = false; @@ -457,7 +475,7 @@ public void testTimeoutExceptionReadWriteAutocommitSlowCommitMultipleStatements( assertThat(timedOut, is(true)); } // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -470,11 +488,12 @@ public void testTimeoutExceptionReadWriteAutocommitPartitioned() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); // first verify that the fast update does not timeout + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); connection.execute(Statement.of(FAST_UPDATE)); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.execute(Statement.of(SLOW_UPDATE)); } @@ -489,8 +508,7 @@ public void testTimeoutExceptionReadWriteTransactional() { .setUri(URI) .build())) { connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.executeQuery(Statement.of(SLOW_SELECT)); } @@ -505,8 +523,7 @@ public void testTimeoutExceptionReadWriteTransactionMultipleStatements() { .setUri(URI) .build())) { connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // Assert that multiple statements after each other will timeout the first time, and then // throw a SpannerException with code FAILED_PRECONDITION. boolean timedOut = false; @@ -527,7 +544,7 @@ public void testTimeoutExceptionReadWriteTransactionMultipleStatements() { connection.clearStatementTimeout(); connection.rollback(); // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -542,9 +559,11 @@ public void testTimeoutExceptionReadWriteTransactionalSlowCommit() { .build(), CommitRollbackBehavior.SLOW_COMMIT)) { connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); connection.executeQuery(Statement.of(FAST_SELECT)); + + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.commit(); } @@ -560,9 +579,10 @@ public void testTimeoutExceptionReadWriteTransactionalSlowRollback() { .build(), CommitRollbackBehavior.SLOW_ROLLBACK)) { connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); connection.executeQuery(Statement.of(FAST_SELECT)); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.rollback(); } @@ -662,7 +682,7 @@ public void testInvalidQueryReadOnlyAutocommit() { .setCredentials(NoCredentials.getInstance()) .build())) { connection.setReadOnly(true); - connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); connection.executeQuery(Statement.of(INVALID_SELECT)); @@ -679,7 +699,7 @@ public void testInvalidQueryReadOnlyTransactional() { .build())) { connection.setReadOnly(true); connection.setAutocommit(false); - connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); connection.executeQuery(Statement.of(INVALID_SELECT)); @@ -694,7 +714,7 @@ public void testInvalidQueryReadWriteAutocommit() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); connection.executeQuery(Statement.of(INVALID_SELECT)); @@ -710,7 +730,7 @@ public void testInvalidQueryReadWriteTransactional() { .setUri(URI) .build())) { connection.setAutocommit(false); - connection.setStatementTimeout(100L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); connection.executeQuery(Statement.of(INVALID_SELECT)); @@ -734,7 +754,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -759,7 +779,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); boolean cancelled = false; @@ -771,7 +791,7 @@ public void run() { assertThat(cancelled, is(true)); // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -794,7 +814,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -820,7 +840,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); boolean cancelled = false; @@ -832,7 +852,7 @@ public void run() { assertThat(cancelled, is(true)); // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); // rollback and do another fast query connection.rollback(); @@ -856,7 +876,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -880,7 +900,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); boolean cancelled = false; @@ -892,7 +912,7 @@ public void run() { assertThat(cancelled, is(true)); // try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -913,7 +933,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -938,7 +958,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -963,7 +983,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -988,7 +1008,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); boolean cancelled = false; @@ -1002,7 +1022,7 @@ public void run() { connection.rollback(); // Try to do a new query that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); } } @@ -1026,7 +1046,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -1050,7 +1070,7 @@ public void run() { connection.cancel(); } }, - 100, + WAIT_BEFORE_CANCEL, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); @@ -1066,8 +1086,7 @@ public void testTimeoutExceptionDdlAutocommit() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); - + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); connection.execute(Statement.of(SLOW_DDL)); } @@ -1081,7 +1100,7 @@ public void testTimeoutExceptionDdlAutocommitMultipleStatements() { .setCredentials(NoCredentials.getInstance()) .setUri(URI) .build())) { - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { @@ -1094,7 +1113,7 @@ public void testTimeoutExceptionDdlAutocommitMultipleStatements() { assertThat(timedOut, is(true)); } // try to do a new DDL statement that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); } } @@ -1109,7 +1128,7 @@ public void testTimeoutExceptionDdlBatch() { .build())) { connection.setAutocommit(false); connection.startBatchDdl(); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // the following statement will NOT timeout as the statement is only buffered locally connection.execute(Statement.of(SLOW_DDL)); @@ -1128,7 +1147,7 @@ public void testTimeoutExceptionDdlBatchMultipleStatements() { .setUri(URI) .build())) { connection.setAutocommit(false); - connection.setStatementTimeout(20L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); // assert that multiple statements after each other also time out for (int i = 0; i < 2; i++) { @@ -1143,7 +1162,7 @@ public void testTimeoutExceptionDdlBatchMultipleStatements() { assertThat(timedOut, is(true)); } // try to do a new DDL statement that is fast. - connection.setStatementTimeout(1000L, TimeUnit.MILLISECONDS); + connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); connection.startBatchDdl(); assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); connection.runBatch(); From 91884ea3b75fb01a0d3542fb693be607a7fcc193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 16 Aug 2019 17:41:41 +0200 Subject: [PATCH 0013/1979] do not close txmanager twice (#6095) Do not close the TransactionManager twice in two different threads. The fireAndForgetRollbackAndCloseTxManager(...) call will close the transaction manager after the commit. The main thread should not also close the transaction manager. --- .../cloud/spanner/jdbc/SingleUseTransaction.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java index 67e6539f71b1..6dd43997449e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java @@ -444,13 +444,9 @@ && executionTime > getStatementTimeout().getTimeoutValue(TimeUnit.MILLISECONDS)) } } catch (Exception e) { if (txManager != null) { - try { - if (txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { - fireAndForgetRollbackAndCloseTxManager(txManager); - } - } finally { - txManager.close(); + if (txManager.getState() + == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { + fireAndForgetRollbackAndCloseTxManager(txManager); } } throw e; From c1cfbfa396a532bc1dd00bf75fff77bfb2c3e802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 17 Aug 2019 08:06:35 +0200 Subject: [PATCH 0014/1979] use random data for tests (#6098) --- .../jdbc/ITSqlScriptTest_InsertTestData.sql | 30 +++++++++---------- .../ITSqlScriptTest_TestAutocommitDmlMode.sql | 8 ++--- ...ITSqlScriptTest_TestAutocommitReadOnly.sql | 8 ++--- ...ITSqlScriptTest_TestGetCommitTimestamp.sql | 18 +++++------ .../ITSqlScriptTest_TestGetReadTimestamp.sql | 16 +++++----- .../ITSqlScriptTest_TestStatementTimeout.sql | 8 ++--- ...qlScriptTest_TestTemporaryTransactions.sql | 8 ++--- .../ITSqlScriptTest_TestTransactionMode.sql | 6 ++-- ...criptTest_TestTransactionMode_ReadOnly.sql | 4 +-- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql index 03c561885aab..e1434ce35952 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql @@ -25,33 +25,33 @@ SET READONLY = FALSE; @EXPECT UPDATE_COUNT 3 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES(1, 'Marc', 'Richards'), - (2, 'Catalina', 'Smith'), - (3, 'Alice', 'Trentor'); +VALUES(1, 'First 1', 'Last 1'), + (2, 'First 2', 'Last 2'), + (3, 'First 3', 'Last 3'); @EXPECT UPDATE_COUNT 3 INSERT INTO Singers (SingerId, FirstName, LastName) -SELECT 4, 'Lea', 'Martin' +SELECT 4, 'First 4', 'Last 4' UNION ALL -SELECT 5, 'David', 'Lomond' +SELECT 5, 'First 5', 'Last 5' UNION ALL -SELECT 6, 'Elena', 'Campbell'; +SELECT 6, 'First 6', 'Last 6'; @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (10, 'Virginia', 'Watson'); +VALUES (10, 'First 10', 'Last 10'); @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (11, 'Timothy', 'Campbell'); +VALUES (11, 'First 11', 'Last 11'); @EXPECT UPDATE_COUNT 5 INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES - (1, 1, 'Total Junk'), - (1, 2, 'Go, Go, Go'), - (2, 1, 'Green'), - (2, 2, 'Forever Hold Your Peace'), - (2, 3, 'Terrified'); + (1, 1, 'Album 1 1'), + (1, 2, 'Album 1 2'), + (2, 1, 'Album 2 1'), + (2, 2, 'Album 2 2'), + (2, 3, 'Album 2 3'); @EXPECT NO_RESULT COMMIT; @@ -59,12 +59,12 @@ COMMIT; -- Try to insert a record that already exists @EXPECT EXCEPTION ALREADY_EXISTS INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (10, 'Virginia', 'Watson'); +VALUES (10, 'First 10', 'Last 10'); @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED FROM Singers -WHERE FirstName='Virginia' AND LastName='Watson'; +WHERE FirstName='First 10' AND LastName='Last 10'; @EXPECT NO_RESULT ROLLBACK; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql index de9ab155a214..355c356132ea 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql @@ -36,11 +36,11 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; -- Verify that executing an update statement is possible @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Anderson' AS EXPECTED +SELECT LastName AS ACTUAL, 'Some Other Last Name' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -52,11 +52,11 @@ SET AUTOCOMMIT_DML_MODE = 'partitioned_non_atomic'; SHOW VARIABLE AUTOCOMMIT_DML_MODE; @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Richards' +UPDATE Singers SET LastName='Last 1' WHERE SingerId=1; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql index 58f33838ee26..1230c01fa8bc 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql @@ -27,17 +27,17 @@ SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'; -- Verify that executing an update statement fails @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' -UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; -- Verify the same for INSERT and DELETE statements @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' -INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (9999, 'Morten', 'Harket'); +INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (9999, 'First 9999', 'Last 9999'); @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' DELETE FROM Singers; @@ -45,7 +45,7 @@ DELETE FROM Singers; -- Verify that the same error message is given even if the update statements references a non-existent table @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' /* The referenced table does not exist */ -update Artists set LastName='Anderson' +update Artists set LastName='Some Last Name' where ArtistId=1; -- Verify that DDL statements will also cause an exception diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql index 67b236f1a6fa..2baa59741210 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql @@ -25,7 +25,7 @@ SET AUTOCOMMIT = TRUE; SET READONLY = TRUE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -37,7 +37,7 @@ SHOW VARIABLE COMMIT_TIMESTAMP; SET READONLY = FALSE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -51,7 +51,7 @@ SET AUTOCOMMIT = FALSE; SET READONLY = TRUE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -66,7 +66,7 @@ SHOW VARIABLE COMMIT_TIMESTAMP; SET READONLY = FALSE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -81,7 +81,7 @@ SHOW VARIABLE COMMIT_TIMESTAMP; SET AUTOCOMMIT = FALSE; @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Perry' +UPDATE Singers SET LastName='New Last 1' WHERE SingerId=1; @EXPECT NO_RESULT @@ -92,7 +92,7 @@ SHOW VARIABLE COMMIT_TIMESTAMP; -- Reset the value to its original value @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Richards' +UPDATE Singers SET LastName='Last 1' WHERE SingerId=1; @EXPECT NO_RESULT @@ -100,7 +100,7 @@ COMMIT; -- Select query in transactional and read-write mode that rollbacks should not yield a commit timestamp @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -112,7 +112,7 @@ SHOW VARIABLE COMMIT_TIMESTAMP; -- Update statement in transactional and read-write mode that rollbacks should not yield a commit timestamp @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Perry' +UPDATE Singers SET LastName='New Last 1' WHERE SingerId=1; @EXPECT NO_RESULT @@ -127,7 +127,7 @@ SET AUTOCOMMIT = FALSE; SET READONLY = FALSE; @EXPECT EXCEPTION INVALID_ARGUMENT -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM NonExistentTable WHERE SingerId=1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql index 0d709c64cffe..c166d48ed88d 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql @@ -23,7 +23,7 @@ SET AUTOCOMMIT = TRUE; SET READONLY = TRUE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -34,7 +34,7 @@ SHOW VARIABLE READ_TIMESTAMP; SET READONLY = FALSE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -46,7 +46,7 @@ SET AUTOCOMMIT = FALSE; SET READONLY = TRUE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -59,7 +59,7 @@ COMMIT; SET READONLY = FALSE; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -72,7 +72,7 @@ COMMIT; SET AUTOCOMMIT = FALSE; @EXPECT UPDATE_COUNT 1 -UPDATE Singers SET LastName='Perry' +UPDATE Singers SET LastName='New Last 1' WHERE SingerId=1; @EXPECT RESULT_SET 'READ_TIMESTAMP',null @@ -82,7 +82,7 @@ ROLLBACK; -- Verify that the rollback actually worked @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -93,7 +93,7 @@ SET AUTOCOMMIT = TRUE; SET READONLY = TRUE; @EXPECT EXCEPTION INVALID_ARGUMENT -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM NonExistentTable WHERE SingerId=1; @@ -104,7 +104,7 @@ SHOW VARIABLE READ_TIMESTAMP; SET READONLY = FALSE; @EXPECT EXCEPTION INVALID_ARGUMENT -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM NonExistentTable WHERE SingerId=1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql index a66956f4e500..9a9894fafa96 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql @@ -98,7 +98,7 @@ FROM ( -- Try to execute an update that should also timeout @EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' -UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1 OR LastName IN ( SELECT LastName @@ -127,7 +127,7 @@ OR LastName IN ( -- Verify that the record was not updated SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; @@ -207,7 +207,7 @@ ROLLBACK; -- Try to execute an update that should also timeout @EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' -UPDATE Singers SET LastName='Anderson' /* It used to be 'Richards' */ +UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1 OR LastName IN ( SELECT LastName @@ -250,6 +250,6 @@ SET STATEMENT_TIMEOUT=null; ROLLBACK; @EXPECT RESULT_SET -SELECT LastName AS ACTUAL, 'Richards' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 1' AS EXPECTED FROM Singers WHERE SingerId=1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql index 106434be74ee..2a64a2a09f85 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql @@ -25,16 +25,16 @@ SET READONLY = FALSE; BEGIN; @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (9999, 'Vegard', 'Ylvisåker'); +VALUES (9999, 'First 9999', 'Last 9999'); COMMIT; -- Verify that the record is there @EXPECT RESULT_SET -SELECT FirstName AS ACTUAL, 'Vegard' AS EXPECTED +SELECT FirstName AS ACTUAL, 'First 9999' AS EXPECTED FROM Singers WHERE SingerId=9999 UNION ALL -SELECT LastName AS ACTUAL, 'Ylvisåker' AS EXPECTED +SELECT LastName AS ACTUAL, 'Last 9999' AS EXPECTED FROM Singers WHERE SingerId=9999; @@ -42,7 +42,7 @@ WHERE SingerId=9999; BEGIN; @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (9998, 'Bård', 'Ylvisåker'); +VALUES (9998, 'First 9998', 'Last 9998'); ROLLBACK; -- Verify that the record is not there diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql index 3e5aec2139a2..c89dab4f8d8e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql @@ -24,7 +24,7 @@ SET READONLY = FALSE; -- Insert a test record @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (9999, 'Vegard', 'Ylvisåker'); +VALUES (9999, 'First 9999', 'Last 9999'); COMMIT; ---------------------------------------- Test read only transactions --------------------------------------------- @@ -37,7 +37,7 @@ WHERE SingerId=9999; @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' -- try to update a record in a read-only transaction -UPDATE Singers SET FirstName='Peter' WHERE SingerId=9999; +UPDATE Singers SET FirstName='New First Name' WHERE SingerId=9999; -- We are in a read-only transaction that has returned a query, so there should be a read-timestamp @EXPECT RESULT_SET 'READ_TIMESTAMP' @@ -76,7 +76,7 @@ SET TRANSACTION READ WRITE; @EXPECT UPDATE_COUNT 1 INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (9998, 'Bård', 'Ylvisåker'); +VALUES (9998, 'First 9998', 'Last 9998'); COMMIT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql index 0d93454eb291..edd213ff607e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql @@ -24,7 +24,7 @@ SET READONLY = TRUE; -- Verify that trying to insert a test record will fail @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' INSERT INTO Singers (SingerId, FirstName, LastName) -VALUES (9999, 'Vegard', 'Ylvisåker'); +VALUES (9999, 'First 9999', 'Last 9999'); COMMIT; ---------------------------------------- Test read only transactions --------------------------------------------- @@ -37,7 +37,7 @@ WHERE SingerId=1; @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' -- try to update a record in a read-only transaction -UPDATE Singers SET FirstName='Peter' WHERE SingerId=9999; +UPDATE Singers SET FirstName='New First Name' WHERE SingerId=9999; -- We are in a read-only transaction that has returned a query, so there should be a read-timestamp @EXPECT RESULT_SET 'READ_TIMESTAMP' From b0c53890d5a24b6461e717363ddf895c5dbd0f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 19 Aug 2019 16:39:37 +0200 Subject: [PATCH 0015/1979] spanner-jdbc: Add jdbc statement integration tests (#6033) * add jdbc statement integration tests * fix parsing error * replace base64 with random numbers * use generated names --- .../spanner/jdbc/ITAbstractJdbcTest.java | 8 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 941 ++++++++++++++++++ .../jdbc/it/ITJdbcSimpleStatementsTest.java | 155 +++ .../google/cloud/spanner/jdbc/it/Albums.txt | 60 ++ .../google/cloud/spanner/jdbc/it/Concerts.txt | 100 ++ .../spanner/jdbc/it/CreateMusicTables.sql | 88 ++ .../google/cloud/spanner/jdbc/it/Singers.txt | 30 + .../google/cloud/spanner/jdbc/it/Songs.txt | 149 +++ 8 files changed, 1529 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index 1793a618e878..f02eb7704969 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -87,8 +87,12 @@ public static void setup() throws IOException, InterruptedException, ExecutionEx * @return The newly opened JDBC connection. */ public CloudSpannerJdbcConnection createConnection() throws SQLException { - StringBuilder url = - new StringBuilder("jdbc:cloudspanner:/").append(getDatabase().getId().getName()); + StringBuilder url = new StringBuilder("jdbc:cloudspanner:"); + String host = env.getTestHelper().getOptions().getHost(); + if (host != null) { + url.append(host.substring(host.indexOf(':') + 1)); + } + url.append("/").append(getDatabase().getId().getName()); if (hasValidKeyFile()) { url.append(";credentials=").append(getKeyFile()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java new file mode 100644 index 000000000000..40b17452d842 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -0,0 +1,941 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import com.google.api.client.util.Base64; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.common.base.Strings; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.StringReader; +import java.sql.BatchUpdateException; +import java.sql.Connection; +import java.sql.Date; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Scanner; +import java.util.TimeZone; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +/** Integration tests for JDBC {@link PreparedStatement}s. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITJdbcPreparedStatementTest extends ITAbstractJdbcTest { + private static final class Singer { + private final long singerId; + private final String firstName; + private final String lastName; + private final byte[] singerInfo; + private final Date birthDate; + + private static Singer of(String values) { + String[] array = values.split(","); + if (array.length != 5) { + throw new IllegalArgumentException(values); + } + return new Singer( + Long.valueOf(array[0]), // singer id + array[1].substring(1, array[1].length() - 1), // first name + array[2].substring(1, array[2].length() - 1), // last name + parseBytes(array[3].substring(13, array[3].length() - 2)), // singer info + parseDate(array[4].substring(6, array[4].length() - 1)) // birth date + ); + } + + private Singer( + long singerId, String firstName, String lastName, byte[] singerInfo, Date birthDate) { + this.singerId = singerId; + this.firstName = firstName; + this.lastName = lastName; + this.singerInfo = singerInfo; + this.birthDate = birthDate; + } + } + + private static final class Album { + private final long singerId; + private final long albumId; + private final String albumTitle; + private final long marketingBudget; + + private static Album of(String values) { + String[] array = values.split(","); + if (array.length != 4) { + throw new IllegalArgumentException(values); + } + return new Album( + Long.valueOf(array[0]), // singer id + Long.valueOf(array[1]), // album id + array[2].substring(1, array[2].length() - 1), // album title + Long.valueOf(array[3]) // marketing budget + ); + } + + private Album(long singerId, long albumId, String albumTitle, long marketingBudget) { + this.singerId = singerId; + this.albumId = albumId; + this.albumTitle = albumTitle; + this.marketingBudget = marketingBudget; + } + } + + private static final class Song { + private final long singerId; + private final long albumId; + private final long songId; + private final String songName; + private final long duration; + private final String songGenre; + + private static Song of(String values) { + String[] array = values.split(","); + if (array.length != 6) { + throw new IllegalArgumentException(values); + } + return new Song( + Long.valueOf(array[0]), // singer id + Long.valueOf(array[1]), // album id + Long.valueOf(array[2]), // song id + array[3].substring(1, array[3].length() - 1), // song name + Long.valueOf(array[4]), // duration + array[5].substring(1, array[5].length() - 1)); + } + + private Song( + long singerId, + long albumId, + long songId, + String songName, + long duration, + String songGenre) { + this.singerId = singerId; + this.albumId = albumId; + this.songId = songId; + this.songName = songName; + this.duration = duration; + this.songGenre = songGenre; + } + } + + private static final class Concert { + private final long venueId; + private final long singerId; + private final Date concertDate; + private final Timestamp beginTime; + private final Timestamp endTime; + private final Long[] ticketPrices; + + private static Concert of(String values) { + values = values.replaceAll("\\[(\\d+),(\\d+),(\\d+),(\\d+)\\]", "[$1;$2;$3;$4]"); + String[] array = values.split(","); + if (array.length != 6) { + throw new IllegalArgumentException(values); + } + return new Concert( + Long.valueOf(array[0]), // venue id + Long.valueOf(array[1]), // singer id + parseDate(array[2].substring(6, array[2].length() - 1)), // concert date + parseTimestamp(array[3].substring(11, array[3].length() - 1)), // begin time + parseTimestamp(array[4].substring(11, array[4].length() - 1)), // end time + parseLongArray(array[5]) // ticket prices + ); + } + + private Concert( + long venueId, + long singerId, + Date concertDate, + Timestamp beginTime, + Timestamp endTime, + Long[] ticketPrices) { + this.venueId = venueId; + this.singerId = singerId; + this.concertDate = concertDate; + this.beginTime = beginTime; + this.endTime = endTime; + this.ticketPrices = ticketPrices; + } + } + + private static Date parseDate(String value) { + try { + return Date.valueOf(value); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(value); + } + } + + private static Timestamp parseTimestamp(String value) { + try { + return Timestamp.valueOf(value.replace('T', ' ').replace("Z", "")); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(value); + } + } + + private static Long[] parseLongArray(String value) { + String[] values = value.substring(1, value.length() - 1).split(";"); + Long[] res = new Long[values.length]; + for (int index = 0; index < values.length; index++) { + res[index] = Long.valueOf(values[index]); + } + return res; + } + + private static byte[] parseBytes(String value) { + return Base64.decodeBase64(value); + } + + private List createSingers() { + List res = new ArrayList<>(); + for (String singerValue : readValuesFromFile("Singers.txt")) { + res.add(Singer.of(singerValue)); + } + return res; + } + + private List createAlbums() { + List res = new ArrayList<>(); + for (String albumValue : readValuesFromFile("Albums.txt")) { + res.add(Album.of(albumValue)); + } + return res; + } + + private List createSongs() { + List res = new ArrayList<>(); + for (String songValue : readValuesFromFile("Songs.txt")) { + res.add(Song.of(songValue)); + } + return res; + } + + private List createConcerts() { + List res = new ArrayList<>(); + for (String concertValue : readValuesFromFile("Concerts.txt")) { + res.add(Concert.of(concertValue)); + } + return res; + } + + @Override + protected boolean doCreateMusicTables() { + return true; + } + + @Test + public void test01_InsertTestData() throws SQLException { + try (Connection connection = createConnection()) { + connection.setAutoCommit(false); + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?)")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 5); + for (Singer singer : createSingers()) { + ps.setByte(1, (byte) singer.singerId); + ps.setString(2, singer.firstName); + ps.setString(3, singer.lastName); + ps.setBytes(4, singer.singerInfo); + ps.setDate(5, singer.birthDate); + + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); + ps.addBatch(); + // check that adding the current params to a batch will not reset the meta data + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); + } + int[] results = ps.executeBatch(); + for (int res : results) { + assertThat(res, is(equalTo(1))); + } + } + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?)")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 4); + for (Album album : createAlbums()) { + ps.setLong(1, album.singerId); + ps.setLong(2, album.albumId); + ps.setString(3, album.albumTitle); + ps.setLong(4, album.marketingBudget); + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); + assertThat(ps.executeUpdate(), is(equalTo(1))); + // check that calling executeUpdate will not reset the meta data + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); + } + } + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?);")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + for (Song song : createSongs()) { + ps.setByte(1, (byte) song.singerId); + ps.setInt(2, (int) song.albumId); + ps.setShort(3, (short) song.songId); + ps.setNString(4, song.songName); + ps.setLong(5, song.duration); + ps.setCharacterStream(6, new StringReader(song.songGenre)); + assertInsertSongParameterMetadata(ps.getParameterMetaData()); + assertThat(ps.executeUpdate(), is(equalTo(1))); + // check that calling executeUpdate will not reset the meta data + assertInsertSongParameterMetadata(ps.getParameterMetaData()); + } + } + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + for (Concert concert : createConcerts()) { + ps.setLong(1, concert.venueId); + ps.setLong(2, concert.singerId); + ps.setDate(3, concert.concertDate); + ps.setTimestamp(4, concert.beginTime); + ps.setTimestamp(5, concert.endTime); + ps.setArray(6, connection.createArrayOf("INT64", concert.ticketPrices)); + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); + assertThat(ps.executeUpdate(), is(equalTo(1))); + // check that calling executeUpdate will not reset the meta data + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); + } + } + connection.commit(); + } + } + + @Test + public void test02_VerifyTestData() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.createStatement().executeQuery("SELECT COUNT(*) FROM Singers")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(30))); + assertThat(rs.next(), is(false)); + } + try (ResultSet rs = + connection.createStatement().executeQuery("SELECT COUNT(*) FROM Albums")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getByte(1), is(equalTo((byte) 60))); + assertThat(rs.next(), is(false)); + } + try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Songs")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getShort(1), is(equalTo((short) 149))); + assertThat(rs.next(), is(false)); + } + try (ResultSet rs = + connection.createStatement().executeQuery("SELECT COUNT(*) FROM Concerts")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(100L))); + assertThat(rs.next(), is(false)); + } + try (PreparedStatement ps = + connection.prepareStatement("SELECT * FROM Concerts WHERE VenueId=? AND SingerId=?")) { + ps.setLong(1, 1L); + ps.setLong(2, 1L); + // Expected: + // (1,1,DATE '2003-06-19',TIMESTAMP '2003-06-19T12:30:05Z',TIMESTAMP + // '2003-06-19T18:57:15Z',[11,93,140,923]); + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs.getLong(2), is(equalTo(1L))); + assertThat(rs.getDate(3), is(equalTo(Date.valueOf("2003-06-19")))); + assertThat(rs.getTimestamp(4), is(equalTo(Timestamp.valueOf("2003-06-19 12:30:05")))); + assertThat(rs.getTimestamp(5), is(equalTo(Timestamp.valueOf("2003-06-19 18:57:15")))); + assertThat(((Long[]) rs.getArray(6).getArray())[0], is(equalTo(11L))); + } + } + } + } + + @SuppressWarnings("deprecation") + @Test + public void test03_Dates() throws SQLException { + List expectedValues = new ArrayList<>(); + expectedValues.add("2008-01-01"); + expectedValues.add("2000-01-01"); + expectedValues.add("1900-01-01"); + expectedValues.add("2000-02-29"); + expectedValues.add("2004-02-29"); + expectedValues.add("2018-12-31"); + expectedValues.add("2015-11-15"); + expectedValues.add("2015-11-15"); + expectedValues.add("2015-11-15"); + + List testDates = new ArrayList<>(); + testDates.add(Date.valueOf("2008-01-01")); + testDates.add(Date.valueOf("2000-01-01")); + testDates.add(Date.valueOf("1900-01-01")); + testDates.add(Date.valueOf("2000-02-29")); + testDates.add(Date.valueOf("2004-02-29")); + testDates.add(Date.valueOf("2018-12-31")); + + // Cloud Spanner does not store any timezone information, meaning that it shouldn't matter in + // what timezone a date is sent to Cloud Spanner, the same date in the local timezone (or the + // requested timezone) should be returned. + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.clear(); + cal.set(2015, 10, 15, 10, 0, 0); + testDates.add(new Date(cal.getTimeInMillis())); + + cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); + cal.clear(); + cal.set(2015, 10, 15, 10, 0, 0); + testDates.add(new Date(cal.getTimeInMillis())); + + cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); + cal.clear(); + cal.set(2015, 10, 15, 10, 0, 0); + testDates.add(new Date(cal.getTimeInMillis())); + + List calendars = new ArrayList<>(); + calendars.add(null); + calendars.add(Calendar.getInstance()); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("CET"))); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("PST"))); + + try (Connection connection = createConnection()) { + for (Calendar testCalendar : calendars) { + int index = 0; + for (Date testDate : testDates) { + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + ps.setLong(1, 100); + ps.setLong(2, 19); + ps.setDate(3, testDate); + ps.setTimestamp(4, new Timestamp(System.currentTimeMillis())); + ps.setTimestamp(5, new Timestamp(System.currentTimeMillis())); + ps.setArray(6, connection.createArrayOf("INT64", new Long[] {})); + ps.executeUpdate(); + } + + try (PreparedStatement ps = + connection.prepareStatement( + "SELECT * FROM Concerts WHERE VenueId=? AND SingerId=?")) { + ps.setLong(1, 100L); + ps.setLong(2, 19L); + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + if (testCalendar == null) { + assertThat(rs.getDate(3), is(equalTo(Date.valueOf(expectedValues.get(index))))); + } else { + // Parse the date in the local timezone. + Date date = Date.valueOf(expectedValues.get(index)); + // Create a calendar in the test timezone with only the date part set. + Calendar localCalendar = Calendar.getInstance(testCalendar.getTimeZone()); + localCalendar.clear(); + localCalendar.set(date.getYear() + 1900, date.getMonth(), date.getDate()); + // Check that the actual time of the date returned by the ResultSet is equal to the + // local time in the timezone of the Calendar that is used. + assertThat( + rs.getDate(3, testCalendar), + is(equalTo(new Date(localCalendar.getTimeInMillis())))); + } + } + } + connection + .createStatement() + .execute("DELETE FROM Concerts WHERE VenueId=100 AND SingerId=19"); + index++; + } + } + } + } + + @Test + public void test04_Timestamps() throws SQLException { + List expectedValues = new ArrayList<>(); + expectedValues.add("2008-01-01 10:00:00"); + expectedValues.add("2000-01-01 00:00:00"); + expectedValues.add("1900-01-01 12:13:14"); + expectedValues.add("2000-02-29 02:00:00"); + expectedValues.add("2004-02-29 03:00:00"); + expectedValues.add("2018-12-31 23:59:59"); + expectedValues.add("2015-11-15 10:00:00"); + expectedValues.add("2015-11-15 10:00:00"); + expectedValues.add("2015-11-15 10:00:00"); + + List timezones = new ArrayList<>(); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getDefault()); + timezones.add(TimeZone.getTimeZone("UTC")); + timezones.add(TimeZone.getTimeZone("CET")); + timezones.add(TimeZone.getTimeZone("PST")); + + List testTimestamps = new ArrayList<>(); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(0))); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(1))); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(2))); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(3))); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(4))); + testTimestamps.add(Timestamp.valueOf(expectedValues.get(5))); + + // Cloud Spanner does not store any timezone information, but does store the timestamp in UTC + // format. + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.clear(); + cal.set(2015, 10, 15); + testTimestamps.add(new Timestamp(cal.getTimeInMillis())); + + cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); + cal.clear(); + cal.set(2015, 10, 15); + testTimestamps.add(new Timestamp(cal.getTimeInMillis())); + + cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); + cal.clear(); + cal.set(2015, 10, 15); + testTimestamps.add(new Timestamp(cal.getTimeInMillis())); + + List calendars = new ArrayList<>(); + calendars.add(null); + calendars.add(Calendar.getInstance()); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("CET"))); + calendars.add(Calendar.getInstance(TimeZone.getTimeZone("PST"))); + + try (Connection connection = createConnection()) { + for (Calendar testCalendar : calendars) { + for (Timestamp testTimestamp : testTimestamps) { + try (PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);")) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + ps.setLong(1, 100); + ps.setLong(2, 19); + ps.setDate(3, new Date(System.currentTimeMillis())); + // Cloud Spanner will store the timestamp in UTC and no other timezone information. + ps.setTimestamp(4, testTimestamp); + ps.setTimestamp(5, testTimestamp, testCalendar); + ps.setArray(6, connection.createArrayOf("INT64", new Long[] {})); + ps.executeUpdate(); + } + + try (PreparedStatement ps = + connection.prepareStatement( + "SELECT * FROM Concerts WHERE VenueId=? AND SingerId=?")) { + ps.setLong(1, 100L); + ps.setLong(2, 19L); + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + + // First test the timestamp that was sent to Spanner using the default timezone. + // Get the timestamp in the default timezone. + Timestamp inDefaultTZ = rs.getTimestamp(4); + assertThat(inDefaultTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + // Then get it in the test timezone. + if (testCalendar != null) { + Timestamp inOtherTZ = rs.getTimestamp(4, testCalendar); + assertThat( + inOtherTZ.getTime(), + is( + equalTo( + testTimestamp.getTime() + testCalendar.getTimeZone().getRawOffset()))); + } + + // Then test the timestamp that was sent to Spanner using a specific timezone. + // Get the timestamp in the default timezone. + inDefaultTZ = rs.getTimestamp(5); + if (testCalendar == null) { + assertThat(inDefaultTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + } else { + assertThat( + inDefaultTZ.getTime(), + is( + equalTo( + testTimestamp.getTime() - testCalendar.getTimeZone().getRawOffset()))); + } + // Then get it in the test timezone. + if (testCalendar != null) { + Timestamp inOtherTZ = rs.getTimestamp(5, testCalendar); + assertThat(inOtherTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + } + } + } + connection + .createStatement() + .execute("DELETE FROM Concerts WHERE VenueId=100 AND SingerId=19"); + } + } + } + } + + @Test + public void test05_BatchUpdates() throws SQLException { + for (boolean autocommit : new boolean[] {true, false}) { + try (Connection con1 = createConnection(); + Connection con2 = createConnection()) { + con1.setAutoCommit(autocommit); + int[] updateCounts; + String[] params = new String[] {"A%", "B%", "C%"}; + try (PreparedStatement ps = + con1.prepareStatement("UPDATE Singers SET FirstName=LastName WHERE LastName LIKE ?")) { + for (String param : params) { + ps.setString(1, param); + ps.addBatch(); + } + updateCounts = ps.executeBatch(); + } + assertThat(updateCounts.length, is(equalTo(params.length))); + long totalUpdated = 0; + try (PreparedStatement ps = + con1.prepareStatement("SELECT COUNT(*) FROM Singers WHERE LastName LIKE ?")) { + for (int i = 0; i < updateCounts.length; i++) { + ps.setString(1, params[i]); + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + assertThat(updateCounts[i], is(equalTo(rs.getInt(1)))); + totalUpdated += updateCounts[i]; + } + } + } + // Check whether the updated values are readable on the second connection. + try (ResultSet rs = + con2.createStatement() + .executeQuery("SELECT COUNT(*) FROM Singers WHERE FirstName=LastName")) { + assertThat(rs.next(), is(true)); + if (autocommit) { + assertThat(rs.getLong(1), is(equalTo(totalUpdated))); + } else { + assertThat(rs.getLong(1), is(equalTo(0L))); + } + } + // If not in autocommit mode --> commit and verify. + if (!autocommit) { + con1.commit(); + try (ResultSet rs = + con2.createStatement() + .executeQuery("SELECT COUNT(*) FROM Singers WHERE FirstName=LastName")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(totalUpdated))); + } + } + // Set first names to null for the updated records for the next test run. + assertThat( + con2.createStatement() + .executeUpdate("UPDATE Singers SET FirstName=null WHERE FirstName=LastName"), + is(equalTo((int) totalUpdated))); + } + } + } + + @Test + public void test06_BatchUpdatesWithException() throws SQLException { + for (boolean autocommit : new boolean[] {true, false}) { + try (Connection con1 = createConnection(); + Connection con2 = createConnection()) { + con1.setAutoCommit(autocommit); + String[] params = new String[] {"A%", "B%", "C%", "D%"}; + // Statement number three will fail because the value is too long for the column. + int[] updateValues = new int[] {1, 1, 1024, 1}; + try (PreparedStatement ps = + con1.prepareStatement("UPDATE Singers SET FirstName=? WHERE LastName LIKE ?")) { + for (int i = 0; i < params.length; i++) { + ps.setString(1, Strings.repeat("not too long", updateValues[i])); + ps.setString(2, params[i]); + ps.addBatch(); + } + ps.executeBatch(); + fail("missing expected BatchUpdateException"); + } catch (BatchUpdateException e) { + assertThat(e.getUpdateCounts().length, is(equalTo(2))); + } + // If not in autocommit mode --> rollback before the next run. + if (!autocommit) { + con1.rollback(); + } + // Set first names to null for the updated records for the next test run. + try (PreparedStatement ps = + con2.prepareStatement("UPDATE Singers SET FirstName=null WHERE FirstName=?")) { + ps.setString(1, "not too long"); + } + } + } + } + + @Test + public void test07_StatementBatchUpdateWithException() throws SQLException { + try (Connection con = createConnection()) { + // The following statements will fail because the value is too long. + try (Statement statement = con.createStatement()) { + statement.addBatch( + String.format( + "UPDATE Singers SET FirstName='%s' WHERE LastName LIKE 'A%%'", + Strings.repeat("too long", 1024))); + statement.addBatch( + String.format( + "UPDATE Singers SET FirstName='%s' WHERE LastName LIKE 'B%%'", + Strings.repeat("too long", 1024))); + statement.executeBatch(); + fail("missing expected BatchUpdateException"); + } catch (BatchUpdateException e) { + assertThat(e.getUpdateCounts(), is(notNullValue())); + } + // The following statements will fail because the table does not exist. + try (Statement statement = con.createStatement()) { + statement.addBatch( + String.format( + "UPDATE Non_Existent_Table SET FirstName='%s' WHERE LastName LIKE 'A%%'", + Strings.repeat("too long", 1024))); + statement.addBatch( + String.format( + "UPDATE Non_Existent_Table SET FirstName='%s' WHERE LastName LIKE 'B%%'", + Strings.repeat("too long", 1024))); + statement.executeBatch(); + fail(); + } catch (BatchUpdateException e) { + assertThat(e.getUpdateCounts(), is(notNullValue())); + } + // The following statements will fail because the primary key values conflict. + try (Statement statement = con.createStatement()) { + statement.addBatch( + "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (9999, 'Test', 'Test', NULL, NULL)"); + statement.addBatch( + "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (9999, 'Test', 'Test', NULL, NULL)"); + statement.executeBatch(); + fail(); + } catch (BatchUpdateException e) { + assertThat(e.getUpdateCounts(), is(notNullValue())); + } + } + } + + private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) + throws SQLException { + assertThat(pmd.getParameterCount(), is(equalTo(expectedParamCount))); + for (int param = 1; param <= expectedParamCount; param++) { + assertThat(pmd.getParameterType(param), is(equalTo(Types.OTHER))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("OTHER"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(nullValue())); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + } + + private List readValuesFromFile(String filename) { + File file = new File(getClass().getResource(filename).getFile()); + StringBuilder builder = new StringBuilder(); + try (Scanner scanner = new Scanner(file)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + builder.append(line).append("\n"); + } + scanner.close(); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + String[] array = builder.toString().split(";"); + List res = new ArrayList<>(array.length); + for (String statement : array) { + if (statement != null && statement.trim().length() > 0) { + // strip the ( and ) + res.add(statement.trim().substring(1, statement.trim().length() - 1)); + } + } + return res; + } + + private void assertInsertSingerParameterMetadata(ParameterMetaData pmd) throws SQLException { + assertThat(pmd.getParameterCount(), is(equalTo(5))); + assertByteParam(pmd, 1); + assertStringParam(pmd, 2); + assertStringParam(pmd, 3); + assertBytesParam(pmd, 4); + assertDateParam(pmd, 5); + } + + private void assertInsertAlbumParameterMetadata(ParameterMetaData pmd) throws SQLException { + assertThat(pmd.getParameterCount(), is(equalTo(4))); + assertLongParam(pmd, 1); + assertLongParam(pmd, 2); + assertStringParam(pmd, 3); + assertLongParam(pmd, 4); + } + + private void assertInsertSongParameterMetadata(ParameterMetaData pmd) throws SQLException { + assertThat(pmd.getParameterCount(), is(equalTo(6))); + assertByteParam(pmd, 1); + assertIntParam(pmd, 2); + assertShortParam(pmd, 3); + assertNStringParam(pmd, 4); + assertLongParam(pmd, 5); + assertStringReaderParam(pmd, 6); + } + + private void assertInsertConcertParameterMetadata(ParameterMetaData pmd) throws SQLException { + assertThat(pmd.getParameterCount(), is(equalTo(6))); + assertLongParam(pmd, 1); + assertLongParam(pmd, 2); + assertDateParam(pmd, 3); + assertTimestampParam(pmd, 4); + assertTimestampParam(pmd, 5); + assertLongArrayParam(pmd, 6); + } + + private void assertLongParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.BIGINT))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Long.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(true)); + } + + private void assertIntParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.INTEGER))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Integer.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(true)); + } + + private void assertShortParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.SMALLINT))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Short.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(true)); + } + + private void assertByteParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.TINYINT))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Byte.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(true)); + } + + private void assertStringParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(String.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertNStringParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(String.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertStringReaderParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(StringReader.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertBytesParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.BINARY))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("BYTES"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(byte[].class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertDateParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.DATE))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("DATE"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Date.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertTimestampParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.TIMESTAMP))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("TIMESTAMP"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat(pmd.getParameterClassName(param), is(equalTo(Timestamp.class.getName()))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } + + private void assertLongArrayParam(ParameterMetaData pmd, int param) throws SQLException { + assertThat(pmd.getParameterType(param), is(equalTo(Types.ARRAY))); + assertThat(pmd.getParameterTypeName(param), is(equalTo("ARRAY"))); + assertThat(pmd.getPrecision(param), is(equalTo(0))); + assertThat(pmd.getScale(param), is(equalTo(0))); + assertThat( + pmd.getParameterClassName(param), is(equalTo("com.google.cloud.spanner.jdbc.JdbcArray"))); + assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); + assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); + assertThat(pmd.isSigned(param), is(false)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java new file mode 100644 index 000000000000..4a71bfd5c358 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test executing simple statements through JDBC. */ +@RunWith(JUnit4.class) +@Category(IntegrationTest.class) +public class ITJdbcSimpleStatementsTest extends ITAbstractJdbcTest { + @Rule public final ExpectedException expected = ExpectedException.none(); + + @Test + public void testSelect1() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = connection.createStatement().executeQuery("select 1")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(1))); + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testSelect1PreparedStatement() throws SQLException { + try (Connection connection = createConnection()) { + try (PreparedStatement ps = connection.prepareStatement("select 1")) { + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(1))); + assertThat(rs.next(), is(false)); + } + } + } + } + + @Test + public void testPreparedStatement() throws SQLException { + String sql = + "select * from (select 1 as number union all select 2 union all select 3) numbers where number=?"; + try (Connection connection = createConnection()) { + try (PreparedStatement ps = connection.prepareStatement(sql)) { + for (int i = 1; i <= 3; i++) { + ps.setInt(1, i); + try (ResultSet rs = ps.executeQuery()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getInt(1), is(equalTo(i))); + assertThat(rs.next(), is(false)); + } + } + } + } + } + + @Test + public void testBatchedDdlStatements() throws SQLException { + // Execute a successful batch of DDL statements. + try (Connection connection = createConnection()) { + try (Statement statement = connection.createStatement()) { + statement.addBatch( + "CREATE TABLE FOO1 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID)"); + statement.addBatch( + "CREATE TABLE FOO2 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID)"); + int[] updateCounts = statement.executeBatch(); + assertThat( + updateCounts, + is(equalTo(new int[] {Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO}))); + } + try (ResultSet rs = + connection + .createStatement() + .executeQuery( + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='' AND TABLE_NAME LIKE 'FOO%'")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(2L))); + } + } + // Execute a batch of DDL statements that contains a statement that will fail. + try (Connection connection = createConnection()) { + // First create a couple of test records that will cause the index creation to fail. + try (Statement statement = connection.createStatement()) { + statement.executeUpdate("INSERT INTO FOO1 (ID, NAME) VALUES (1,'TEST')"); + statement.executeUpdate("INSERT INTO FOO1 (ID, NAME) VALUES (2,'TEST')"); + } + boolean gotExpectedException = false; + try (Statement statement = connection.createStatement()) { + statement.addBatch( + "CREATE TABLE FOO3 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID)"); + statement.addBatch("CREATE UNIQUE INDEX IDX_FOO1_UNIQUE ON FOO1 (NAME)"); + statement.executeBatch(); + } catch (SQLException e) { + gotExpectedException = true; + } + assertThat(gotExpectedException, is(true)); + // The table should have been created, the index should not. + try (ResultSet rs = + connection + .createStatement() + .executeQuery( + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='' AND TABLE_NAME LIKE 'FOO%'")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(3L))); + } + try (ResultSet rs = + connection + .createStatement() + .executeQuery( + "SELECT COUNT(*) FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_SCHEMA='' AND INDEX_NAME='IDX_FOO1_UNIQUE'")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(0L))); + } + } + } + + @Test + public void testAddBatchWhenAlreadyInBatch() throws SQLException { + expected.expect(SQLException.class); + expected.expectMessage( + "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection."); + try (Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DML"); + connection.createStatement().addBatch("INSERT INTO Singers (SingerId) VALUES (-1)"); + } + } +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt new file mode 100644 index 000000000000..0cf7eafedf85 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt @@ -0,0 +1,60 @@ +(1,1,"Album 1",980045); +(2,2,"Album 2",667788); +(3,3,"Album 3",908791); +(4,4,"Album 4",690335); +(5,5,"Album 5",133041); +(6,6,"Album 6",505292); +(7,7,"Album 7",91969); +(8,8,"Album 8",289965); +(9,9,"Album 9",78176); +(10,10,"Album 10",485664); +(11,11,"Album 11",972680); +(12,12,"Album 12",893680); +(13,13,"Album 13",892138); +(14,14,"Album 14",449562); +(15,15,"Album 15",150968); +(16,16,"Album 16",580377); +(17,17,"Album 17",763081); +(18,18,"Album 18",203427); +(19,19,"Album 19",995368); +(20,20,"Album 20",29900); +(21,21,"Album 21",723728); +(22,22,"Album 22",540582); +(23,23,"Album 23",784245); +(24,24,"Album 24",614788); +(25,25,"Album 25",275649); +(26,26,"Album 26",970898); +(27,27,"Album 27",409289); +(28,28,"Album 28",766560); +(29,29,"Album 29",32414); +(30,30,"Album 30",457957); +(1,31,"Album 31",52546); +(2,32,"Album 32",412424); +(3,33,"Album 33",568496); +(4,34,"Album 34",353491); +(5,35,"Album 35",489951); +(6,36,"Album 36",75938); +(7,37,"Album 37",460461); +(8,38,"Album 38",642042); +(9,39,"Album 39",282872); +(10,40,"Album 40",521496); +(11,41,"Album 41",98126); +(12,42,"Album 42",535113); +(13,43,"Album 43",957625); +(14,44,"Album 44",667630); +(15,45,"Album 45",236968); +(16,46,"Album 46",445647); +(17,47,"Album 47",446396); +(18,48,"Album 48",852859); +(19,49,"Album 49",404105); +(20,50,"Album 50",384439); +(21,51,"Album 51",440468); +(22,52,"Album 52",455384); +(23,53,"Album 53",210756); +(24,54,"Album 54",849113); +(25,55,"Album 55",63969); +(26,56,"Album 56",277122); +(27,57,"Album 57",350063); +(28,58,"Album 58",359473); +(29,59,"Album 59",209825); +(30,60,"Album 60",84543); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt new file mode 100644 index 000000000000..2e53d92ccafc --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt @@ -0,0 +1,100 @@ +(1,1,DATE '2003-06-19',TIMESTAMP '2003-06-19T12:30:05Z',TIMESTAMP '2003-06-19T18:57:15Z',[11,93,140,923]); +(2,18,DATE '2004-01-25',TIMESTAMP '2004-01-25T14:58:28Z',TIMESTAMP '2004-01-26T01:10:52Z',[18,51,101,812]); +(3,21,DATE '2005-03-15',TIMESTAMP '2005-03-15T18:14:50Z',TIMESTAMP '2005-03-16T02:21:28Z',[23,26,107,721]); +(4,16,DATE '2009-05-09',TIMESTAMP '2009-05-09T05:22:34Z',TIMESTAMP '2009-05-09T15:28:28Z',[18,70,150,297]); +(5,11,DATE '2001-01-07',TIMESTAMP '2001-01-07T18:37:33Z',TIMESTAMP '2001-01-07T21:22:17Z',[20,55,185,672]); +(6,25,DATE '2015-11-19',TIMESTAMP '2015-11-19T22:47:42Z',TIMESTAMP '2015-11-20T02:54:01Z',[12,73,150,833]); +(7,26,DATE '2012-10-06',TIMESTAMP '2012-10-06T10:58:43Z',TIMESTAMP '2012-10-06T15:35:40Z',[8,83,199,625]); +(8,8,DATE '2001-09-26',TIMESTAMP '2001-09-26T06:41:20Z',TIMESTAMP '2001-09-26T16:38:35Z',[19,87,192,912]); +(9,27,DATE '2016-11-24',TIMESTAMP '2016-11-24T20:00:48Z',TIMESTAMP '2016-11-24T23:03:07Z',[20,84,134,885]); +(10,30,DATE '2017-05-05',TIMESTAMP '2017-05-05T12:44:05Z',TIMESTAMP '2017-05-05T23:06:55Z',[17,44,177,997]); +(11,7,DATE '2018-06-07',TIMESTAMP '2018-06-07T07:03:11Z',TIMESTAMP '2018-06-07T08:21:41Z',[10,73,182,287]); +(12,22,DATE '2009-01-07',TIMESTAMP '2009-01-07T23:22:11Z',TIMESTAMP '2009-01-08T08:34:18Z',[22,59,150,983]); +(13,16,DATE '2013-06-28',TIMESTAMP '2013-06-28T14:59:25Z',TIMESTAMP '2013-06-28T22:32:11Z',[17,41,129,433]); +(14,11,DATE '2005-08-19',TIMESTAMP '2005-08-19T01:11:28Z',TIMESTAMP '2005-08-19T01:30:30Z',[18,49,110,590]); +(15,18,DATE '2001-11-26',TIMESTAMP '2001-11-26T15:55:31Z',TIMESTAMP '2001-11-26T20:52:13Z',[18,51,132,854]); +(16,26,DATE '2009-01-04',TIMESTAMP '2009-01-04T03:09:11Z',TIMESTAMP '2009-01-04T12:02:14Z',[5,37,146,344]); +(17,20,DATE '2012-09-28',TIMESTAMP '2012-09-28T00:45:00Z',TIMESTAMP '2012-09-28T02:10:39Z',[15,89,185,480]); +(18,24,DATE '2004-09-06',TIMESTAMP '2004-09-06T09:55:40Z',TIMESTAMP '2004-09-06T18:10:32Z',[23,51,113,244]); +(19,21,DATE '2010-11-18',TIMESTAMP '2010-11-18T09:59:17Z',TIMESTAMP '2010-11-18T17:13:12Z',[14,69,164,218]); +(20,29,DATE '2010-12-24',TIMESTAMP '2010-12-24T04:21:25Z',TIMESTAMP '2010-12-24T06:10:08Z',[20,34,166,573]); +(21,3,DATE '2000-05-14',TIMESTAMP '2000-05-14T13:49:08Z',TIMESTAMP '2000-05-14T14:39:25Z',[21,67,136,779]); +(22,18,DATE '2000-05-14',TIMESTAMP '2000-05-14T00:23:23Z',TIMESTAMP '2000-05-14T01:20:04Z',[21,91,111,749]); +(23,26,DATE '2015-05-04',TIMESTAMP '2015-05-04T10:39:46Z',TIMESTAMP '2015-05-04T19:21:45Z',[24,91,128,559]); +(24,16,DATE '2012-08-18',TIMESTAMP '2012-08-18T08:47:12Z',TIMESTAMP '2012-08-18T09:35:03Z',[19,44,136,281]); +(25,4,DATE '2000-03-16',TIMESTAMP '2000-03-16T10:15:15Z',TIMESTAMP '2000-03-16T12:29:53Z',[22,28,111,948]); +(26,4,DATE '2002-11-20',TIMESTAMP '2002-11-20T16:28:19Z',TIMESTAMP '2002-11-20T17:56:10Z',[7,70,141,517]); +(27,23,DATE '2000-08-09',TIMESTAMP '2000-08-09T04:30:51Z',TIMESTAMP '2000-08-09T15:27:15Z',[13,98,156,230]); +(28,16,DATE '2000-10-15',TIMESTAMP '2000-10-15T04:12:39Z',TIMESTAMP '2000-10-15T14:07:05Z',[8,39,160,455]); +(29,22,DATE '2003-03-25',TIMESTAMP '2003-03-25T17:21:56Z',TIMESTAMP '2003-03-25T19:18:25Z',[17,70,148,681]); +(30,15,DATE '2008-11-11',TIMESTAMP '2008-11-11T22:56:07Z',TIMESTAMP '2008-11-12T09:33:48Z',[24,47,175,901]); +(31,7,DATE '2018-05-22',TIMESTAMP '2018-05-22T20:54:59Z',TIMESTAMP '2018-05-23T02:52:28Z',[13,34,177,804]); +(32,30,DATE '2000-04-03',TIMESTAMP '2000-04-03T13:54:10Z',TIMESTAMP '2000-04-03T15:57:02Z',[16,48,137,249]); +(33,23,DATE '2003-12-24',TIMESTAMP '2003-12-24T22:22:00Z',TIMESTAMP '2003-12-25T06:09:40Z',[15,36,131,922]); +(34,12,DATE '2012-06-23',TIMESTAMP '2012-06-23T18:15:30Z',TIMESTAMP '2012-06-24T03:46:17Z',[25,31,160,564]); +(35,5,DATE '2017-12-15',TIMESTAMP '2017-12-15T09:43:38Z',TIMESTAMP '2017-12-15T17:18:28Z',[22,31,177,868]); +(36,20,DATE '2012-12-21',TIMESTAMP '2012-12-21T08:28:14Z',TIMESTAMP '2012-12-21T11:34:59Z',[25,62,143,437]); +(37,19,DATE '2014-07-07',TIMESTAMP '2014-07-07T22:01:35Z',TIMESTAMP '2014-07-08T04:39:37Z',[8,31,184,784]); +(38,15,DATE '2012-07-26',TIMESTAMP '2012-07-26T09:45:35Z',TIMESTAMP '2012-07-26T13:03:53Z',[19,79,140,908]); +(39,24,DATE '2014-03-19',TIMESTAMP '2014-03-19T07:52:25Z',TIMESTAMP '2014-03-19T11:47:01Z',[11,90,141,978]); +(40,4,DATE '2015-08-26',TIMESTAMP '2015-08-26T20:51:25Z',TIMESTAMP '2015-08-27T07:06:46Z',[15,94,195,510]); +(41,24,DATE '2016-04-11',TIMESTAMP '2016-04-11T08:59:07Z',TIMESTAMP '2016-04-11T13:23:30Z',[15,51,173,233]); +(42,18,DATE '2005-03-19',TIMESTAMP '2005-03-19T15:45:04Z',TIMESTAMP '2005-03-19T16:28:42Z',[19,31,188,546]); +(43,7,DATE '2001-01-04',TIMESTAMP '2001-01-04T11:02:16Z',TIMESTAMP '2001-01-04T11:32:21Z',[20,37,133,958]); +(44,5,DATE '2015-12-24',TIMESTAMP '2015-12-24T06:49:48Z',TIMESTAMP '2015-12-24T14:46:46Z',[12,61,175,233]); +(45,12,DATE '2011-08-24',TIMESTAMP '2011-08-24T03:45:46Z',TIMESTAMP '2011-08-24T06:13:10Z',[18,38,169,913]); +(46,16,DATE '2017-03-04',TIMESTAMP '2017-03-04T04:01:04Z',TIMESTAMP '2017-03-04T13:44:38Z',[21,79,119,839]); +(47,18,DATE '2009-05-19',TIMESTAMP '2009-05-19T23:10:52Z',TIMESTAMP '2009-05-20T04:02:01Z',[25,79,151,357]); +(48,22,DATE '2003-10-03',TIMESTAMP '2003-10-03T14:10:24Z',TIMESTAMP '2003-10-03T17:35:09Z',[18,60,140,450]); +(49,9,DATE '2003-03-07',TIMESTAMP '2003-03-07T22:09:59Z',TIMESTAMP '2003-03-08T08:28:29Z',[22,41,122,726]); +(50,9,DATE '2015-07-12',TIMESTAMP '2015-07-12T07:43:51Z',TIMESTAMP '2015-07-12T12:45:20Z',[18,67,126,474]); +(51,12,DATE '2014-11-05',TIMESTAMP '2014-11-05T19:03:00Z',TIMESTAMP '2014-11-06T05:27:07Z',[19,43,125,865]); +(52,6,DATE '2016-07-25',TIMESTAMP '2016-07-25T14:39:28Z',TIMESTAMP '2016-07-26T00:36:03Z',[6,74,192,344]); +(53,13,DATE '2005-08-02',TIMESTAMP '2005-08-02T16:06:47Z',TIMESTAMP '2005-08-02T17:13:41Z',[5,52,192,977]); +(54,18,DATE '2010-01-25',TIMESTAMP '2010-01-25T07:34:54Z',TIMESTAMP '2010-01-25T16:29:11Z',[24,85,181,304]); +(55,14,DATE '2012-05-20',TIMESTAMP '2012-05-20T13:15:12Z',TIMESTAMP '2012-05-20T17:40:09Z',[15,43,104,665]); +(56,3,DATE '2013-09-08',TIMESTAMP '2013-09-08T19:53:42Z',TIMESTAMP '2013-09-08T22:32:52Z',[14,81,129,354]); +(57,27,DATE '2003-07-18',TIMESTAMP '2003-07-18T23:11:24Z',TIMESTAMP '2003-07-19T03:29:46Z',[21,85,188,854]); +(58,27,DATE '2001-04-10',TIMESTAMP '2001-04-10T08:36:49Z',TIMESTAMP '2001-04-10T16:17:57Z',[17,86,161,438]); +(59,2,DATE '2002-07-02',TIMESTAMP '2002-07-02T17:32:20Z',TIMESTAMP '2002-07-03T01:59:33Z',[23,59,164,357]); +(60,28,DATE '2000-11-24',TIMESTAMP '2000-11-24T12:53:25Z',TIMESTAMP '2000-11-24T22:37:53Z',[22,47,161,739]); +(61,12,DATE '2017-07-04',TIMESTAMP '2017-07-04T21:02:01Z',TIMESTAMP '2017-07-05T03:57:29Z',[16,88,179,478]); +(62,3,DATE '2015-10-07',TIMESTAMP '2015-10-07T17:58:42Z',TIMESTAMP '2015-10-07T21:04:38Z',[21,44,155,381]); +(63,23,DATE '2005-05-03',TIMESTAMP '2005-05-03T15:08:10Z',TIMESTAMP '2005-05-03T20:58:30Z',[20,43,111,824]); +(64,24,DATE '2012-12-09',TIMESTAMP '2012-12-09T02:52:09Z',TIMESTAMP '2012-12-09T08:01:11Z',[18,87,106,997]); +(65,30,DATE '2004-03-01',TIMESTAMP '2004-03-01T07:09:06Z',TIMESTAMP '2004-03-01T07:49:32Z',[14,26,195,895]); +(66,24,DATE '2007-05-19',TIMESTAMP '2007-05-19T10:20:57Z',TIMESTAMP '2007-05-19T15:21:09Z',[18,54,179,238]); +(67,16,DATE '2016-01-06',TIMESTAMP '2016-01-06T21:32:20Z',TIMESTAMP '2016-01-07T02:31:32Z',[20,61,120,652]); +(68,2,DATE '2007-10-26',TIMESTAMP '2007-10-26T03:37:22Z',TIMESTAMP '2007-10-26T10:02:36Z',[11,65,151,537]); +(69,2,DATE '2018-08-11',TIMESTAMP '2018-08-11T01:33:38Z',TIMESTAMP '2018-08-11T07:39:21Z',[10,98,105,621]); +(70,23,DATE '2012-07-06',TIMESTAMP '2012-07-06T01:02:23Z',TIMESTAMP '2012-07-06T05:04:16Z',[14,44,172,953]); +(71,7,DATE '2006-01-24',TIMESTAMP '2006-01-24T15:32:10Z',TIMESTAMP '2006-01-24T17:40:43Z',[9,58,150,713]); +(72,8,DATE '2002-11-06',TIMESTAMP '2002-11-06T05:58:03Z',TIMESTAMP '2002-11-06T07:43:24Z',[25,36,193,213]); +(73,10,DATE '2003-11-24',TIMESTAMP '2003-11-24T17:39:10Z',TIMESTAMP '2003-11-25T03:17:36Z',[8,55,200,352]); +(74,16,DATE '2007-11-03',TIMESTAMP '2007-11-03T05:49:12Z',TIMESTAMP '2007-11-03T16:34:16Z',[21,50,114,820]); +(75,4,DATE '2009-05-06',TIMESTAMP '2009-05-06T18:52:07Z',TIMESTAMP '2009-05-06T21:10:02Z',[16,42,101,281]); +(76,1,DATE '2012-12-03',TIMESTAMP '2012-12-03T06:01:05Z',TIMESTAMP '2012-12-03T06:45:00Z',[24,60,140,292]); +(77,1,DATE '2016-11-26',TIMESTAMP '2016-11-26T01:19:27Z',TIMESTAMP '2016-11-26T07:20:17Z',[19,31,123,214]); +(78,9,DATE '2018-05-21',TIMESTAMP '2018-05-21T00:14:43Z',TIMESTAMP '2018-05-21T08:43:35Z',[7,28,115,634]); +(79,14,DATE '2013-11-20',TIMESTAMP '2013-11-20T08:54:47Z',TIMESTAMP '2013-11-20T10:44:54Z',[18,39,155,328]); +(80,17,DATE '2015-10-11',TIMESTAMP '2015-10-11T23:41:17Z',TIMESTAMP '2015-10-12T02:42:48Z',[16,94,102,894]); +(81,23,DATE '2011-08-07',TIMESTAMP '2011-08-07T19:33:01Z',TIMESTAMP '2011-08-07T21:51:53Z',[23,90,134,370]); +(82,7,DATE '2010-04-10',TIMESTAMP '2010-04-10T13:22:08Z',TIMESTAMP '2010-04-10T17:59:08Z',[18,68,121,303]); +(83,27,DATE '2001-07-08',TIMESTAMP '2001-07-08T20:19:54Z',TIMESTAMP '2001-07-08T22:46:15Z',[18,86,148,746]); +(84,6,DATE '2017-09-02',TIMESTAMP '2017-09-02T10:29:03Z',TIMESTAMP '2017-09-02T13:06:41Z',[12,85,138,471]); +(85,1,DATE '2013-11-02',TIMESTAMP '2013-11-02T04:01:03Z',TIMESTAMP '2013-11-02T14:08:47Z',[9,65,111,583]); +(86,22,DATE '2004-04-03',TIMESTAMP '2004-04-03T19:13:48Z',TIMESTAMP '2004-04-04T05:59:31Z',[19,72,105,908]); +(87,2,DATE '2012-02-26',TIMESTAMP '2012-02-26T22:52:21Z',TIMESTAMP '2012-02-27T02:55:24Z',[16,75,129,740]); +(88,9,DATE '2017-09-17',TIMESTAMP '2017-09-17T11:28:49Z',TIMESTAMP '2017-09-17T12:13:03Z',[24,77,182,755]); +(89,11,DATE '2011-03-28',TIMESTAMP '2011-03-28T13:05:23Z',TIMESTAMP '2011-03-28T16:32:29Z',[22,96,174,731]); +(90,21,DATE '2006-12-12',TIMESTAMP '2006-12-12T20:44:10Z',TIMESTAMP '2006-12-12T22:10:34Z',[15,68,166,616]); +(91,27,DATE '2010-08-18',TIMESTAMP '2010-08-18T05:49:35Z',TIMESTAMP '2010-08-18T12:58:36Z',[12,84,157,369]); +(92,2,DATE '2003-02-03',TIMESTAMP '2003-02-03T11:19:43Z',TIMESTAMP '2003-02-03T22:10:42Z',[25,59,140,939]); +(93,5,DATE '2016-01-04',TIMESTAMP '2016-01-04T08:10:26Z',TIMESTAMP '2016-01-04T13:08:30Z',[5,90,163,272]); +(94,3,DATE '2018-04-20',TIMESTAMP '2018-04-20T07:19:52Z',TIMESTAMP '2018-04-20T17:41:01Z',[5,59,109,854]); +(95,19,DATE '2016-10-09',TIMESTAMP '2016-10-09T17:02:59Z',TIMESTAMP '2016-10-09T17:37:27Z',[6,35,176,442]); +(96,9,DATE '2007-06-12',TIMESTAMP '2007-06-12T16:50:12Z',TIMESTAMP '2007-06-12T19:27:30Z',[7,49,169,729]); +(97,29,DATE '2012-11-25',TIMESTAMP '2012-11-25T20:40:30Z',TIMESTAMP '2012-11-25T21:29:50Z',[12,35,128,269]); +(98,11,DATE '2013-10-22',TIMESTAMP '2013-10-22T03:26:36Z',TIMESTAMP '2013-10-22T06:42:42Z',[14,49,148,726]); +(99,10,DATE '2006-05-10',TIMESTAMP '2006-05-10T05:49:43Z',TIMESTAMP '2006-05-10T07:12:18Z',[5,67,131,360]); +(100,18,DATE '2015-02-15',TIMESTAMP '2015-02-15T01:18:05Z',TIMESTAMP '2015-02-15T04:19:27Z',[11,38,127,909]); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql new file mode 100644 index 000000000000..896b8b9cbf2e --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -0,0 +1,88 @@ +/* + * Copyright 2019 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. + */ + +START BATCH DDL; + +CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX), + BirthDate DATE +) PRIMARY KEY(SingerId); + +CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); + +CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX), + MarketingBudget INT64 +) PRIMARY KEY(SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE; + +CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); + +CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget); + +CREATE TABLE Songs ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + TrackId INT64 NOT NULL, + SongName STRING(MAX), + Duration INT64, + SongGenre STRING(25) +) PRIMARY KEY(SingerId, AlbumId, TrackId), + INTERLEAVE IN PARENT Albums ON DELETE CASCADE; + +CREATE UNIQUE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums; + +CREATE INDEX SongsBySongName ON Songs(SongName); + +CREATE TABLE Concerts ( + VenueId INT64 NOT NULL, + SingerId INT64 NOT NULL, + ConcertDate DATE NOT NULL, + BeginTime TIMESTAMP, + EndTime TIMESTAMP, + TicketPrices ARRAY +) PRIMARY KEY(VenueId, SingerId, ConcertDate); + +CREATE TABLE TableWithAllColumnTypes ( + ColInt64 INT64 NOT NULL, + ColFloat64 FLOAT64 NOT NULL, + ColBool BOOL NOT NULL, + ColString STRING(100) NOT NULL, + ColStringMax STRING(MAX) NOT NULL, + ColBytes BYTES(100) NOT NULL, + ColBytesMax BYTES(MAX) NOT NULL, + ColDate DATE NOT NULL, + ColTimestamp TIMESTAMP NOT NULL, + ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), + + ColInt64Array ARRAY, + ColFloat64Array ARRAY, + ColBoolArray ARRAY, + ColStringArray ARRAY, + ColStringMaxArray ARRAY, + ColBytesArray ARRAY, + ColBytesMaxArray ARRAY, + ColDateArray ARRAY, + ColTimestampArray ARRAY +) PRIMARY KEY (ColInt64) +; + +RUN BATCH; \ No newline at end of file diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt new file mode 100644 index 000000000000..939873de17e6 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt @@ -0,0 +1,30 @@ +(1,'First 1','A Last 1',FROM_BASE64('5KckBUgBLuj+nlmI0WXBEA0TCSeOK8x/B35kzIIHC01YrF8CNTjRT8hVQ4T0NkVGZjz96bF68aBu4QQ9VlZ/EhX22++vPADslt5YdqFzJjdxhlbGCufKIbrCVn1Po5u+j46SaV1TAHffIGfsAY0lhHJNmRS2P4p2/CGWJas4bzEo/Fn/JxuKF/et1LXgmlShOiE+LbnysvjbDt7GcbL7mA=='),DATE '1906-04-28'); +(2,'First 2','ALast 2',FROM_BASE64('1uLrsGLZS2BUfLGU0CLO9lgDau+TfX/XYK0RyEKvwgWdm3f0mbt4vbLziTn7iY/fM5OeGoeNZneQFWJoAY1XimD4aFDcQlIkkUxaXHFbOik4KNc/OiQMNaLghXtyaTP+UEaHX7o3w7iCp/wjzljEsnaYZxYTKY8Nm6JfKSwXvP1xHXi0KpaCdLf/V/8Vg102CNqqR4fgFwLy3/5QLxbGAg=='),DATE '1922-11-17'); +(3,'First 3','A Last 3',FROM_BASE64('Mc3i5IYbAWfrpZbCa8R2IXsK2DM0zW8mCx58tMClAPvIKktEIOh/HEl3l6qnJ8FPqp17E+PYZsplE9Hxu0LV9N1inR4TO+my3h9Vq72BA6hoSHmo2mxhRSF+iUL3TrC+MalcKPZuKnmI48RRfKoIrwP0Am1iqXWhhpOMo+zHDVL40FsbDIDW7zezTjyxPmwryF9I5vF+t1j8B5NKPA8Gnw=='),DATE '1935-11-08'); +(4,'First 4','A Last 4',FROM_BASE64('FyMiT7GA1pQzfrf/SnGN4iWMizOf+M59fVauKUqP84oGBSkI4F746K+grXinm3txsfPGu23J4OYtZt9FUxQssbaVykkhGBX9+nuiV+RYESLRj6uHT6mZH5g2BOR9L6cWRclks6GBFzIwjFu7JqeofmiJt/R1BwJMFH+07rDRPgi/9oS/DK6/ipC77dpomAuW48d9IbUNofd9/tc89mJbEg=='),DATE '1945-03-23'); +(5,'First 5','A Last 5',FROM_BASE64('BfpuifEdiau23UcEnnaONRxA9V0UH2uMhv3gZG/o0tnh6IR306luK4UL12RSbDVzGgpmDa7tLNC2pZzAlDMJmO4h5F73GzvSa8mVFrJrnqeNy9ECLM1sTIH1HYaF9jZXAYcSo14PK4+xygz1tsENs3jfKfWNuNBEi463x+fL8RcVxVMclSyOEBQaTnLD0pnzji99NkwMBQiwIHN5bl6XLA=='),DATE '1953-06-03'); +(6,'First 6','A Last 6',FROM_BASE64('Hdcj53Vc1yNAuCAP7H8YGadmbdOFGg1nfSpfVuiWWgx2OGR8KQIzTTHny8FsYnmyEBmJQZQMv1m1HU0EFmq5b4id0TmBUMfPzgWF5LFAJPgziAnbprYiKhwDaiRxrmL4Q0kVozeT1vniS3T6HioC20pjzmN8aF1vxzrLBr3IC9e8zHt9+Vla52lNoG/8atlWaSPx1agj5CyPncO7QTdPuw=='),DATE '1956-02-07'); +(7,'First 7','B Last 7',FROM_BASE64('FqOl3vAVSMU6NGINNZjVbYQRgmb95stb6CHfMYEec32ngI8XCS2687kGHfZ16innPuGau5Z/JSchkE8JYMaSITQ/7+B5eh40vZI1CKuLyXKfZ4BR8VkBVqxXyAsAShboxlt+kMHZEvWMY0iXcl9jCB3V+GNbPMHlCxz46CAnjp9ArnwwojRZgUDK9PonTr9N4GBEmO04DLip30LyvCpW/g=='),DATE '1969-05-26'); +(8,'First 8','B Last 8',FROM_BASE64('PQLBMSGGZXeSI7FLot4EcX3JfPTafiu5yeisMBQvuQmDW7kQC/mU9Oh+UhAbovDIx0dZGJ5dIhoAXZEzZPxGgBMWvbPNFmTB7+Q5Hd3/1uxL81XDZs6FlVCpGCKB0KER4WxtKbVqeQgltCeEvhYsTeLRNJdka33uq06lSZFyJXKX9bQyRLCZlGQRy2VHG1+sqjAX0FfcLf6RNEG64sDwOA=='),DATE '1978-11-08'); +(9,'First 9','B Last 9',FROM_BASE64('Nk2ZqJZSCFKKY+NMSq0WGVnNDS/BDHDEyb/bbJFxC/TqRPi+8DQ1csNlqvULW0pDEE6IygIRQR2lv5kT43E4tal4PKXx/z5LTeL9xiJ+qOHwLqAJrZK3V4aQFCNXT6t95lsxZLcjaP6fzNWlGwuN++iR7hpYJLI3WQSlaPL2GuHI9dLGS9ZUPR9KhDor72IURkOHU9Dt1eWfYouPsuVnrA=='),DATE '1987-07-04'); +(10,'First 10','B Last 10',FROM_BASE64('E0rzdg+IDhd1N9S/Nh11Yr6Za+xZlfCOQr0TrsxjFzRvO1ZnXjHGQPdWvT/LIJV+f7TXu0rYtk75fx7uPylxANNEYnLfD7v6UHB5Yful0TCweTFs9qH35BEd0jJl0ATb1ggUmsxXF0xZQpsRRnfycPbMY59w2APSX3hvgF2Xk7lvhHQaSbjnHOh4s78cqa2Atrjeds8KI/I4v+aVQIX9+Q=='),DATE '1993-07-06'); +(11,'First 11','C Last 11',FROM_BASE64('rO6MoGIcZJ+6zIPyMCt2td9ytNkSAn/LxWkrBKUGQs+Fk+Se43Ml7YsuRYhdcIeawAtySL35vZzb6Avl7bH/MyXrg4E0jdvjpEsi7KHiN4f0ky85purgyEg8tRASTi2zVsIM8c27DZenHOqRFl4KUaGRdQATOEoEIH3aHLVoACb0Y1m9JDTIDBcKST8nvTDzayQx1Ur4CO+ZqqG8ye99ww=='),DATE '1895-09-15'); +(12,'First 12','C Last 12',FROM_BASE64('ki4b0vB6EHp9qdm9lFrxplFPTnFCq9/BWwBLK1Jzz39K2q1rESpVXFIe2L2WzOKrunXo8e+p7+xlzBBKCwVIW6hQy0A+7kp7SwdZgWr2pXJqtSuo43fwfhf/A63zFaUYg3AkuNJNAtV/F3mOVudPeJ2xvfRfJ06uKY4MzsDhXAFW5Wsf1ypWMCke58U1VncvpuNOwzSb0El+hOreiQRX8g=='),DATE '1922-01-03'); +(13,'First 13','C Last 13',FROM_BASE64('KEx72v8CBibM16yet2U0Nsbt8KypF1ih18jLso5Q4AmFYUK7961GTYWj0YprWHxIxL/3qAXkm8jjtcRqEUmIXxW7kR0xC7sOcMYJsOSsy2m59YnDTlzDLlR1gynzNJVUhj+aKkUPMQfYV6Dw3UEx2Kik4NKDlGJQc9A0w3rfXjzRln8Ou3F+KYMuuoi/4jP4GEu1Pgyqy8jhQKiN0e9cjA=='),DATE '1930-08-03'); +(14,'First 14','C Last 14',FROM_BASE64('SdOTrssLh3vCqjtPNSqUvX5xrHs6/tpdlqgbp1jp9FseXhhJm+sq6FhgSMX+jm/grBUkUbGCNcWYthv3hdRMIapyZANENn/8CN0BxoVnvECGA9moThVIVghiSAiUNB+SyZg9XlmFRBaQcXpSWoZ1tIRTIuFRKpKaC2GYiOHVPLSQEUOBGc+sN4J0eCvM5aytanUGzn0o98yL73hbRXjwUw=='),DATE '1940-05-12'); +(15,'First 15','C Last 15',FROM_BASE64('NFgZNOzxoDSrAOPXtDIyUtetwm6eUN11YdjB7rIFfylx2SSTbhWZMuJoToE8xQz458BNaUJ8xPB+fJR2AQJL75eZdwJgSA7nnSiFcQgJxU7CEShlBT1ANNJvPujQ7cowRAo4joPfxoBSODuZcEc9WeXhJpEnlQtiGq7k+kzQ0oPgGaj0gLNwiC2zZwL5XCiet5qsRk4LSkUcX3OugpgeCg=='),DATE '1946-09-23'); +(16,'First 16','D Last 16',FROM_BASE64('mmXbRxEVEhiWeMGeuYOv6xGovovbq/qfevmWdMcGiqmCU1yzUrWKLvDhwzYZMbdscj7Tr5e4YyaXpIgpdMro3SApCyfhX5o/dsBlBNVmwLqg8DYbzAeApkaXeiStpAtKdQ8kZ1jezAFlhR/PioNsZjj1iAU4paFLG5F1i01spp3OOeJaD1mUTCSEO85rOAbQ8+B1N3vzz1Yc3E3mTQtxHg=='),DATE '1947-09-30'); +(17,'First 17','D Last 17',FROM_BASE64('zXIaISyrpPC/s0Yowmfdcbcavm6bGs95oBnWOHeTlXXk2n61Ug/GdG4gn5KxcXTfkqZAyzCBEnoaVcrwcp3HzEPUQeumXQn0dt2/oc5s0qfmGDo1+eOVy3tWMTdXv3vKmc4xXQ9bTMQE+MTtZDUknVCJ73zGUAMunFgzVnERLGBfOVaoLxcwC4HBrRtvtLlMboaCHirA1U5fF8xx81dK/g=='),DATE '1948-02-04'); +(18,'First 18','D Last 18',FROM_BASE64('mYZ5eW8+N/PFaDAmnIU77XX1jOZszdOXxblHbB0gKoJ6XOLYKcsmJKG8mjmUCQDYiG1b12xRQga6wprvLsciiyIwTCca6i4JL4RoVz+GqyDLmNSxHruz4xIB7XFIQ0q5SIeL7nob7llp7n+4+T9VYeoMDlFkG903WfjZNqsMRzpFYTT1C4ef+IlHOQSD5K3f/H/uWQ61PUebhSYe9hYQNg=='),DATE '1962-11-10'); +(19,'First 19','D Last 19',FROM_BASE64('/FqFHFjzF6yL/d3bKfSS9ZS1j8xkDlmF6gLpFf/MlC8idAt9ceLvr6oNEAKIdu0xqfLN9fKh9B7wQjAGUBKFLFlVzPIC2BBt7cCiiVVqgYwH3PIKiWL1LndLi1VRcNpy+gWLdgaFn+u4FxNotLDhdx9jUJOsDDPy9aBDSYmYOBajVUgN6jyfvG6egGnIhj+RNGxRkKfZ0isLOByT82v73w=='),DATE '1988-10-07'); +(20,'First 20','D Last 20',FROM_BASE64('3YII52xQjwk1RwhDPlbEKYWje92/04jIYhSJWa7LsLEt6qDxaFt1/1viQKAJWreCzgD0iC08CSJOQDLEmpuDPW5HZmWSnA0AuO46TGaYWtdQDFeJhgVzcldsAC7dMRid+SO1+sjvr/VfGCJP0XT3kWdE8mWNTdI74KrVm0CChj6XF7fLtjekbjZETrg7ySo8pmawVbTKrrZ5FIuNlkxI/Q=='),DATE '2000-02-29'); +(21,'First 21','D Last 21',FROM_BASE64('sKVHb3YTv4OPAB+77pjXln3omYqFy20LkBT/uP7PMSWlYaH+UpRdzOO52pDUh6BrMDjS3qgXU7irLoNA2NEma1QFzvVrLaa6yArnpZCyAEOw3OzpIQf2lJ7YqN8ZjwWEn8SztpMZBiJVXeZoYyYWnhkn9a+crIBOWMYI9ZfPUWk1xtvMX7I1QgHdSqPsLpT8iSnO42tjraGd5ulqkWrIRg=='),DATE '1886-08-09'); +(22,'First 22','E Last 22',FROM_BASE64('07GVEGBPEhQC8lELkxIGFhrQNspbl2NEGIrND5VXnUJFnuFctZaSpPovPHlYKtORcpGFsHTv3rSM6UUxTYFHzIUrxQJxNJ84KXjEXrlAN4tWkQOifh4icFc9FezQzQfsjf0KDjRatIFy8Q2jcSUfnhHbeZ1gpbsLIp8Ajioc7ptZG7Lnl1JyPmqKjQwQ+9WyE4uB0BGJTHI3xwzXQLm45A=='),DATE '1889-04-03'); +(23,'First 23','E Last 23',FROM_BASE64('tyGduCzcRQhWJXhDm5c9a8Mfpyyc1sKKk/OxSJFJ2numyNWuurKglMuDZSgdC9sH122eZdJU1uid7umiWYwhYYUC0JuYaYLNpYCnRuOL2FWVSN9jrJYX6AsNNpUDUfcKlJobFL/XJ+ulAr18Z/qtoWXDr4lx5TZAk05TTlFHJwRjIrybzrFYohhZZ20O4WtL3dryRKTgTgvVSElX0SZ8Tw=='),DATE '1892-01-21'); +(24,'First 24','E Last 24',FROM_BASE64('bXe6LecQB+BcWwzcE3b+JrH/20zrVIUXsH9AcBMduKoVIpCnrloUziiWbE1b2Te3/mD7ShKfD4RXSahJ7KgACA3CxS70yAa945NaqoX/aND7kGfFE6PEiS4pUrkJ10A1mRY2fP0J/Qn2tEyegtTF4b2BZuACQJy0qU8QyYrykaVK/+ExVI+MrvHA2LD062EDWPJrPgApCpPRMmtAV3KnTA=='),DATE '1898-02-21'); +(25,'First 25','Last 25',FROM_BASE64('82g7Ytc6/RBp/3vFxUG7JfAz9al82TRPlqBybWKBj/1pA26Pgv1UTxdDloQ24ovTmRZ3agPmaFEc/0ry820ozm8NmR340IwHRmO+jb2LQY4FGEMKFg7zDxAZpJXqITMZsFL1zO/EJ6VMnvZ90Udk2mywsnvv857PRCXJgx6vu4gn+oqUaRAQnSHq3pveu4/88FogqWoOotSzraD2RkW39Q=='),DATE '1911-12-15'); +(26,'First 26','Last 26',FROM_BASE64('KwbjBuHNQvzeWR2Ucf3v5dHAIO/b3/A0AlKxWI2qARDKuaXNuBooTCtdhIv5ZczOH5BbEKlaYkK3mr3GA5GClmwxsafbv3eE0LkV88T7KjfrKSkfatyTtcIWLIrw60B5hlMS5uxmj4X9nZfivj9boB4g3rqEdg/vgOsO9xdk/BKw6FMCuDO3PgDGEn89dOZmaB0PgadYNN3vqz8ZLgXWtg=='),DATE '1912-07-01'); +(27,'First 27','Last 27',FROM_BASE64('O3T43r6OjBwCWu925WlVnd6NLufFAken2Jk/QQBJOGQWsqc4dQsFhs/RSAC8iMZg32lfpfjMQPltRjmwqV7JleYRxL9e6co5WDj9cQk7AcL6wedgR5O/voPZIJ0aqkh5bZvijuxNIerbYhmYZEPOuzhgz9ayE7LgPkvO6WWNfhYuhnulnuDa3e2RsBNC7J1zuuf3DKHnL8SpaD0SMcZRuw=='),DATE '1939-05-17'); +(28,'First 28','Last 28',FROM_BASE64('xC71kYOpe6iZJd4DZnb11wBapa37lquOSW0JzuS15kW1xSG/Jxu0FXUIbFaBJ84hvFYQ3OSxr5HRxI0SBaFyUQhglUT3KTv/m8fEN/W+apBu4aUtlLcZPOTr1amaz30fu89J6pEoQOgmswSIr/0CtiaQ/ZHnuU2rZUXh7hTzBdygF30bAIq6yBGPpfb/MV66yagZtQO/q69sRmar70H/hg=='),DATE '1946-10-18'); +(29,'First 29','Last 29',FROM_BASE64('koHC6ZTUt89ksDORKlw5ep/zJCO0/LNo5A6yC5E8HEKOZpzX7xllDsIQuDmMQDn1HCHkpouKFmoTM24kWvfAs9B6yE7JccSFJbUU5s4Z/iLtYnnfKDzMEDDd/TyL6FxxS0McscfZ/TIc6ZFCArlJCbviqTSafPamrlD7tOJNxkCZae+dFIgnTCiTcwcjvkQeM5Ul6jDNoqIy5lrZdR6wJg=='),DATE '1956-12-23'); +(30,'First 30','Last 30',FROM_BASE64('WjdDzKHsiWCc0kXraf7NbebOU2TIv9KicHO6Og18iZpsxKH0am6wN7f1FwB1VSvZkvfJQgFkqjoqYEJ8qmgKB/YC9mbQAP14BjoJTq6fwDehF5leqSYT7NJarlhV7BX+hn4cCOBZ/gdGPCdK2aXZy8KJrnxh6RBGe0+84L3mEOaSZmZRvmXMcRjRozu17qV3xm6mo7BTq+/7tES3CAovMw=='),DATE '1988-05-29'); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt new file mode 100644 index 000000000000..bda929b0fe5f --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt @@ -0,0 +1,149 @@ +(12,42,1,"Song 12 42 1",387,'Unknown'); +(12,12,2,"Song 12 12 2",202,'Unknown'); +(29,59,3,"Song 29 59 3",160,'Unknown'); +(23,23,4,"Song 23 23 4",255,'Unknown'); +(24,54,5,"Song 24 54 5",436,'Unknown'); +(28,58,6,"Song 28 58 6",121,'Unknown'); +(27,27,7,"Song 27 27 7",319,'Unknown'); +(24,24,8,"Song 24 24 8",213,'Unknown'); +(19,49,9,"Song 19 49 9",280,'Unknown'); +(17,47,10,"Song 17 47 10",253,'Unknown'); +(6,6,11,"Song 6 6 11",321,'Unknown'); +(12,42,12,"Song 12 42 12 12 42 12",124,'Unknown'); +(25,25,13,"Song 25 25 13",449,'Unknown'); +(24,24,14,"Song 24 24 14",438,'Unknown'); +(5,5,15,"Song 5 5 15",378,'Unknown'); +(9,39,16,"Song 9 39 16",202,'Unknown'); +(20,50,17,"Song 20 50 17",452,'Unknown'); +(7,37,18,"Song 7 37 18",420,'Unknown'); +(8,8,19,"Song 8 8 19",318,'Unknown'); +(5,35,20,"Song 5 35 20",347,'Unknown'); +(3,3,21,"Song 3 3 21",377,'Unknown'); +(15,15,22,"Song 15 15 22",314,'Unknown'); +(19,49,23,"Song 19 49 23",199,'Unknown'); +(20,20,24,"Song 20 20 24",266,'Unknown'); +(15,45,25,"Song 15 45 25",433,'Unknown'); +(14,44,26,"Song 14 44 26",482,'Unknown'); +(19,19,27,"Song 19 19 27",345,'Unknown'); +(13,43,28,"Song 13 43 28",159,'Unknown'); +(18,48,29,"Song 18 48 29",350,'Unknown'); +(13,13,30,"Song 13 13 30",131,'Unknown'); +(9,9,31,"Song 9 9 31",183,'Unknown'); +(13,13,32,"Song 13 13 32",193,'Unknown'); +(24,24,33,"Song 24 24 33",378,'Unknown'); +(30,60,34,"Song 30 60 34",270,'Unknown'); +(13,43,35,"Song 13 43 35",375,'Unknown'); +(27,27,36,"Song 27 27 36",219,'Unknown'); +(20,50,37,"Song 20 50 37",314,'Unknown'); +(18,48,38,"Song 18 48 38",416,'Unknown'); +(21,51,39,"Song 21 51 39",330,'Unknown'); +(1,31,40,"Song 1 31 40",376,'Unknown'); +(5,5,41,"Song 5 5 41",398,'Unknown'); +(15,45,42,"Song 15 45 42",466,'Unknown'); +(24,24,43,"v 24 24 43",384,'Unknown'); +(19,19,44,"Song 19 19 44",472,'Unknown'); +(15,45,45,"Song 15 45 45",246,'Unknown'); +(3,33,46,"Song 3 33 46",412,'Unknown'); +(23,23,47,"Song 23 23 47",159,'Unknown'); +(30,60,48,"Song 30 60 48",290,'Unknown'); +(19,19,49,"Song 19 19 49",446,'Unknown'); +(16,16,50,"Song 16 16 50",485,'Unknown'); +(4,4,51,"Song 4 4 51",185,'Unknown'); +(8,38,52,"Song 8 38 52",349,'Unknown'); +(24,54,53,"Song 24 54 53",301,'Unknown'); +(5,35,54,"Song 5 35 54",206,'Unknown'); +(30,30,55,"Song 30 30 55",250,'Unknown'); +(12,42,56,"Song 12 42 56",146,'Unknown'); +(30,30,57,"Song 30 30 57",416,'Unknown'); +(26,56,58,"Song 26 56 58",244,'Unknown'); +(20,50,59,"Song 20 50 59",356,'Unknown'); +(7,7,60,"Song 7 7 60",234,'Unknown'); +(19,19,61,"Song 19 19 61",412,'Unknown'); +(13,43,62,"Song 13 43 62",161,'Unknown'); +(5,5,63,"Song 5 5 63",300,'Unknown'); +(1,31,64,"Song 1 31 64",307,'Unknown'); +(4,4,65,"Song 4 4 65",197,'Unknown'); +(24,54,66,"Song 24 54 66",180,'Unknown'); +(3,3,67,"Song 3 3 67",156,'Unknown'); +(14,44,68,"Song 14 44 68",184,'Unknown'); +(21,51,69,"Song 21 51 69",486,'Unknown'); +(19,49,70,"Song 19 49 70",212,'Unknown'); +(9,39,71,"Song 9 39 71",452,'Unknown'); +(23,53,72,"Song 23 53 72",425,'Unknown'); +(11,41,73,"Song 11 41 73",316,'Unknown'); +(8,8,74,"Song 8 8 74",395,'Unknown'); +(9,9,75,"Song 9 9 75",189,'Unknown'); +(2,2,76,"Song 2 2 76",354,'Unknown'); +(23,53,77,"Song 23 53 77",137,'Unknown'); +(15,15,78,"TSong 15 15 78",176,'Unknown'); +(30,60,79,"Song 30 60 79",224,'Unknown'); +(14,44,80,"Song 14 44 80",305,'Unknown'); +(27,27,81,"Song 27 27 81",432,'Unknown'); +(18,18,82,"Song 18 18 82",357,'Unknown'); +(10,10,83,"Song 10 10 83",187,'Unknown'); +(12,42,84,"Song 12 42 84",461,'Unknown'); +(8,8,85,"Song 8 8 85",434,'Unknown'); +(1,31,86,"Song 1 31 86",436,'Unknown'); +(11,41,87,"Song 11 41 87",469,'Unknown'); +(13,13,88,"Song 13 13 88",452,'Unknown'); +(4,34,89,"Song 4 34 89",309,'Unknown'); +(21,21,90,"Song 21 21 90",226,'Unknown'); +(6,36,91,"Song 6 36 91",257,'Unknown'); +(27,27,92,"Song 27 27 92",251,'Unknown'); +(9,39,93,"Song 9 39 93",325,'Unknown'); +(30,30,94,"Song 30 30 94",122,'Unknown'); +(29,59,95,"Song 29 59 95",207,'Unknown'); +(1,1,96,"Song 1 1 96",318,'Unknown'); +(4,4,97,"Song 4 4 97",353,'Unknown'); +(23,23,98,"Song 23 23 98",450,'Unknown'); +(12,12,99,"Song 12 12 99",323,'Unknown'); +(24,24,100,"Song 24 24 100",397,'Unknown'); +(27,27,101,"Song 27 27 101",296,'Unknown'); +(29,59,102,"Song 29 59 102",349,'Unknown'); +(17,47,103,"Song 17 47 103",438,'Unknown'); +(5,5,104,"Song 5 5 104",388,'Unknown'); +(26,56,105,"Song 26 56 105",425,'Unknown'); +(22,52,106,"Song 22 52 106",154,'Unknown'); +(23,23,107,"Song 23 23 107",213,'Unknown'); +(8,38,108,"Song 8 38 108",276,'Unknown'); +(9,39,109,"Song 9 39 109",417,'Unknown'); +(9,9,110,"Song 9 9 110",299,'Unknown'); +(22,52,111,"Song 22 52 111",476,'Unknown'); +(21,21,112,"Song 21 21 112",225,'Unknown'); +(23,23,113,"Song 23 23 113",303,'Unknown'); +(7,7,114,"Song 7 7 114",291,'Unknown'); +(8,38,115,"Song 8 38 115",276,'Unknown'); +(14,44,116,"Song 14 44 116",238,'Unknown'); +(27,57,117,"Song 27 57 117",188,'Unknown'); +(28,28,118,"Song 28 28 118",372,'Unknown'); +(15,15,119,"Song 15 15 119",258,'Unknown'); +(21,21,120,"Song 21 21 120",308,'Unknown'); +(29,59,121,"Song 29 59 121",319,'Unknown'); +(28,58,122,"Song 28 58 122",453,'Unknown'); +(7,7,123,"Song 7 7 123",198,'Unknown'); +(4,4,124,"Song 4 4 124",435,'Unknown'); +(27,27,125,"Song 27 27 125",475,'Unknown'); +(30,30,126,"Song 30 30 126",395,'Unknown'); +(21,51,127,"Song 21 51 127",454,'Unknown'); +(29,29,128,"Song 29 29 128",376,'Unknown'); +(27,57,129,"Song 27 57 129",396,'Unknown'); +(23,53,130,"Song 23 53 130",458,'Unknown'); +(6,36,131,"Song 6 36 131",289,'Unknown'); +(29,29,132,"Song 29 29 132",207,'Unknown'); +(25,55,133,"Song 25 55 133",280,'Unknown'); +(3,3,134,"Song 3 3 134",432,'Unknown'); +(5,35,135,"1 5 35 135",304,'Unknown'); +(3,3,136,"2 3 3 136",392,'Unknown'); +(12,12,137,"3 12 12 137",393,'Unknown'); +(13,13,138,"4 13 13 138",382,'Unknown'); +(18,48,139,"5 18 48 139",447,'Unknown'); +(17,17,140,"6 17 17 140",182,'Unknown'); +(23,23,141,"7 23 23 141",266,'Unknown'); +(21,51,142,"8 21 51 142",383,'Unknown'); +(3,3,143,"9 3 3 143",439,'Unknown'); +(25,25,144,"10 25 25 144",454,'Unknown'); +(12,12,145,"11 12 12 145",179,'Unknown'); +(19,19,146,"12 19 19 146",422,'Unknown'); +(24,54,147,"13 24 54 147",478,'Unknown'); +(8,38,148,"14 8 38 148",233,'Unknown'); +(6,6,149,"15 6 6 149",245,'Unknown'); From 759e6f98db45912124b53db94e5727d13f7fc883 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Mon, 19 Aug 2019 16:25:24 -0400 Subject: [PATCH 0016/1979] Update Spanner JDBC README (#6105) --- java-spanner-jdbc/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 73642fe7d2be..0162399a4e64 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -3,9 +3,6 @@ JDBC Driver for [Google Cloud Spanner](https://cloud.google.com/spanner/). -> Note: This client is a work-in-progress, and may occasionally -> make backwards-incompatible changes. - ## Quickstart [//]: # ({x-version-update-start:google-cloud-spanner-jdbc:released}) From 177156c4c58fdd7c0412eeaa3bf891083c50666f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 19 Aug 2019 22:26:36 +0200 Subject: [PATCH 0017/1979] spanner-jdbc: Add integration tests for JDBC DatabaseMetadata (#6035) * add integration tests for jdbc database metadata * fix formatting * use random data --- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 560 ++++++++++++++++++ 1 file changed, 560 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java new file mode 100644 index 000000000000..124664dc7cff --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -0,0 +1,560 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Integration tests for {@link DatabaseMetaData} implementation for Spanner. */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { + private static final String DEFAULT_CATALOG = ""; + private static final String DEFAULT_SCHEMA = ""; + private static final String SINGERS_TABLE = "Singers"; + private static final String ALBUMS_TABLE = "Albums"; + private static final String SONGS_TABLE = "Songs"; + private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; + + @Override + protected boolean doCreateMusicTables() { + return true; + } + + private static final class Column { + private final String name; + private final int type; + private final String typeName; + private final Integer colSize; + private final Integer decimalDigits; + private final Integer radix; + private final boolean nullable; + private final Integer charOctetLength; + + private Column( + String name, + int type, + String typeName, + Integer colSize, + Integer decimalDigits, + Integer radix, + boolean nullable, + Integer charOctetLength) { + this.name = name; + this.type = type; + this.typeName = typeName; + this.colSize = colSize; + this.decimalDigits = decimalDigits; + this.radix = radix; + this.nullable = nullable; + this.charOctetLength = charOctetLength; + } + } + + private static final List EXPECTED_COLUMNS = + Arrays.asList( + new Column("ColInt64", Types.BIGINT, "INT64", 19, null, 10, false, null), + new Column("ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null), + new Column("ColBool", Types.BOOLEAN, "BOOL", null, null, null, false, null), + new Column("ColString", Types.NVARCHAR, "STRING(100)", 100, null, null, false, 100), + new Column( + "ColStringMax", Types.NVARCHAR, "STRING(MAX)", 2621440, null, null, false, 2621440), + new Column("ColBytes", Types.BINARY, "BYTES(100)", 100, null, null, false, null), + new Column("ColBytesMax", Types.BINARY, "BYTES(MAX)", 10485760, null, null, false, null), + new Column("ColDate", Types.DATE, "DATE", 10, null, null, false, null), + new Column("ColTimestamp", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), + new Column("ColCommitTS", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), + new Column("ColInt64Array", Types.ARRAY, "ARRAY", 19, null, 10, true, null), + new Column("ColFloat64Array", Types.ARRAY, "ARRAY", 15, 16, 2, true, null), + new Column("ColBoolArray", Types.ARRAY, "ARRAY", null, null, null, true, null), + new Column( + "ColStringArray", Types.ARRAY, "ARRAY", 100, null, null, true, 100), + new Column( + "ColStringMaxArray", + Types.ARRAY, + "ARRAY", + 2621440, + null, + null, + true, + 2621440), + new Column( + "ColBytesArray", Types.ARRAY, "ARRAY", 100, null, null, true, null), + new Column( + "ColBytesMaxArray", + Types.ARRAY, + "ARRAY", + 10485760, + null, + null, + true, + null), + new Column("ColDateArray", Types.ARRAY, "ARRAY", 10, null, null, true, null), + new Column( + "ColTimestampArray", Types.ARRAY, "ARRAY", 35, null, null, true, null)); + + @Test + public void testGetColumns() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection + .getMetaData() + .getColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { + int pos = 1; + for (Column col : EXPECTED_COLUMNS) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("COLUMN_NAME"), is(equalTo(col.name))); + assertThat(rs.getInt("DATA_TYPE"), is(equalTo(col.type))); + assertThat(rs.getString("TYPE_NAME"), is(equalTo(col.typeName))); + if (col.colSize == null) { + assertThat(rs.getInt("COLUMN_SIZE"), is(equalTo(0))); + assertThat(rs.wasNull(), is(true)); + } else { + assertThat(rs.getInt("COLUMN_SIZE"), is(equalTo(col.colSize))); + } + rs.getObject("BUFFER_LENGTH"); // just assert that it exists + if (col.decimalDigits == null) { + assertThat(rs.getInt("DECIMAL_DIGITS"), is(equalTo(0))); + assertThat(rs.wasNull(), is(true)); + } else { + assertThat(rs.getInt("DECIMAL_DIGITS"), is(equalTo(col.decimalDigits))); + } + if (col.radix == null) { + assertThat(rs.getInt("NUM_PREC_RADIX"), is(equalTo(0))); + assertThat(rs.wasNull(), is(true)); + } else { + assertThat(rs.getInt("NUM_PREC_RADIX"), is(equalTo(col.radix))); + } + assertThat( + rs.getInt("NULLABLE"), + is( + equalTo( + col.nullable + ? DatabaseMetaData.columnNullable + : DatabaseMetaData.columnNoNulls))); + assertThat(rs.getString("REMARKS"), is(nullValue())); + assertThat(rs.getString("COLUMN_DEF"), is(nullValue())); + assertThat(rs.getInt("SQL_DATA_TYPE"), is(equalTo(0))); + assertThat(rs.getInt("SQL_DATETIME_SUB"), is(equalTo(0))); + if (col.charOctetLength == null) { + assertThat(rs.getInt("CHAR_OCTET_LENGTH"), is(equalTo(0))); + assertThat(rs.wasNull(), is(true)); + } else { + assertThat(rs.getInt("CHAR_OCTET_LENGTH"), is(equalTo(col.charOctetLength))); + } + assertThat(rs.getInt("ORDINAL_POSITION"), is(equalTo(pos))); + assertThat(rs.getString("IS_NULLABLE"), is(equalTo(col.nullable ? "YES" : "NO"))); + assertThat(rs.getString("SCOPE_CATALOG"), is(nullValue())); + assertThat(rs.getString("SCOPE_SCHEMA"), is(nullValue())); + assertThat(rs.getString("SCOPE_TABLE"), is(nullValue())); + assertThat(rs.getShort("SOURCE_DATA_TYPE"), is(equalTo((short) 0))); + assertThat(rs.wasNull(), is(true)); + assertThat(rs.getString("IS_AUTOINCREMENT"), is(equalTo("NO"))); + assertThat(rs.getString("IS_GENERATEDCOLUMN"), is(equalTo("NO"))); + assertThat(rs.getMetaData().getColumnCount(), is(equalTo(24))); + + pos++; + } + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testGetCrossReferences() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + SINGERS_TABLE, + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + ALBUMS_TABLE)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Singers"))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Albums"))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + ALBUMS_TABLE, + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + SONGS_TABLE)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Albums"))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Songs"))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Albums"))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("AlbumId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Songs"))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("AlbumId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + } + // try getting self-references + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + ALBUMS_TABLE, + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + ALBUMS_TABLE)) { + assertThat(rs.next(), is(false)); + } + // try getting all cross-references in the database + try (ResultSet rs = + connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { + for (int i = 0; i < 3; i++) { + assertThat(rs.next(), is(true)); + } + assertThat(rs.next(), is(false)); + } + } + } + + private static final class IndexInfo { + private final String tableName; + private final boolean nonUnique; + private final String indexName; + private final short ordinalPosition; + private final String columnName; + private final String ascDesc; + + private IndexInfo( + String tableName, + boolean nonUnique, + String indexName, + int ordinalPosition, + String columnName, + String ascDesc) { + this.tableName = tableName; + this.nonUnique = nonUnique; + this.indexName = indexName; + this.ordinalPosition = (short) ordinalPosition; + this.columnName = columnName; + this.ascDesc = ascDesc; + } + } + + private static final List EXPECTED_INDICES = + Arrays.asList( + 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("Albums", true, "AlbumsByAlbumTitle2", 0, "MarketingBudget", null), + new IndexInfo("Albums", true, "AlbumsByAlbumTitle2", 1, "AlbumTitle", "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"), + new IndexInfo("Singers", false, "PRIMARY_KEY", 1, "SingerId", "A"), + new IndexInfo("Singers", true, "SingersByFirstLastName", 1, "FirstName", "A"), + new IndexInfo("Singers", true, "SingersByFirstLastName", 2, "LastName", "A"), + new IndexInfo("Songs", false, "PRIMARY_KEY", 1, "SingerId", "A"), + new IndexInfo("Songs", false, "PRIMARY_KEY", 2, "AlbumId", "A"), + new IndexInfo("Songs", false, "PRIMARY_KEY", 3, "TrackId", "A"), + new IndexInfo("Songs", false, "SongsBySingerAlbumSongNameDesc", 1, "SingerId", "A"), + new IndexInfo("Songs", false, "SongsBySingerAlbumSongNameDesc", 2, "AlbumId", "A"), + new IndexInfo("Songs", false, "SongsBySingerAlbumSongNameDesc", 3, "SongName", "D"), + new IndexInfo("Songs", true, "SongsBySongName", 1, "SongName", "A"), + new IndexInfo("TableWithAllColumnTypes", false, "PRIMARY_KEY", 1, "ColInt64", "A")); + + @Test + public void testGetIndexInfo() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection + .getMetaData() + .getIndexInfo(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, false, false)) { + + for (IndexInfo index : EXPECTED_INDICES) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(index.tableName))); + assertThat(rs.getBoolean("NON_UNIQUE"), is(index.nonUnique)); + assertThat(rs.getString("INDEX_QUALIFIER"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("INDEX_NAME"), is(equalTo(index.indexName))); + if (index.indexName.equals("PRIMARY_KEY")) { + assertThat(rs.getShort("TYPE"), is(equalTo(DatabaseMetaData.tableIndexClustered))); + } else { + assertThat(rs.getShort("TYPE"), is(equalTo(DatabaseMetaData.tableIndexHashed))); + } + assertThat(rs.getShort("ORDINAL_POSITION"), is(equalTo(index.ordinalPosition))); + if (index.ordinalPosition == 0) { + assertThat(rs.wasNull(), is(true)); + } + assertThat(rs.getString("COLUMN_NAME"), is(equalTo(index.columnName))); + assertThat(rs.getString("ASC_OR_DESC"), is(equalTo(index.ascDesc))); + assertThat(rs.getInt("CARDINALITY"), is(equalTo(-1))); + assertThat(rs.getInt("PAGES"), is(equalTo(-1))); + assertThat(rs.getString("FILTER_CONDITION"), is(nullValue())); + } + // all indices found + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testGetExportedKeys() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection + .getMetaData() + .getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { + assertKeysSingersAlbums(rs); + } + try (ResultSet rs = + connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { + assertKeysAlbumsSongs(rs); + } + } + } + + @Test + public void testGetImportedKeys() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { + assertKeysSingersAlbums(rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SONGS_TABLE)) { + assertKeysAlbumsSongs(rs); + } + } + } + + private void assertKeysSingersAlbums(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + assertThat(rs.next(), is(false)); + } + + private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(SONGS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("AlbumId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(SONGS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("AlbumId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + assertThat(rs.next(), is(false)); + } + + @Test + public void testGetPrimaryKeys() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(SINGERS_TABLE))); + assertThat(rs.getString("COLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getInt("KEY_SEQ"), is(equalTo(1))); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.next(), is(false)); + } + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("COLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getInt("KEY_SEQ"), is(equalTo(1))); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("COLUMN_NAME"), is(equalTo("AlbumId"))); + assertThat(rs.getInt("KEY_SEQ"), is(equalTo(2))); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.next(), is(false)); + } + } + } + + @Test + public void testGetSchemas() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = connection.getMetaData().getSchemas()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("INFORMATION_SCHEMA"))); + 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))); + } + } + } + + private static final class Table { + private final String name; + + private Table(String name) { + this.name = name; + } + } + + private static final List EXPECTED_TABLES = + Arrays.asList( + new Table("Albums"), + new Table("Concerts"), + new Table("Singers"), + new Table("Songs"), + new Table("TableWithAllColumnTypes")); + + @Test + public void testGetTables() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { + for (Table table : EXPECTED_TABLES) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("TABLE_NAME"), is(equalTo(table.name))); + assertThat(rs.getString("TABLE_TYPE"), is(equalTo("TABLE"))); + assertThat(rs.getString("REMARKS"), is(nullValue())); + assertThat(rs.getString("TYPE_CAT"), is(nullValue())); + assertThat(rs.getString("TYPE_SCHEM"), is(nullValue())); + assertThat(rs.getString("TYPE_NAME"), is(nullValue())); + assertThat(rs.getString("SELF_REFERENCING_COL_NAME"), is(nullValue())); + assertThat(rs.getString("REF_GENERATION"), is(nullValue())); + } + assertThat(rs.next(), is(false)); + } + } + } +} From bb97b38b20158ead268988446bc38a2e3cccf68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2019 19:13:15 +0200 Subject: [PATCH 0018/1979] make sql logging optional (#6111) --- .../jdbc/AbstractSqlScriptVerifier.java | 15 +++--- .../jdbc/ClientSideStatementsTest.java | 2 +- .../ConnectionImplGeneratedSqlScriptTest.java | 2 +- .../JdbcConnectionGeneratedSqlScriptTest.java | 2 +- .../spanner/jdbc/JdbcTimeoutSqlTest.java | 2 +- .../SetReadOnlyStalenessSqlScriptTest.java | 2 +- .../SetStatementTimeoutSqlScriptTest.java | 2 +- .../cloud/spanner/jdbc/it/ITDdlTest.java | 2 +- .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 2 +- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 4 +- .../it/ITJdbcReadWriteAutocommitTest.java | 2 +- .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 53 +++++-------------- .../jdbc/it/ITReadOnlySpannerTest.java | 4 +- .../it/ITReadWriteAutocommitSpannerTest.java | 2 +- .../spanner/jdbc/it/ITSqlScriptTest.java | 47 +++++----------- .../jdbc/it/ITTransactionModeTest.java | 2 +- 16 files changed, 47 insertions(+), 98 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java index 489370364945..71a1865b84ec 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java @@ -182,6 +182,8 @@ public static List readStatementsFromFile(String filename, Class reso private final Map variables = new HashMap<>(); + private final boolean logStatements; + /** * Constructor for a verifier that will take a {@link GenericConnection} as a parameter to the * {@link AbstractSqlScriptVerifier#verifyStatementsInFile(GenericConnection, String, Class, @@ -194,6 +196,7 @@ public AbstractSqlScriptVerifier() { /** Constructor for a verifier that will use a connection provider for connections */ public AbstractSqlScriptVerifier(GenericConnectionProvider provider) { this.connectionProvider = provider; + this.logStatements = Boolean.parseBoolean(System.getProperty("log_sql_statements", "false")); } /** @@ -209,14 +212,10 @@ public AbstractSqlScriptVerifier(GenericConnectionProvider provider) { * semicolon (;) * @param resourceClass The class that should be used to locate the resource specified by the file * name - * @param logStatements Should the verifier log each statement that is executed and verified to - * standard out * @throws Exception */ - public void verifyStatementsInFile(String filename, Class resourceClass, boolean logStatements) - throws Exception { - verifyStatementsInFile( - connectionProvider.getConnection(), filename, resourceClass, logStatements); + public void verifyStatementsInFile(String filename, Class resourceClass) throws Exception { + verifyStatementsInFile(connectionProvider.getConnection(), filename, resourceClass); } /** @@ -230,11 +229,9 @@ public void verifyStatementsInFile(String filename, Class resourceClass, bool * @param filename The file name containing the statements. Statements must be separated by a * semicolon (;) * @param resourceClass The class that defines the package where to find the input file - * @param logStatements Should all statements be logged to standard out? */ public void verifyStatementsInFile( - GenericConnection connection, String filename, Class resourceClass, boolean logStatements) - throws Exception { + GenericConnection connection, String filename, Class resourceClass) throws Exception { try { List statements = readStatementsFromFile(filename, resourceClass); for (String statement : statements) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java index 18a13017ff43..4ba2cb7a0fb4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java @@ -48,7 +48,7 @@ public class ClientSideStatementsTest { @Test public void testExecuteClientSideStatementsScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("ClientSideStatementsTest.sql", getClass(), false); + verifier.verifyStatementsInFile("ClientSideStatementsTest.sql", getClass()); } private static final String SCRIPT_FILE = diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java index 6a56250a8785..6e2008eb1a37 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java @@ -59,7 +59,7 @@ public GenericConnection getConnection() { @Test public void testGeneratedScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("ConnectionImplGeneratedSqlScriptTest.sql", getClass(), false); + verifier.verifyStatementsInFile("ConnectionImplGeneratedSqlScriptTest.sql", getClass()); } /** diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index 8fdbeacbd543..fb4fccbc643b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -57,6 +57,6 @@ public GenericConnection getConnection() { public void testGeneratedScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); verifier.verifyStatementsInFile( - "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class, false); + "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java index fc9d81549c56..6d743d147c21 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java @@ -35,6 +35,6 @@ public class JdbcTimeoutSqlTest { @Test public void testTimeoutScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass(), false); + verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java index 43cf113ccee5..de32e0f5bc0e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java @@ -42,6 +42,6 @@ public GenericConnection getConnection() { @Test public void testSetReadOnlyStalenessScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("SetReadOnlyStalenessTest.sql", getClass(), false); + verifier.verifyStatementsInFile("SetReadOnlyStalenessTest.sql", getClass()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java index 594e5772911d..62b76b3fe389 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java @@ -38,6 +38,6 @@ public GenericConnection getConnection() { @Test public void testSetStatementTimeoutScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("SetStatementTimeoutTest.sql", getClass(), false); + verifier.verifyStatementsInFile("SetStatementTimeoutTest.sql", getClass()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java index c59d2fe668a1..1642c26bf57f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java @@ -32,6 +32,6 @@ public class ITDdlTest extends ITAbstractSpannerTest { @Test public void testSqlScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index 794f8338afe6..4fe79a3febd6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -33,6 +33,6 @@ public class ITJdbcDdlTest extends ITAbstractJdbcTest { @Test public void testSqlScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); - verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 3bab287c6c85..8e083f592ecb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -56,7 +56,7 @@ public void createTestTables() throws Exception { // create tables JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class, true); + "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class); // fill tables with data connection.setAutoCommit(false); @@ -89,7 +89,7 @@ public void createTestTables() throws Exception { @Test public void testSqlScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); - verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 752cb868d30c..315cdc17e199 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -56,7 +56,7 @@ public boolean doCreateDefaultTestTable() { public void test01_SqlScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class, true); + "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index 43cfb43c0754..cc1334662945 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -72,7 +72,7 @@ public class ITJdbcSqlScriptTest extends ITAbstractJdbcTest { public void test01_CreateTables() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class, true); + JdbcGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class); } } @@ -83,8 +83,7 @@ public void test02_InsertTestData() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), INSERT_AND_VERIFY_TEST_DATA, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -92,10 +91,7 @@ public void test02_InsertTestData() throws Exception { public void test03_TestGetReadTimestamp() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_GET_READ_TIMESTAMP, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_GET_READ_TIMESTAMP, SqlScriptVerifier.class); } } @@ -103,10 +99,7 @@ public void test03_TestGetReadTimestamp() throws Exception { public void test04_TestGetCommitTimestamp() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_GET_COMMIT_TIMESTAMP, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_GET_COMMIT_TIMESTAMP, SqlScriptVerifier.class); } } @@ -116,8 +109,7 @@ public void test05_TestTemporaryTransactions() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), TEST_TEMPORARY_TRANSACTIONS, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -125,10 +117,7 @@ public void test05_TestTemporaryTransactions() throws Exception { public void test06_TestTransactionMode() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_TRANSACTION_MODE, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_TRANSACTION_MODE, SqlScriptVerifier.class); } } @@ -138,8 +127,7 @@ public void test07_TestTransactionModeReadOnly() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), TEST_TRANSACTION_MODE_READ_ONLY, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -147,10 +135,7 @@ public void test07_TestTransactionModeReadOnly() throws Exception { public void test08_TestReadOnlyStaleness() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_READ_ONLY_STALENESS, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_READ_ONLY_STALENESS, SqlScriptVerifier.class); } } @@ -158,10 +143,7 @@ public void test08_TestReadOnlyStaleness() throws Exception { public void test09_TestAutocommitDmlMode() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_AUTOCOMMIT_DML_MODE, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_AUTOCOMMIT_DML_MODE, SqlScriptVerifier.class); } } @@ -169,10 +151,7 @@ public void test09_TestAutocommitDmlMode() throws Exception { public void test10_TestAutocommitReadOnly() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_AUTOCOMMIT_READ_ONLY, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_AUTOCOMMIT_READ_ONLY, SqlScriptVerifier.class); } } @@ -180,10 +159,7 @@ public void test10_TestAutocommitReadOnly() throws Exception { public void test11_TestStatementTimeout() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_STATEMENT_TIMEOUT, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_STATEMENT_TIMEOUT, SqlScriptVerifier.class); } try (Connection connection = createConnection()) { // Create a statement with a query timeout, but do not set a statement timeout on the @@ -221,7 +197,7 @@ public void test11_TestStatementTimeout() throws Exception { public void test12_TestSetStatements() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class, true); + JdbcGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class); } } @@ -229,10 +205,7 @@ public void test12_TestSetStatements() throws Exception { public void test13_TestInvalidStatements() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), - TEST_INVALID_STATEMENTS, - SqlScriptVerifier.class, - true); + JdbcGenericConnection.of(connection), TEST_INVALID_STATEMENTS, SqlScriptVerifier.class); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java index 8e46ceceebd1..b3aa8ea751c8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java @@ -69,7 +69,7 @@ public void createTestTables() throws Exception { // create tables SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class, true); + "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class); // fill tables with data connection.setAutocommit(false); @@ -102,7 +102,7 @@ public void createTestTables() throws Exception { @Test public void testSqlScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java index f08e6226721a..aa464fd4b756 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java @@ -63,7 +63,7 @@ public boolean doCreateDefaultTestTable() { public void test01_SqlScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class, true); + "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java index be20ec3c4591..9f60ae6ccb00 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java @@ -62,10 +62,7 @@ public class ITSqlScriptTest extends ITAbstractSpannerTest { public void test01_CreateTables() throws Exception { try (ITConnection connection = createConnection()) { verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - CREATE_TABLES_FILE, - SqlScriptVerifier.class, - true); + SpannerGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class); } } @@ -75,8 +72,7 @@ public void test02_InsertTestData() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), INSERT_AND_VERIFY_TEST_DATA, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -86,8 +82,7 @@ public void test03_TestGetReadTimestamp() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_GET_READ_TIMESTAMP, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -97,8 +92,7 @@ public void test04_TestGetCommitTimestamp() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_GET_COMMIT_TIMESTAMP, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -108,8 +102,7 @@ public void test05_TestTemporaryTransactions() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_TEMPORARY_TRANSACTIONS, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -117,10 +110,7 @@ public void test05_TestTemporaryTransactions() throws Exception { public void test06_TestTransactionMode() throws Exception { try (ITConnection connection = createConnection()) { verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_TRANSACTION_MODE, - SqlScriptVerifier.class, - true); + SpannerGenericConnection.of(connection), TEST_TRANSACTION_MODE, SqlScriptVerifier.class); } } @@ -130,8 +120,7 @@ public void test07_TestTransactionModeReadOnly() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_TRANSACTION_MODE_READ_ONLY, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -141,8 +130,7 @@ public void test08_TestReadOnlyStaleness() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_READ_ONLY_STALENESS, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -152,8 +140,7 @@ public void test09_TestAutocommitDmlMode() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_AUTOCOMMIT_DML_MODE, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -163,8 +150,7 @@ public void test10_TestAutocommitReadOnly() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_AUTOCOMMIT_READ_ONLY, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } @@ -172,10 +158,7 @@ public void test10_TestAutocommitReadOnly() throws Exception { public void test11_TestStatementTimeout() throws Exception { try (ITConnection connection = createConnection()) { verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_STATEMENT_TIMEOUT, - SqlScriptVerifier.class, - true); + SpannerGenericConnection.of(connection), TEST_STATEMENT_TIMEOUT, SqlScriptVerifier.class); } } @@ -183,10 +166,7 @@ public void test11_TestStatementTimeout() throws Exception { public void test12_TestSetStatements() throws Exception { try (ITConnection connection = createConnection()) { verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_SET_STATEMENTS, - SqlScriptVerifier.class, - true); + SpannerGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class); } } @@ -196,8 +176,7 @@ public void test13_TestInvalidStatements() throws Exception { verifier.verifyStatementsInFile( SpannerGenericConnection.of(connection), TEST_INVALID_STATEMENTS, - SqlScriptVerifier.class, - true); + SqlScriptVerifier.class); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java index 7e3959e8449a..19c204a75254 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java @@ -55,7 +55,7 @@ public boolean doCreateDefaultTestTable() { @Test public void testSqlScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITTransactionModeTest.sql", SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile("ITTransactionModeTest.sql", SqlScriptVerifier.class); } @Test From 960124d0ec23abfdb0a910db8a2dbf16c6ce9d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2019 19:13:33 +0200 Subject: [PATCH 0019/1979] spanner-jdbc: Add music sql script based integration tests (#6034) * add music sql script based tests * allow using custom host for integration tests * replace base64 data with random numbers * run code formatter * use random data * fixed reference to wrong first name * count nested aborts as successful retries * simplify assertion to prevent flaky failures Simplify the assertion as the actual number of restarts of a transaction cannot be determined for certain, as Cloud Spanner might abort any transaction. * run code formatter * move connection URL generation to util method --- .../spanner/jdbc/ITAbstractJdbcTest.java | 11 +- .../spanner/jdbc/ITAbstractSpannerTest.java | 18 +- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 43 ++ .../spanner/jdbc/it/ITSqlMusicScriptTest.java | 205 ++++++ .../jdbc/it/ITTransactionRetryTest.java | 10 +- .../spanner/jdbc/ITSqlMusicScriptTest.sql | 670 ++++++++++++++++++ 6 files changed, 941 insertions(+), 16 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index f02eb7704969..eab1fcc521af 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -87,12 +87,11 @@ public static void setup() throws IOException, InterruptedException, ExecutionEx * @return The newly opened JDBC connection. */ public CloudSpannerJdbcConnection createConnection() throws SQLException { - StringBuilder url = new StringBuilder("jdbc:cloudspanner:"); - String host = env.getTestHelper().getOptions().getHost(); - if (host != null) { - url.append(host.substring(host.indexOf(':') + 1)); - } - url.append("/").append(getDatabase().getId().getName()); + // Create a connection URL for the generic connection API. + StringBuilder url = + ITAbstractSpannerTest.extractConnectionUrl(env.getTestHelper().getOptions(), getDatabase()); + // Prepend it with 'jdbc:' to make it a valid JDBC connection URL. + url.insert(0, "jdbc:"); if (hasValidKeyFile()) { url.append(";credentials=").append(getKeyFile()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java index affb025134a0..beb5b56bbfc2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java @@ -23,6 +23,7 @@ import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TransactionManager; import com.google.cloud.spanner.TransactionManager.TransactionState; @@ -167,6 +168,20 @@ protected static Database getDatabase() { return database; } + /** + * Returns a connection URL that is extracted from the given {@link SpannerOptions} and database + * in the form + * cloudspanner:[//host]/projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID + */ + static StringBuilder extractConnectionUrl(SpannerOptions options, Database database) { + StringBuilder url = new StringBuilder("cloudspanner:"); + if (options.getHost() != null) { + url.append(options.getHost().substring(options.getHost().indexOf(':') + 1)); + } + url.append("/").append(database.getId().getName()); + return url; + } + @BeforeClass public static void setup() throws IOException, InterruptedException, ExecutionException { database = env.getTestHelper().createTestDatabase(); @@ -211,7 +226,8 @@ public ITConnection createConnection( public ITConnection createConnection( List interceptors, List transactionRetryListeners) { - StringBuilder url = new StringBuilder("cloudspanner:/").append(getDatabase().getId().getName()); + StringBuilder url = + extractConnectionUrl(getTestEnv().getTestHelper().getOptions(), getDatabase()); appendConnectionUri(url); ConnectionOptions.Builder builder = ConnectionOptions.newBuilder() diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java new file mode 100644 index 000000000000..5bc8945173c6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import java.sql.Connection; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcSqlMusicScriptTest extends ITAbstractJdbcTest { + private static final String SCRIPT_FILE = "ITSqlMusicScriptTest.sql"; + + @Test + public void testRunScript() throws Exception { + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(); + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), SCRIPT_FILE, SqlScriptVerifier.class, true); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java new file mode 100644 index 000000000000..07cee877506d --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java @@ -0,0 +1,205 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier; +import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; +import java.util.ArrayList; +import java.util.List; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +/** + * Integration test that runs one long sql script using the default Singers/Albums/Songs/Concerts + * data model + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ITSqlMusicScriptTest extends ITAbstractSpannerTest { + private static final String SCRIPT_FILE = "ITSqlMusicScriptTest.sql"; + + @Test + public void test01_RunScript() throws Exception { + SqlScriptVerifier verifier = new SqlScriptVerifier(); + try (GenericConnection connection = SpannerGenericConnection.of(createConnection())) { + verifier.verifyStatementsInFile(connection, SCRIPT_FILE, SqlScriptVerifier.class, true); + } + } + + @Test + public void test02_RunAbortedTest() { + final long SINGER_ID = 2L; + final long VENUE_ID = 68L; + final long NUMBER_OF_SINGERS = 30L; + final long NUMBER_OF_ALBUMS = 60L; + final long NUMBER_OF_SONGS = 149L; + final long NUMBER_OF_CONCERTS = 100L; + long numberOfSongs = 0L; + AbortInterceptor interceptor = new AbortInterceptor(0.0D); + try (ITConnection connection = createConnection(interceptor)) { + connection.setAutocommit(false); + connection.setRetryAbortsInternally(true); + // Read all data from the different music tables in the transaction + // The previous test deleted the first two Singers records. + long expectedId = 3L; + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM Singers ORDER BY SingerId"))) { + while (rs.next()) { + assertThat(rs.getLong("SingerId"), is(equalTo(expectedId))); + expectedId++; + } + } + assertThat(expectedId, is(equalTo(NUMBER_OF_SINGERS + 1L))); + expectedId = 3L; + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM Albums ORDER BY AlbumId"))) { + while (rs.next()) { + assertThat(rs.getLong("AlbumId"), is(equalTo(expectedId))); + expectedId++; + // 31 and 32 were deleted by the first test script. + if (expectedId == 31L || expectedId == 32L) { + expectedId = 33L; + } + } + } + assertThat(expectedId, is(equalTo(NUMBER_OF_ALBUMS + 1L))); + expectedId = 1L; + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM Songs ORDER BY TrackId"))) { + while (rs.next()) { + assertThat(rs.getLong("TrackId"), is(equalTo(expectedId))); + expectedId++; + numberOfSongs++; + // 40, 64, 76, 86 and 96 were deleted by the first test script. + if (expectedId == 40L + || expectedId == 64L + || expectedId == 76L + || expectedId == 86L + || expectedId == 96L) { + expectedId++; + } + } + } + assertThat(expectedId, is(equalTo(NUMBER_OF_SONGS + 1L))); + // Concerts are not in the table hierarchy, so no records have been deleted. + expectedId = 1L; + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT * FROM Concerts ORDER BY VenueId"))) { + while (rs.next()) { + assertThat(rs.getLong("VenueId"), is(equalTo(expectedId))); + expectedId++; + } + } + assertThat(expectedId, is(equalTo(NUMBER_OF_CONCERTS + 1L))); + + // make one small concurrent change in a different transaction + List originalPrices; + List newPrices; + try (ITConnection connection2 = createConnection()) { + assertThat(connection2.isAutocommit(), is(true)); + try (ResultSet rs = + connection2.executeQuery( + Statement.newBuilder( + "SELECT TicketPrices FROM Concerts WHERE SingerId=@singer AND VenueId=@venue") + .bind("singer") + .to(SINGER_ID) + .bind("venue") + .to(VENUE_ID) + .build())) { + assertThat(rs.next(), is(true)); + originalPrices = rs.getLongList(0); + // increase one of the prices by 1 + newPrices = new ArrayList<>(originalPrices); + newPrices.set(1, originalPrices.get(1) + 1); + connection2.executeUpdate( + Statement.newBuilder( + "UPDATE Concerts SET TicketPrices=@prices WHERE SingerId=@singer AND VenueId=@venue") + .bind("prices") + .toInt64Array(newPrices) + .bind("singer") + .to(SINGER_ID) + .bind("venue") + .to(VENUE_ID) + .build()); + } + } + + // try to add a new song and then try to commit, but trigger an abort on commit + connection.bufferedWrite( + Mutation.newInsertBuilder("Songs") + .set("SingerId") + .to(3L) + .set("AlbumId") + .to(3L) + .set("TrackId") + .to(1L) + .set("SongName") + .to("Aborted") + .set("Duration") + .to(1L) + .set("SongGenre") + .to("Unknown") + .build()); + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // the transaction retry should fail because of the concurrent modification + boolean expectedException = false; + try { + connection.commit(); + } catch (AbortedDueToConcurrentModificationException e) { + expectedException = true; + } + // verify that the commit aborted, an internal retry was started and then aborted because of + // the concurrent modification + assertThat(expectedException, is(true)); + // verify that the prices were changed + try (ResultSet rs = + connection.executeQuery( + Statement.newBuilder( + "SELECT TicketPrices FROM Concerts WHERE SingerId=@singer AND VenueId=@venue") + .bind("singer") + .to(SINGER_ID) + .bind("venue") + .to(VENUE_ID) + .build())) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLongList(0), is(equalTo(newPrices))); + } + // verify that the new song was not written to the database + try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) FROM Songs"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(0), is(equalTo(numberOfSongs))); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java index 0ece44ed05f7..fb01e97bdd75 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java @@ -1562,14 +1562,6 @@ private void assertRetryStatistics( assertThat( RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(concurrentModificationsExpected))); - // There might be more retry attempts than expected. The number of successful retries should be - // equal to the actual difference between started and successful. - assertThat( - RETRY_STATISTICS.totalSuccessfulRetries, - is( - equalTo( - RETRY_STATISTICS.totalRetryAttemptsStarted - - minAttemptsStartedExpected - + successfulRetriesExpected))); + assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= successfulRetriesExpected, is(true)); } } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql new file mode 100644 index 000000000000..93218da9765d --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql @@ -0,0 +1,670 @@ +/* + * Copyright 2019 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. + */ + +/** + * SQL script that uses the standard Singers/Albums/Songs/Concerts data model for testing the Connection API. + */ + +SET AUTOCOMMIT = FALSE; +START BATCH DDL; + +CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX), + BirthDate DATE +) PRIMARY KEY(SingerId); + +CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); + +CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX), + MarketingBudget INT64 +) PRIMARY KEY(SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE; + +CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); + +CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget); + +CREATE TABLE Songs ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + TrackId INT64 NOT NULL, + SongName STRING(MAX), + Duration INT64, + SongGenre STRING(25) +) PRIMARY KEY(SingerId, AlbumId, TrackId), + INTERLEAVE IN PARENT Albums ON DELETE CASCADE; + +CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums; + +CREATE INDEX SongsBySongName ON Songs(SongName); + +CREATE TABLE Concerts ( + VenueId INT64 NOT NULL, + SingerId INT64 NOT NULL, + ConcertDate DATE NOT NULL, + BeginTime TIMESTAMP, + EndTime TIMESTAMP, + TicketPrices ARRAY +) PRIMARY KEY(VenueId, SingerId, ConcertDate); + +RUN BATCH; + +-- Check that all tables and indices were created +SET AUTOCOMMIT = TRUE; + +@EXPECT RESULT_SET +SELECT TABLE_NAME AS ACTUAL, 'Singers' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Singers'; + +@EXPECT RESULT_SET +SELECT TABLE_NAME AS ACTUAL, 'Albums' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Albums'; + +@EXPECT RESULT_SET +SELECT TABLE_NAME AS ACTUAL, 'Songs' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Songs'; + +@EXPECT RESULT_SET +SELECT TABLE_NAME AS ACTUAL, 'Concerts' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Concerts'; + +@EXPECT RESULT_SET +SELECT INDEX_NAME AS ACTUAL, 'SingersByFirstLastName' AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE INDEX_NAME='SingersByFirstLastName' AND TABLE_NAME='Singers'; + +@EXPECT RESULT_SET +SELECT INDEX_NAME AS ACTUAL, 'AlbumsByAlbumTitle' AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE INDEX_NAME='AlbumsByAlbumTitle' AND TABLE_NAME='Albums'; + +@EXPECT RESULT_SET +SELECT INDEX_NAME AS ACTUAL, 'AlbumsByAlbumTitle2' AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE INDEX_NAME='AlbumsByAlbumTitle2' AND TABLE_NAME='Albums'; + +@EXPECT RESULT_SET +SELECT INDEX_NAME AS ACTUAL, 'SongsBySingerAlbumSongNameDesc' AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE INDEX_NAME='SongsBySingerAlbumSongNameDesc' AND TABLE_NAME='Songs'; + +@EXPECT RESULT_SET +SELECT INDEX_NAME AS ACTUAL, 'SongsBySongName' AS EXPECTED +FROM INFORMATION_SCHEMA.INDEXES +WHERE INDEX_NAME='SongsBySongName' AND TABLE_NAME='Songs'; + +@EXPECT RESULT_SET +SELECT PARENT_TABLE_NAME AS ACTUAL, 'Singers' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Albums'; + +@EXPECT RESULT_SET +SELECT PARENT_TABLE_NAME AS ACTUAL, 'Albums' AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Songs'; + +-- Insert test data +SET AUTOCOMMIT = FALSE; +SET TRANSACTION READ WRITE; + +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (1,'First 1','Last 1',FROM_BASE64('TIX0lfKhZyUjI+F5VXYQ9O/SXgQh4kT4Ktnp7BYPnTmAps2DA2YuulryUp9UD21JxGY1oq+UYQ/HYeN5eZ6aY31ualSCN417oWJH2yeZweByeGpxJ3XQ3tVnjbz2AYfaZ8IAap0v5EbUN/ATQT3H6NBb3qM+RzVK/VszGOxs0i8+aT6rXH3hsfXbgL36zXChrSxDNT4TjxhAjPA1YiDPqw=='),DATE '1906-04-28'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (2,'First 2','Last 2',FROM_BASE64('RtIHMSnQrvv1/aZEhBtP/JBfDe1dLjgRqGOQ/5qr3uYhdId6wthztQel0bD4Ucypl6L6/Lc56rz9PfvwKmvlBuMGr87zBvi1q3O/O74/4MTOl6Nic/3ltzxA7GEIgyKAcbKYdApPdMGMOG2Vx4p8nbPaPwMBr6hcp68A5xG/FLTreNVv2IVZx7NMSw3lqe3AV2uYdKWJp4zFB+qshsCmkA=='),DATE '1922-11-17'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (3,'First 3','Last 3',FROM_BASE64('VF6u7dM6mIY0RebnEh6E0jYajqZcfGH9b9HeotdCvUzpbOo7wJfqPMLZP3QVYnG416BFPct7Bl90EsbNE8FA/4EwUk8SU65N86PZGRoUUXEeTvaojCjVeqTByM0GQ+nROb73Kd0cW/TURRGv3ihLCMQdWIH8iGgCtjN3G+7vBavsinnnToCdSPlJxweyYKTdo+JwdqL3kVFk2O1QymuaHA=='),DATE '1935-11-08'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (4,'First 4','Last 4',FROM_BASE64('8YrvnC8FyWLGLTcv7D/fUKLxX+UqYiz6U0WOJHWyneRCDIFKsLSue3lhtbW+MnsrveL0WFmHHXRTdQ91EWzhvqdIJf4JIyk/Ndmq6mouM0n36EUeTAPQU7Wg4bxsrzggyD5FNvvuimLLpKuQBDZY1os7Xw/bksWUJ7XzZwy90pfDrgtGb4DdWZ1EJ6x71C2IMuzCnzhoV7/E15tXjiOfkg=='),DATE '1945-03-23'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (5,'First 5','Last 5',FROM_BASE64('BOItWwCAuhUAwZxfmh3F3KK6+Ne+KqShIZA/uCHi72wJOY0V3/Y/f5M8XhE+MLwz0VvLANU3Y6sHonGw8d09YkAZEo034Z2Q+YEEfFCwIhUIM+VTfwOkuRYgeU1SXBXjcZc5zsicakqYA82O3cd1RsFW+mmAO/bBcbSqraxuBR/5DYnbKrL9b5q9xqL+kQRMm2ZwoWpQP24Xke3lRlQlYg=='),DATE '1953-06-03'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (6,'First 6','Last 6',FROM_BASE64('Tz+o/44KGH34c7DzY4R/H7v0Uk4HyLV4yzjZ9VApDkhwiNKi33JspiLxfG43UvDpk0nLfRSbwu9h7p69H5NPNs9FyGaLxmqmKlP4/vohRJffbyLPEcGl3uSFRg7tnWcrlyegS03MotT9wXQNfjiAFwDh70jsxd7LnowepMMjk+qt+R8MaZkyZyL/AuE300N5P2D5i7shkS4F3IudQihtIA=='),DATE '1956-02-07'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (7,'First 7','Last 7',FROM_BASE64('r1QqmO+/0+e/J616waBJQVciDvuaLuRahdtZaCC5Tq95VxwIXfZE0Hisj0SER3+3A53DZw0qClcMOdPVTufwrKhAwggyqbtQ54UR2Q/dwAA1rHzikSS9JCyY3ksTQgUYmvcvtlfnNo/RA222yDyJMQ9sBcpJAs5cAbac0X4v8DgWicueJtQe2ohZMh4r7L9LydHW+B8DpqAa2yZWEzHoPw=='),DATE '1969-05-26'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (8,'First 8','Last 8',FROM_BASE64('IEcPp2dPGDIGotq157CMyokgh2eh5buNTqUu6JQfmbpb4vOuNFzFNrljhnFIxqj+PWAhkjjNhcYTHCmwAM5USSjrpyObo6P8KHe1ctENtgzVZ6Ym3OiKydVLsQGltVOFSpT4l/sM2aGc3AiAPkjAncCZudrMy57MtDcIUCwz1I8giEzB2ZOhlSaR2v8Vs+62+KiZOWGFnoVnen4lWywHEw=='),DATE '1978-11-08'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (9,'First 9','Last 9',FROM_BASE64('uNTiTW4e9PZuRNhywFSLAkMtLpkS/+g3J3FWuiI7kAjyWHzIJMX/KswTyyiUKasn1lcdrIieGN1wiyyXU0+o9kbCuCeT4RfrC+tSqh4rm5pbY+JaR65DtbzfGw3TrWkwoHhfxU/ftnZ14v6H3xAMVM22P3rphR833b1jc1lz3R/mdcTN0dEYhzrgCCtpoOygZZpmN8yOUR3AG0oErN1pyw=='),DATE '1987-07-04'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (10,'First 10','Last 10',FROM_BASE64('ZLpjMKSfhG9zjm/ACvA5TwB/djEWviypBYklKeuTwodVKUYciGavmgm2QkwlslDP0D0PutUorM3trZHt2vqSkKdpzoQxPa5fBtuUa+FQ3xtCZ8RoDJoZ1TEy3rGX6oUQh4vsrflFxhzuUKevKPMmf/ZQFvslytPN0vtHbHtPA9i4iaw0R6RuWyoc8QBLcHHyopul63KzweLlTBacSeC7oQ=='),DATE '1993-07-06'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (11,'First 11','Last 11',FROM_BASE64('OwMBMDWFt7Rni8cbwjWDeZ4BWluiA91JHDyh41zm2Vm36DuwwaLblF1kX2oGwJkICx2191DyfnFsJ7xejiPylZg170+iSwOeNkjj7s45JyihJVnCgEN2u5/D/7DFi0lmdqIGQzIJZ7VrhC/qEU8+4kx8uPfoQx8XndgOQJYibzw2YZM6LIMHhmJmd1nDvvda7Etdo5s9rYlGN6lvvBGifA=='),DATE '1895-09-15'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (12,'First 12','Last 12',FROM_BASE64('DNE+9WHnlmdsOLBBtVwEBotQmrHLw3JbKU6CzAGmV6yEtut+dmZU0OyDMK1jMY+vFH1fK0CSUJ4oM9jBkrI2lIhbL4UyxZghP3z6aWyywpOor/llA4xYoNdaT75xcQJUFYkrR1omHA5BqFG72qx+bjv2qV2izdttQYqq72+TYDLYCPLzhB6iP21zodySDD3HS0qc2/FeJHtm4Xe/HdOzlw=='),DATE '1922-01-03'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (13,'First 13','Last 13',FROM_BASE64('ltUFKoMUjmWlo0Vxwq4pd2kONfIX7mnNnmC2UmfF+M6w9X0U41iMVSVkVZBh4jpUNHx3AhZEJH4x7DnGgcuc8JaFbqRCT8GawwmFvrrJV8lBT3fPCV/QRDrP8Mx4DePxnBEcABfwPJlHMOF59WJX67eUyx1o5EnJx+KS8DTEPEh0yKWDreErIvMPft5T5JlHgGqOMrSNX3eKiEPI3sWjpw=='),DATE '1930-08-03'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (14,'First 14','Last 14',FROM_BASE64('SuJFYQf146OJUJCoOUOcN41X8M84E1lHVn/S0mHjrq7J8HPsUmfjAUNrwZ5RVJJ81vsm8I3xQkLtlQRC7lWkS5eCFSSo56B/NwtgtMugg+r7PSjoIC2HbIM0p89PA8QPW7jRMSx7fmSIm+PJBxavr5xJvv38IQboX/G4lK8wtMy0eNySrya0OE5fCKGKvke2fP9V5QpzhC0WnG9lhs/aRg=='),DATE '1940-05-12'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (15,'First 15','Last 15',FROM_BASE64('bUSUVJWZAEqNlHvePw03zNjtv6Bt45YXSnkduopD1wfJK8enFd9/9FwcWpEom6F8k7skYlTFMgsJCoxVXYXEbb9ZXYi0NoevQ3xG9uWT5NvFCKw++IeUwVztUjYIIHkH4zsYI3csH9Su3yHEqddKyg216ccUTgB0NZcosgKs1eTg1NC5BIzqCXa5Z+X38t/QismLAflh1gTbD2F7ihSDIA=='),DATE '1946-09-23'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (16,'First 16','Last 16',FROM_BASE64('lan0QanIaA/igo2HGkKzB82cKPgAZod4JMN/sV7kQSsMLqzMijItMQFKR1H6eYJosWKm2ajiYByBG8nxP5og5B3aut/Y2n58U86jgoHxoQR4LHOmhCnzjsBLfwZ4wE8BN8iznkWuMihQbZvsAQituLo3zygYKzSZ0V0O+nJBf4OesrS9UW1fwC312k1iB39ELDnZFTuWfca+8nqiv5kolg=='),DATE '1947-09-30'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (17,'First 17','Last 17',FROM_BASE64('NCks7+4E3+XdpeWrBg/0zz2t3KzNGh1hE3uZaXcQewMjBmiujYEP4teH6Sb2awoR55zII2eJHC6hyTcrCVLrTktBm8wqSkve+yxTvY1IIJt5eULLCerZeyl8dRDXpkpIJ3itPvXlsQUToBNhxW2gQqmz+segWsJwbtQSnnGZ+Frn8JiFSz51FCRcYP/eBlogljT9vxxuWkKrL8koRz3+ew=='),DATE '1948-02-04'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (18,'First 18','Last 18',FROM_BASE64('KZyY3e9J6d5G4uuBYa4mLVWaZv8SowusNx4KHrYx5VWF3xLsy/ZuOqRczNDeAitOyXC4lh2t1M8hclCsyxHIW2cUOR9xQnnqWtYA3WrYcFycqJn4hM+ghEAX5OXRVWEQ5lr9op7cSJio2JMawTcR5z3MrNucj0VTBtLTQKxHcW7VeuPARHCBkDCOicr0gQr/pODAUs5ipqv807ZhCV0n7Q=='),DATE '1962-11-10'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (19,'First 19','Last 19',FROM_BASE64('RymWYvEhWXx4AhUQaGoruxL/XgVUnz2vjMqa8yQtFEd8awR7Vzknzl1hpl/kKdCaKSzI9TV6RoD0HZu0U3UTazIh5WjMZYKwDT0ewsh4i5S1EIRzGohMg7l0vUVRtCzWVO5uALxm1mKYp3SczU0ETmQ0t+o1ke13Bz8I1/hyIsj6PnCIvxdOBZVycfKZ64dVxwwB9vYjVoRv5jnEw4K9Kg=='),DATE '1988-10-07'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (20,'First 20','Last 20',FROM_BASE64('+OgGCnKsVaMSILWEr/0wqkPajWcdSx79nDEOqmtCtQiIP7zqZETVKOjgfVYZg3pBzQQHQ9IExYlCvqX+//GxLhegBzKFfpJ6hp6NpKiJ2p6odLfeYVkvP7GdggU5sII5da3ApMebuQDkbYS1fWk8pXdqDIpkWbFG/PTGq+p1IdHRV0tkAEe9NFW2h5y8aO6Oy+zJprq0IX5CYln6zek/gQ=='),DATE '2000-02-29'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (21,'First 21','Last 21',FROM_BASE64('0BPlFBGYZ1w3Snpf3o6PswLXQeFgEE2ehluMDXYeqPjOO+dXN6s3CrS3JUVhejj5kARAoT510bRM4eAY7x5zRBtGQisDkeaeh0d1h/o+NESSX8MPZikMmeltT864xjxwnTd/5/m1oZTSVjVLVewzi6b1MuHcghcHrdgYMy/0f3ivz1DJMH6T4tIIFxg/y8Ueb0qKcFGvnvJlTWuNnMEpdA=='),DATE '1886-08-09'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (22,'First 22','Last 22',FROM_BASE64('K6GpZCoGGMJdF/55vnvqKCfpNyVrSJGMIpvDA8nxlwQFLBqemxUgCFrtAAZx7ERd0ndYXFJOpsRS8+You2lPcaXh/jfGWoZSy/AHLS7vpML7vRzrxKlyuocjaaDEm/wb351dEU3tT8VSOEhFkYk1VvhiFS47Hm5au5E2XXUpuQwHE/6f+FlkoD64wgmdyaOQWaJgJ0Nhg6UHWA0+MJ6AEA=='),DATE '1889-04-03'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (23,'First 23','Last 23',FROM_BASE64('etCS2Mi+5SgbO7VHnr1V+3PHp2ExR+NW0mF5mUhUxitXK4CtS1tbcUzvoSYoVEMhRlT0d1O2qlIyOPayxIB2GfEfhkJpajyPSjyBSEmh8frdKLx9qICQ+Ztwv8jK9JBOJC3VQxooS49ovUff/0W6akc0s9bNevQx8v8d3daklRCKFWYQCSIFcoYZv5+78zwZ8KZHErTXQl2ZW9/zH06Uew=='),DATE '1892-01-21'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (24,'First 24','Last 24',FROM_BASE64('RUq40F7M3XWGARLYX8ZW04hf4L+zW2wkKXf5zH4rqBxG2sacUMpZcK65mmQgj51C8XFcny+4E+ZuGfGVXIi3rsF700SnZVeFdKx1s2WMZJRKvJjbXKyHoaWytT9oUHIGqJw4qXpGh/CKUb9frNWCK5FiUk6iNsE3yMsEMVe+WnG5x+AeGXtWYwW5FtF0TnqUTnXw1lf3QzSdXg+DAvIZQA=='),DATE '1898-02-21'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (25,'First 25','Last 25',FROM_BASE64('HzmgCTWib9uD7oO0qPps+AvNx1o5b38RVsvRGXAMG9uxijG62pDK6gMVwCMt0PvUJNxEpcs0uKmPqx8eF66+V++VKjpKI8CerlxrEi7oOq344tAwRYK941HqXgBN9nQB1X33cwIufEwqq5nU85HGlGFm6O8EEGQb6+n5hXItCuMJAZWXkYiK1UW7H3zLDW4xJp+ijA35TfcHusirUaH8WQ=='),DATE '1911-12-15'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (26,'First 26','Last 26',FROM_BASE64('/j6wAEIFHAARYGDM5RDQYihb8QSfQGvZA7O2wDL2Tag1iY+twDM6DcFtvKt3PFmaFKYlB1mNkc129CWAW7PSHIIKDIVTDeI4PSHWy6DwCrYBDfn/ARmP7tRFqtM/RzFQKVQS3BvKPTAv3dNTjIWto9C0FFv7TyguTv0aPVkboxzQpJnR2FfjNG05/Uy2J67w+ngspZiUvj3aRQI/s/k8qQ=='),DATE '1912-07-01'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (27,'First 27','Last 27',FROM_BASE64('OTmvVaLjJI/8/xL6/W2dYhmAnhnB8SlzdnU1VxV/Z/FAmYp+4rALgjjq6KrQNpZ7oF2Iw+MF6bWbdQO2I3uqiH9nwCGflrq1Tjf8YkqwfZvYJ/RAorsd9WHHK74+5XpGYB3hgcPjeZ5vZg6cBeHnJbAlxEKTiBpnGvOoQqBm5bQQ1sLKsLanvBcMEsGyT98BlEZIHYeubPOELbLmhR/SWQ=='),DATE '1939-05-17'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (28,'First 28','Last 28',FROM_BASE64('OVlneKkb0DxkcCvpsKAVCE6hTutOrOBk+lF/iNCh/YMFQbIiVdZyBWNhpo8yfDKicgL50n3jjPNvEPX+I/RdKG82uM/bF8v/SWkrpzxXX9HMN4Ng9kErouVTK7s0Gf1eBHQcF4WrIbnCuN+SxWQxJhD6LCX02xw0JxXyqqRBUEmGYEbTmr/vfKZgGfj0UWYdvxbFX8bO+6vDq9NK9wTAKA=='),DATE '1946-10-18'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (29,'First 29','Last 29',FROM_BASE64('BUClPKVhaV2/DkWtL/JwWVIlqUjF1bOhCNQGM0xz/pbgxsE1jcLYNoMNVFbVPhwmEIyGiqAGOyUzfyyVVNHfPY0Hrbw2LlHXbm7VymFvxqlRNufrDnQrA6ZzsZECwkYHNtrOVcSp0rdSToNDzKdViSDPwIEzELtCKFWcycDYHF5AZzJDU1AV7gQQZHi8h8oJfncvCP9wLnXy/YpCjnDClQ=='),DATE '1956-12-23'); +INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) VALUES (30,'First 30','Last 30',FROM_BASE64('1JJ36b41BmeXie2RZ8TykjUUzyJfWV0ZoRShMybsVYebCanPaTb6uUiTFT4MDP1ise6jjN2STpZ49aHL8fOj02vzq1TsAVOznAScd2cbLDdnfSjVeABZRFKKIslpBNUSEP+4sgkoRi7D+ojXsNYVl+D+hSEB1mPn0brbV6mMQUWeryiUFf9ock9hYqa3BbhDEGFjkH0WcnRrvDHZgGAIVw=='),DATE '1988-05-29'); +COMMIT; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 30 AS EXPECTED +FROM Singers; + +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (1,1,"Album 1 1",980045); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (2,2,"Album 2 2",667788); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (3,3,"Album 3 3",908791); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (4,4,"Album 4 4",690335); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (5,5,"Album 5 5",133041); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (6,6,"Album 6 6",505292); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (7,7,"Album 7 7",91969); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (8,8,"Album 8 8",289965); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (9,9,"Album 9 9",78176); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (10,10,"Album 10 10",485664); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (11,11,"Album 11 11",972680); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (12,12,"Album 12 12",893680); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (13,13,"Album 13 13",892138); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (14,14,"Album 14 14",449562); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (15,15,"Album 15 15",150968); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (16,16,"Album 16 16",580377); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (17,17,"Album 17 17",763081); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (18,18,"Album 18 18",203427); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (19,19,"Album 19 19",995368); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (20,20,"Album 20 20",29900); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (21,21,"Album 21 21",723728); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (22,22,"Album 22 22",540582); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (23,23,"Album 23 23",784245); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (24,24,"Album 24 24",614788); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (25,25,"Album 25 25",275649); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (26,26,"Album 26 26",970898); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (27,27,"Album 27 27",409289); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (28,28,"Album 28 28",766560); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (29,29,"Album 29 29",32414); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (30,30,"Album 30 30",457957); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (1,31,"Album 1 31",52546); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (2,32,"Album 2 32",412424); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (3,33,"Album 3 33",568496); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (4,34,"Album 4 34",353491); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (5,35,"Album 5 35",489951); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (6,36,"Album 6 36",75938); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (7,37,"Album 7 37",460461); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (8,38,"Album 8 38",642042); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (9,39,"Album 9 39",282872); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (10,40,"Album 10 40",521496); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (11,41,"Album 11 41",98126); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (12,42,"Album 12 42",535113); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (13,43,"Album 13 43",957625); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (14,44,"Album 14 44",667630); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (15,45,"Album 15 45",236968); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (16,46,"Album 16 46",445647); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (17,47,"Album 17 47",446396); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (18,48,"Album 18 48",852859); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (19,49,"Album 19 49",404105); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (20,50,"Album 20 50",384439); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (21,51,"Album 21 51",440468); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (22,52,"Album 22 52",455384); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (23,53,"Album 23 53",210756); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (24,54,"Album 24 54",849113); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (25,55,"Album 25 55",63969); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (26,56,"Album 26 56",277122); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (27,57,"Album 27 57",350063); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (28,58,"Album 28 58",359473); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (29,59,"Album 29 59",209825); +INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (30,60,"Album 30 60",84543); + +COMMIT; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 60 AS EXPECTED +FROM Albums; + +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,42,1,"Song 12 42 1",387,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,12,2,"Song 12 12 2",202,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,59,3,"Song 29 59 3",160,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,4,"Song 23 23 4",255,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,54,5,"Song 24 54 5",436,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (28,58,6,"Song 28 58 6",121,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,7,"Song 27 27 7",319,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,24,8,"Song 24 24 8",213,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,49,9,"Song 19 49 9",280,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (17,47,10,"Song 17 47 10",253,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (6,6,11,"Song 6 6 11",321,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,42,12,"Song 12 42 12",124,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (25,25,13,"Song 25 25 13",449,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,24,14,"Song 24 24 14",438,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,5,15,"Song 5 5 15",378,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,39,16,"Song 9 39 16",202,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (20,50,17,"Song 20 50 17",452,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (7,37,18,"Song 7 37 18",420,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,8,19,"Song 8 8 19",318,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,35,20,"Song 5 35 20",347,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,3,21,"Song 3 3 21",377,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,15,22,"Song 15 15 22",314,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,49,23,"Song 19 49 23",199,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (20,20,24,"Song 20 20 24",266,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,45,25,"Song 15 45 25",433,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (14,44,26,"Song 14 44 26",482,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,19,27,"Song 19 19 27",345,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,43,28,"Song 13 43 28",159,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (18,48,29,"Song 18 48 29",350,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,13,30,"Song 13 13 30",131,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,9,31,"Song 9 9 31",183,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,13,32,"Song 13 13 32",193,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,24,33,"Song 24 24 33",378,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,60,34,"Song 30 60 34",270,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,43,35,"Song 13 43 35",375,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,36,"Song 27 27 36",219,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (20,50,37,"Song 20 50 37",314,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (18,48,38,"Song 18 48 38",416,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,51,39,"Song 21 51 39",330,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (1,31,40,"Song 1 31 40",376,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,5,41,"Song 5 5 41",398,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,45,42,"Song 15 45 42",466,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,24,43,"Song 24 24 43",384,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,19,44,"Song 19 19 44",472,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,45,45,"Song 15 45 45",246,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,33,46,"Song 3 33 46",412,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,47,"Song 23 23 47",159,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,60,48,"Song 30 60 48",290,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,19,49,"Song 19 19 49",446,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (16,16,50,"Song 16 16 50",485,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (4,4,51,"Song 4 4 51",185,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,38,52,"Song 8 38 52",349,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,54,53,"Song 24 54 53",301,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,35,54,"Song 5 35 54",206,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,30,55,"Song 30 30 55",250,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,42,56,"Song 12 42 56",146,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,30,57,"Song 30 30 57",416,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (26,56,58,"Song 26 56 58",244,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (20,50,59,"Song 20 50 59",356,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (7,7,60,"Song 7 7 60",234,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,19,61,"Song 19 19 61",412,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,43,62,"Song 13 43 62",161,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,5,63,"Song 5 5 63",300,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (1,31,64,"Song 1 31 64",307,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (4,4,65,"Song 4 4 65",197,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,54,66,"Song 24 54 66",180,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,3,67,"Song 3 3 67",156,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (14,44,68,"Song 14 44 68",184,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,51,69,"Song 21 51 69",486,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,49,70,"Song 19 49 70",212,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,39,71,"Song 9 39 71",452,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,53,72,"Song 23 53 72",425,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (11,41,73,"Song 11 41 73",316,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,8,74,"Song 8 8 74",395,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,9,75,"Song 9 9 75",189,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (2,2,76,"Song 2 2 76",354,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,53,77,"Song 23 53 77",137,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,15,78,"Song 15 15 78",176,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,60,79,"Song 30 60 79",224,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (14,44,80,"Song 14 44 80",305,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,81,"Song 27 27 81",432,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (18,18,82,"Song 18 18 82",357,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (10,10,83,"Song 10 10 83",187,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,42,84,"Song 12 42 84",461,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,8,85,"Song 8 8 85",434,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (1,31,86,"Song 1 31 86",436,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (11,41,87,"Song 11 41 87",469,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,13,88,"Song 13 13 88",452,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (4,34,89,"Song 4 34 89",309,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,21,90,"Song 21 21 90",226,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (6,36,91,"Song 6 36 91",257,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,92,"Song 27 27 92",251,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,39,93,"Song 9 39 93",325,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,30,94,"Song 30 30 94",122,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,59,95,"Song 29 59 95",207,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (1,1,96,"Song 1 1 96",318,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (4,4,97,"Song 4 4 97",353,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,98,"Song 23 23 98",450,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,12,99,"Song 12 12 99",323,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,24,100,"Song 24 24 100",397,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,101,"Song 27 27 101",296,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,59,102,"Song 29 59 102",349,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (17,47,103,"Song 17 47 103",438,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,5,104,"Song 5 5 104",388,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (26,56,105,"Song 26 56 105",425,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (22,52,106,"Song 22 52 106",154,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,107,"Song 23 23 107",213,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,38,108,"Song 8 38 108",276,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,39,109,"Song 9 39 109",417,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (9,9,110,"Song 9 9 110",299,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (22,52,111,"Song 22 52 111",476,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,21,112,"Song 21 21 112",225,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,113,"Song 23 23 113",303,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (7,7,114,"Song 7 7 114",291,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,38,115,"Song 8 38 115",276,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (14,44,116,"Song 14 44 116",238,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,57,117,"Song 27 57 117",188,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (28,28,118,"Song 28 28 118",372,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (15,15,119,"Song 15 15 119",258,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,21,120,"Song 21 21 120",308,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,59,121,"Song 29 59 121",319,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (28,58,122,"Song 28 58 122",453,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (7,7,123,"Song 7 7 123",198,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (4,4,124,"Song 4 4 124",435,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,27,125,"Song 27 27 125",475,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (30,30,126,"Song 30 30 126",395,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,51,127,"Song 21 51 127",454,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,29,128,"Song 29 29 128",376,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (27,57,129,"Song 27 57 129",396,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,53,130,"Song 23 53 130",458,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (6,36,131,"Song 6 36 131",289,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (29,29,132,"Song 29 29 132",207,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (25,55,133,"Song 25 55 133",280,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,3,134,"Song 3 3 134",432,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (5,35,135,"",304,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,3,136,"",392,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,12,137,"",393,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (13,13,138,"",382,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (18,48,139,"",447,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (17,17,140,"",182,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (23,23,141,"",266,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (21,51,142,"",383,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (3,3,143,"",439,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (25,25,144,"",454,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (12,12,145,"",179,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (19,19,146,"",422,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (24,54,147,"",478,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (8,38,148,"",233,'Unknown'); +INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (6,6,149,"",245,'Unknown'); + +COMMIT; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 149 AS EXPECTED +FROM Songs; + +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (1,1,DATE '2003-06-19',TIMESTAMP '2003-06-19T12:30:05Z',TIMESTAMP '2003-06-19T18:57:15Z',[11,93,140,923]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (2,18,DATE '2004-01-25',TIMESTAMP '2004-01-25T14:58:28Z',TIMESTAMP '2004-01-26T01:10:52Z',[18,51,101,812]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (3,21,DATE '2005-03-15',TIMESTAMP '2005-03-15T18:14:50Z',TIMESTAMP '2005-03-16T02:21:28Z',[23,26,107,721]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (4,16,DATE '2009-05-09',TIMESTAMP '2009-05-09T05:22:34Z',TIMESTAMP '2009-05-09T15:28:28Z',[18,70,150,297]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (5,11,DATE '2001-01-07',TIMESTAMP '2001-01-07T18:37:33Z',TIMESTAMP '2001-01-07T21:22:17Z',[20,55,185,672]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (6,25,DATE '2015-11-19',TIMESTAMP '2015-11-19T22:47:42Z',TIMESTAMP '2015-11-20T02:54:01Z',[12,73,150,833]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (7,26,DATE '2012-10-06',TIMESTAMP '2012-10-06T10:58:43Z',TIMESTAMP '2012-10-06T15:35:40Z',[8,83,199,625]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (8,8,DATE '2001-09-26',TIMESTAMP '2001-09-26T06:41:20Z',TIMESTAMP '2001-09-26T16:38:35Z',[19,87,192,912]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (9,27,DATE '2016-11-24',TIMESTAMP '2016-11-24T20:00:48Z',TIMESTAMP '2016-11-24T23:03:07Z',[20,84,134,885]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (10,30,DATE '2017-05-05',TIMESTAMP '2017-05-05T12:44:05Z',TIMESTAMP '2017-05-05T23:06:55Z',[17,44,177,997]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (11,7,DATE '2018-06-07',TIMESTAMP '2018-06-07T07:03:11Z',TIMESTAMP '2018-06-07T08:21:41Z',[10,73,182,287]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (12,22,DATE '2009-01-07',TIMESTAMP '2009-01-07T23:22:11Z',TIMESTAMP '2009-01-08T08:34:18Z',[22,59,150,983]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (13,16,DATE '2013-06-28',TIMESTAMP '2013-06-28T14:59:25Z',TIMESTAMP '2013-06-28T22:32:11Z',[17,41,129,433]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (14,11,DATE '2005-08-19',TIMESTAMP '2005-08-19T01:11:28Z',TIMESTAMP '2005-08-19T01:30:30Z',[18,49,110,590]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (15,18,DATE '2001-11-26',TIMESTAMP '2001-11-26T15:55:31Z',TIMESTAMP '2001-11-26T20:52:13Z',[18,51,132,854]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (16,26,DATE '2009-01-04',TIMESTAMP '2009-01-04T03:09:11Z',TIMESTAMP '2009-01-04T12:02:14Z',[5,37,146,344]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (17,20,DATE '2012-09-28',TIMESTAMP '2012-09-28T00:45:00Z',TIMESTAMP '2012-09-28T02:10:39Z',[15,89,185,480]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (18,24,DATE '2004-09-06',TIMESTAMP '2004-09-06T09:55:40Z',TIMESTAMP '2004-09-06T18:10:32Z',[23,51,113,244]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (19,21,DATE '2010-11-18',TIMESTAMP '2010-11-18T09:59:17Z',TIMESTAMP '2010-11-18T17:13:12Z',[14,69,164,218]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (20,29,DATE '2010-12-24',TIMESTAMP '2010-12-24T04:21:25Z',TIMESTAMP '2010-12-24T06:10:08Z',[20,34,166,573]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (21,3,DATE '2000-05-14',TIMESTAMP '2000-05-14T13:49:08Z',TIMESTAMP '2000-05-14T14:39:25Z',[21,67,136,779]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (22,18,DATE '2000-05-14',TIMESTAMP '2000-05-14T00:23:23Z',TIMESTAMP '2000-05-14T01:20:04Z',[21,91,111,749]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (23,26,DATE '2015-05-04',TIMESTAMP '2015-05-04T10:39:46Z',TIMESTAMP '2015-05-04T19:21:45Z',[24,91,128,559]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (24,16,DATE '2012-08-18',TIMESTAMP '2012-08-18T08:47:12Z',TIMESTAMP '2012-08-18T09:35:03Z',[19,44,136,281]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (25,4,DATE '2000-03-16',TIMESTAMP '2000-03-16T10:15:15Z',TIMESTAMP '2000-03-16T12:29:53Z',[22,28,111,948]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (26,4,DATE '2002-11-20',TIMESTAMP '2002-11-20T16:28:19Z',TIMESTAMP '2002-11-20T17:56:10Z',[7,70,141,517]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (27,23,DATE '2000-08-09',TIMESTAMP '2000-08-09T04:30:51Z',TIMESTAMP '2000-08-09T15:27:15Z',[13,98,156,230]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (28,16,DATE '2000-10-15',TIMESTAMP '2000-10-15T04:12:39Z',TIMESTAMP '2000-10-15T14:07:05Z',[8,39,160,455]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (29,22,DATE '2003-03-25',TIMESTAMP '2003-03-25T17:21:56Z',TIMESTAMP '2003-03-25T19:18:25Z',[17,70,148,681]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (30,15,DATE '2008-11-11',TIMESTAMP '2008-11-11T22:56:07Z',TIMESTAMP '2008-11-12T09:33:48Z',[24,47,175,901]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (31,7,DATE '2018-05-22',TIMESTAMP '2018-05-22T20:54:59Z',TIMESTAMP '2018-05-23T02:52:28Z',[13,34,177,804]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (32,30,DATE '2000-04-03',TIMESTAMP '2000-04-03T13:54:10Z',TIMESTAMP '2000-04-03T15:57:02Z',[16,48,137,249]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (33,23,DATE '2003-12-24',TIMESTAMP '2003-12-24T22:22:00Z',TIMESTAMP '2003-12-25T06:09:40Z',[15,36,131,922]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (34,12,DATE '2012-06-23',TIMESTAMP '2012-06-23T18:15:30Z',TIMESTAMP '2012-06-24T03:46:17Z',[25,31,160,564]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (35,5,DATE '2017-12-15',TIMESTAMP '2017-12-15T09:43:38Z',TIMESTAMP '2017-12-15T17:18:28Z',[22,31,177,868]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (36,20,DATE '2012-12-21',TIMESTAMP '2012-12-21T08:28:14Z',TIMESTAMP '2012-12-21T11:34:59Z',[25,62,143,437]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (37,19,DATE '2014-07-07',TIMESTAMP '2014-07-07T22:01:35Z',TIMESTAMP '2014-07-08T04:39:37Z',[8,31,184,784]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (38,15,DATE '2012-07-26',TIMESTAMP '2012-07-26T09:45:35Z',TIMESTAMP '2012-07-26T13:03:53Z',[19,79,140,908]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (39,24,DATE '2014-03-19',TIMESTAMP '2014-03-19T07:52:25Z',TIMESTAMP '2014-03-19T11:47:01Z',[11,90,141,978]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (40,4,DATE '2015-08-26',TIMESTAMP '2015-08-26T20:51:25Z',TIMESTAMP '2015-08-27T07:06:46Z',[15,94,195,510]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (41,24,DATE '2016-04-11',TIMESTAMP '2016-04-11T08:59:07Z',TIMESTAMP '2016-04-11T13:23:30Z',[15,51,173,233]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (42,18,DATE '2005-03-19',TIMESTAMP '2005-03-19T15:45:04Z',TIMESTAMP '2005-03-19T16:28:42Z',[19,31,188,546]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (43,7,DATE '2001-01-04',TIMESTAMP '2001-01-04T11:02:16Z',TIMESTAMP '2001-01-04T11:32:21Z',[20,37,133,958]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (44,5,DATE '2015-12-24',TIMESTAMP '2015-12-24T06:49:48Z',TIMESTAMP '2015-12-24T14:46:46Z',[12,61,175,233]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (45,12,DATE '2011-08-24',TIMESTAMP '2011-08-24T03:45:46Z',TIMESTAMP '2011-08-24T06:13:10Z',[18,38,169,913]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (46,16,DATE '2017-03-04',TIMESTAMP '2017-03-04T04:01:04Z',TIMESTAMP '2017-03-04T13:44:38Z',[21,79,119,839]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (47,18,DATE '2009-05-19',TIMESTAMP '2009-05-19T23:10:52Z',TIMESTAMP '2009-05-20T04:02:01Z',[25,79,151,357]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (48,22,DATE '2003-10-03',TIMESTAMP '2003-10-03T14:10:24Z',TIMESTAMP '2003-10-03T17:35:09Z',[18,60,140,450]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (49,9,DATE '2003-03-07',TIMESTAMP '2003-03-07T22:09:59Z',TIMESTAMP '2003-03-08T08:28:29Z',[22,41,122,726]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (50,9,DATE '2015-07-12',TIMESTAMP '2015-07-12T07:43:51Z',TIMESTAMP '2015-07-12T12:45:20Z',[18,67,126,474]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (51,12,DATE '2014-11-05',TIMESTAMP '2014-11-05T19:03:00Z',TIMESTAMP '2014-11-06T05:27:07Z',[19,43,125,865]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (52,6,DATE '2016-07-25',TIMESTAMP '2016-07-25T14:39:28Z',TIMESTAMP '2016-07-26T00:36:03Z',[6,74,192,344]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (53,13,DATE '2005-08-02',TIMESTAMP '2005-08-02T16:06:47Z',TIMESTAMP '2005-08-02T17:13:41Z',[5,52,192,977]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (54,18,DATE '2010-01-25',TIMESTAMP '2010-01-25T07:34:54Z',TIMESTAMP '2010-01-25T16:29:11Z',[24,85,181,304]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (55,14,DATE '2012-05-20',TIMESTAMP '2012-05-20T13:15:12Z',TIMESTAMP '2012-05-20T17:40:09Z',[15,43,104,665]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (56,3,DATE '2013-09-08',TIMESTAMP '2013-09-08T19:53:42Z',TIMESTAMP '2013-09-08T22:32:52Z',[14,81,129,354]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (57,27,DATE '2003-07-18',TIMESTAMP '2003-07-18T23:11:24Z',TIMESTAMP '2003-07-19T03:29:46Z',[21,85,188,854]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (58,27,DATE '2001-04-10',TIMESTAMP '2001-04-10T08:36:49Z',TIMESTAMP '2001-04-10T16:17:57Z',[17,86,161,438]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (59,2,DATE '2002-07-02',TIMESTAMP '2002-07-02T17:32:20Z',TIMESTAMP '2002-07-03T01:59:33Z',[23,59,164,357]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (60,28,DATE '2000-11-24',TIMESTAMP '2000-11-24T12:53:25Z',TIMESTAMP '2000-11-24T22:37:53Z',[22,47,161,739]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (61,12,DATE '2017-07-04',TIMESTAMP '2017-07-04T21:02:01Z',TIMESTAMP '2017-07-05T03:57:29Z',[16,88,179,478]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (62,3,DATE '2015-10-07',TIMESTAMP '2015-10-07T17:58:42Z',TIMESTAMP '2015-10-07T21:04:38Z',[21,44,155,381]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (63,23,DATE '2005-05-03',TIMESTAMP '2005-05-03T15:08:10Z',TIMESTAMP '2005-05-03T20:58:30Z',[20,43,111,824]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (64,24,DATE '2012-12-09',TIMESTAMP '2012-12-09T02:52:09Z',TIMESTAMP '2012-12-09T08:01:11Z',[18,87,106,997]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (65,30,DATE '2004-03-01',TIMESTAMP '2004-03-01T07:09:06Z',TIMESTAMP '2004-03-01T07:49:32Z',[14,26,195,895]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (66,24,DATE '2007-05-19',TIMESTAMP '2007-05-19T10:20:57Z',TIMESTAMP '2007-05-19T15:21:09Z',[18,54,179,238]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (67,16,DATE '2016-01-06',TIMESTAMP '2016-01-06T21:32:20Z',TIMESTAMP '2016-01-07T02:31:32Z',[20,61,120,652]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (68,2,DATE '2007-10-26',TIMESTAMP '2007-10-26T03:37:22Z',TIMESTAMP '2007-10-26T10:02:36Z',[11,65,151,537]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (69,2,DATE '2018-08-11',TIMESTAMP '2018-08-11T01:33:38Z',TIMESTAMP '2018-08-11T07:39:21Z',[10,98,105,621]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (70,23,DATE '2012-07-06',TIMESTAMP '2012-07-06T01:02:23Z',TIMESTAMP '2012-07-06T05:04:16Z',[14,44,172,953]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (71,7,DATE '2006-01-24',TIMESTAMP '2006-01-24T15:32:10Z',TIMESTAMP '2006-01-24T17:40:43Z',[9,58,150,713]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (72,8,DATE '2002-11-06',TIMESTAMP '2002-11-06T05:58:03Z',TIMESTAMP '2002-11-06T07:43:24Z',[25,36,193,213]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (73,10,DATE '2003-11-24',TIMESTAMP '2003-11-24T17:39:10Z',TIMESTAMP '2003-11-25T03:17:36Z',[8,55,200,352]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (74,16,DATE '2007-11-03',TIMESTAMP '2007-11-03T05:49:12Z',TIMESTAMP '2007-11-03T16:34:16Z',[21,50,114,820]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (75,4,DATE '2009-05-06',TIMESTAMP '2009-05-06T18:52:07Z',TIMESTAMP '2009-05-06T21:10:02Z',[16,42,101,281]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (76,1,DATE '2012-12-03',TIMESTAMP '2012-12-03T06:01:05Z',TIMESTAMP '2012-12-03T06:45:00Z',[24,60,140,292]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (77,1,DATE '2016-11-26',TIMESTAMP '2016-11-26T01:19:27Z',TIMESTAMP '2016-11-26T07:20:17Z',[19,31,123,214]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (78,9,DATE '2018-05-21',TIMESTAMP '2018-05-21T00:14:43Z',TIMESTAMP '2018-05-21T08:43:35Z',[7,28,115,634]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (79,14,DATE '2013-11-20',TIMESTAMP '2013-11-20T08:54:47Z',TIMESTAMP '2013-11-20T10:44:54Z',[18,39,155,328]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (80,17,DATE '2015-10-11',TIMESTAMP '2015-10-11T23:41:17Z',TIMESTAMP '2015-10-12T02:42:48Z',[16,94,102,894]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (81,23,DATE '2011-08-07',TIMESTAMP '2011-08-07T19:33:01Z',TIMESTAMP '2011-08-07T21:51:53Z',[23,90,134,370]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (82,7,DATE '2010-04-10',TIMESTAMP '2010-04-10T13:22:08Z',TIMESTAMP '2010-04-10T17:59:08Z',[18,68,121,303]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (83,27,DATE '2001-07-08',TIMESTAMP '2001-07-08T20:19:54Z',TIMESTAMP '2001-07-08T22:46:15Z',[18,86,148,746]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (84,6,DATE '2017-09-02',TIMESTAMP '2017-09-02T10:29:03Z',TIMESTAMP '2017-09-02T13:06:41Z',[12,85,138,471]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (85,1,DATE '2013-11-02',TIMESTAMP '2013-11-02T04:01:03Z',TIMESTAMP '2013-11-02T14:08:47Z',[9,65,111,583]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (86,22,DATE '2004-04-03',TIMESTAMP '2004-04-03T19:13:48Z',TIMESTAMP '2004-04-04T05:59:31Z',[19,72,105,908]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (87,2,DATE '2012-02-26',TIMESTAMP '2012-02-26T22:52:21Z',TIMESTAMP '2012-02-27T02:55:24Z',[16,75,129,740]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (88,9,DATE '2017-09-17',TIMESTAMP '2017-09-17T11:28:49Z',TIMESTAMP '2017-09-17T12:13:03Z',[24,77,182,755]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (89,11,DATE '2011-03-28',TIMESTAMP '2011-03-28T13:05:23Z',TIMESTAMP '2011-03-28T16:32:29Z',[22,96,174,731]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (90,21,DATE '2006-12-12',TIMESTAMP '2006-12-12T20:44:10Z',TIMESTAMP '2006-12-12T22:10:34Z',[15,68,166,616]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (91,27,DATE '2010-08-18',TIMESTAMP '2010-08-18T05:49:35Z',TIMESTAMP '2010-08-18T12:58:36Z',[12,84,157,369]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (92,2,DATE '2003-02-03',TIMESTAMP '2003-02-03T11:19:43Z',TIMESTAMP '2003-02-03T22:10:42Z',[25,59,140,939]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (93,5,DATE '2016-01-04',TIMESTAMP '2016-01-04T08:10:26Z',TIMESTAMP '2016-01-04T13:08:30Z',[5,90,163,272]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (94,3,DATE '2018-04-20',TIMESTAMP '2018-04-20T07:19:52Z',TIMESTAMP '2018-04-20T17:41:01Z',[5,59,109,854]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (95,19,DATE '2016-10-09',TIMESTAMP '2016-10-09T17:02:59Z',TIMESTAMP '2016-10-09T17:37:27Z',[6,35,176,442]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (96,9,DATE '2007-06-12',TIMESTAMP '2007-06-12T16:50:12Z',TIMESTAMP '2007-06-12T19:27:30Z',[7,49,169,729]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (97,29,DATE '2012-11-25',TIMESTAMP '2012-11-25T20:40:30Z',TIMESTAMP '2012-11-25T21:29:50Z',[12,35,128,269]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (98,11,DATE '2013-10-22',TIMESTAMP '2013-10-22T03:26:36Z',TIMESTAMP '2013-10-22T06:42:42Z',[14,49,148,726]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (99,10,DATE '2006-05-10',TIMESTAMP '2006-05-10T05:49:43Z',TIMESTAMP '2006-05-10T07:12:18Z',[5,67,131,360]); +INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (100,18,DATE '2015-02-15',TIMESTAMP '2015-02-15T01:18:05Z',TIMESTAMP '2015-02-15T04:19:27Z',[11,38,127,909]); + +COMMIT; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 100 AS EXPECTED +FROM Concerts; + +COMMIT; + +# Switch to read-only mode +SET READONLY = TRUE; + +# Do a query that should also generate a read timestamp +@EXPECT RESULT_SET 'NUMBER_OF_SINGERS',30 +SELECT COUNT(*) AS NUMBER_OF_SINGERS +FROM Singers; + +# Check that the read-timestamp is there +@EXPECT RESULT_SET 'READ_TIMESTAMP' +SHOW VARIABLE READ_TIMESTAMP; + +-- End the read-only transaction and try to get a commit timestamp. +COMMIT; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Try to do an update in read-only mode +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE Singers SET FirstName='FirstName' WHERE SingerId=1; + +-- Verify that it was not changed +@EXPECT RESULT_SET 'FirstName','First 1' +SELECT FirstName +FROM Singers +WHERE SingerId=1; + +COMMIT; + +-- Switch to autocommit and read/write mode +SET READONLY = FALSE; +SET AUTOCOMMIT = TRUE; + +-- Try to insert a record that already exists +@EXPECT EXCEPTION ALREADY_EXISTS +INSERT INTO Singers (SingerId, FirstName, LastName) +SELECT SingerId, FirstName, LastName +FROM Singers +WHERE SingerId=1; + +-- Ensure there was no commit timestamp +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +-- Delete a record that will also cascade to other records +-- First verify the actual number of records +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED +FROM Albums +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 4 AS EXPECTED +FROM Songs +WHERE SingerId=1; + +-- Even though the delete cascades to several other records, the update count is returned as 1 +@EXPECT UPDATE_COUNT 1 +DELETE FROM Singers WHERE SingerId=1; + +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Albums +WHERE SingerId=1; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Songs +WHERE SingerId=1; + +-- Switch to transactional mode +SET AUTOCOMMIT = FALSE; + +-- Delete a record that will also cascade to other records and then rollback +-- First verify the actual number of records +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED +FROM Albums +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Songs +WHERE SingerId=2; + +-- Even though the delete cascades to several other records, the update count is returned as 1 +@EXPECT UPDATE_COUNT 1 +DELETE FROM Singers WHERE SingerId=2; + +-- Verify that the change is visible inside the transaction +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Albums +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Songs +WHERE SingerId=2; + +-- Rollback and verify that no changes were persisted +ROLLBACK; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Singers +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 2 AS EXPECTED +FROM Albums +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM Songs +WHERE SingerId=2; + +-- End transaction +COMMIT; + +-- Switch to autocommit and partitioned_non_atomic mode and redo the delete +SET AUTOCOMMIT = TRUE; +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; + +@EXPECT UPDATE_COUNT 1 +DELETE FROM Singers WHERE SingerId=2; + +-- There should be no commit timestamp for PARTITIONED_NON_ATOMIC +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Singers +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Albums +WHERE SingerId=2; + +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Songs +WHERE SingerId=2; From 6d1429130584f9b8e967a4df9bc44193e3fb7612 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 21 Aug 2019 11:46:37 -0400 Subject: [PATCH 0020/1979] Fix build (#6116) * Fix build * Fix build --- .../google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java | 2 +- .../com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 5bc8945173c6..29b0b054d5e9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -37,7 +37,7 @@ public void testRunScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(); try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), SCRIPT_FILE, SqlScriptVerifier.class, true); + JdbcGenericConnection.of(connection), SCRIPT_FILE, SqlScriptVerifier.class); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java index 07cee877506d..c8a0b897767c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java @@ -52,7 +52,7 @@ public class ITSqlMusicScriptTest extends ITAbstractSpannerTest { public void test01_RunScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(); try (GenericConnection connection = SpannerGenericConnection.of(createConnection())) { - verifier.verifyStatementsInFile(connection, SCRIPT_FILE, SqlScriptVerifier.class, true); + verifier.verifyStatementsInFile(connection, SCRIPT_FILE, SqlScriptVerifier.class); } } From e6e582e24abeaa100b4b40e2c91084da1bef4a80 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 22 Aug 2019 13:14:03 -0700 Subject: [PATCH 0021/1979] Release v0.106.0 (#6140) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0162399a4e64..335e966c3b72 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 0.2.0 + 0.3.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:0.2.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:0.3.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.2.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.3.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3dafde9e15de..2373443ebb21 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.2.1-SNAPSHOT + 0.3.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.105.1-alpha-SNAPSHOT + 0.106.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.32.1-SNAPSHOT + 1.33.0 test-jar test From f8090244f3c7e16d5820e6794dd9cc7f61617c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 15:38:32 +0200 Subject: [PATCH 0022/1979] change assert to check for >= as the exact number of aborts is unknown (#6159) --- .../google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java index fb01e97bdd75..159ca7e6c9ef 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java @@ -624,7 +624,7 @@ public void testAbortWithUnseenConcurrentInsert() { interceptor.setOnlyInjectOnce(true); int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted; connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted, is(equalTo(currentRetryCount + 1))); + assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= currentRetryCount + 1, is(true)); // Consume the rest of the result set. The insert by the other transaction should now be // included in the result set as the transaction retried. Although this means that the result // is different after a retry, it is not different as seen by the user, as the user didn't From f3c4b873f8e194930f130d05c6b781d5fe857181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 15:39:40 +0200 Subject: [PATCH 0023/1979] spanner-jdbc: Add tests for JdbcStatement (#6158) * throw exception when called with RETURN_GENERATED_KEYS * add tests for JdbcStatement --- .../cloud/spanner/jdbc/JdbcConnection.java | 2 +- .../cloud/spanner/jdbc/JdbcStatement.java | 6 ++ .../cloud/spanner/jdbc/JdbcStatementTest.java | 68 +++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 0114eb0a32da..8d5d55bcc25a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -40,7 +40,7 @@ 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"; - private static final String ONLY_NO_GENERATED_KEYS = "Only NO_GENERATED_KEYS are supported"; + static final String ONLY_NO_GENERATED_KEYS = "Only NO_GENERATED_KEYS are supported"; private Map> typeMap = new HashMap<>(); JdbcConnection(String connectionUrl, ConnectionOptions options) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 54488c6ea3cc..e87558e68e92 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -329,6 +329,9 @@ public ResultSet getGeneratedKeys() throws SQLException { @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); } @@ -347,6 +350,9 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { @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); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index bc563652050f..648261efdf26 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -21,6 +21,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -28,10 +29,12 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.cloud.spanner.jdbc.StatementResult.ResultType; 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; @@ -50,6 +53,7 @@ public class JdbcStatementTest { @Rule public final ExpectedException thrown = ExpectedException.none(); private static final String SELECT = "SELECT 1"; private static final String UPDATE = "UPDATE FOO SET BAR=1 WHERE BAZ=2"; + private static final String LARGE_UPDATE = "UPDATE FOO SET BAR=1 WHERE 1=1"; private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; @Rule public final ExpectedException expected = ExpectedException.none(); @@ -71,6 +75,12 @@ private JdbcStatement createStatement() { when(updateResult.getUpdateCount()).thenReturn(1L); when(spanner.execute(com.google.cloud.spanner.Statement.of(UPDATE))).thenReturn(updateResult); + StatementResult largeUpdateResult = mock(StatementResult.class); + when(largeUpdateResult.getResultType()).thenReturn(ResultType.UPDATE_COUNT); + when(largeUpdateResult.getUpdateCount()).thenReturn(Integer.MAX_VALUE + 1L); + when(spanner.execute(com.google.cloud.spanner.Statement.of(LARGE_UPDATE))) + .thenReturn(largeUpdateResult); + StatementResult ddlResult = mock(StatementResult.class); when(ddlResult.getResultType()).thenReturn(ResultType.NO_RESULT); when(spanner.execute(com.google.cloud.spanner.Statement.of(DDL))).thenReturn(ddlResult); @@ -181,6 +191,14 @@ public void testExecuteWithUpdateStatement() throws SQLException { assertThat(res, is(false)); assertThat(statement.getResultSet(), is(nullValue())); assertThat(statement.getUpdateCount(), is(equalTo(1))); + try { + assertThat(statement.execute(LARGE_UPDATE), is(false)); + assertThat(statement.getResultSet(), is(nullValue())); + statement.getUpdateCount(); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode(), is(equalTo(Code.OUT_OF_RANGE))); + } } @Test @@ -192,6 +210,20 @@ public void testExecuteWithDdlStatement() throws SQLException { assertThat(statement.getUpdateCount(), is(equalTo(JdbcConstants.STATEMENT_NO_RESULT))); } + @Test + public void testExecuteWithGeneratedKeys() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.execute(UPDATE, Statement.NO_GENERATED_KEYS), is(false)); + ResultSet keys = statement.getGeneratedKeys(); + assertThat(keys.next(), is(false)); + try { + statement.execute(UPDATE, Statement.RETURN_GENERATED_KEYS); + fail("missing expected exception"); + } catch (SQLFeatureNotSupportedException e) { + // Ignore, this is the expected exception. + } + } + @Test public void testExecuteQuery() throws SQLException { Statement statement = createStatement(); @@ -220,6 +252,12 @@ public void testExecuteQueryWithDdlStatement() throws SQLException { public void testExecuteUpdate() throws SQLException { Statement statement = createStatement(); assertThat(statement.executeUpdate(UPDATE), is(equalTo(1))); + try { + statement.executeUpdate(LARGE_UPDATE); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode(), is(equalTo(Code.OUT_OF_RANGE))); + } } @Test @@ -237,6 +275,36 @@ public void testExecuteUpdateWithDdlStatement() throws SQLException { assertThat(statement.executeUpdate(DDL), is(equalTo(0))); } + @Test + public void testExecuteUpdateWithGeneratedKeys() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.executeUpdate(UPDATE, Statement.NO_GENERATED_KEYS), is(equalTo(1))); + ResultSet keys = statement.getGeneratedKeys(); + assertThat(keys.next(), is(false)); + try { + statement.executeUpdate(UPDATE, Statement.RETURN_GENERATED_KEYS); + fail("missing expected exception"); + } catch (SQLFeatureNotSupportedException e) { + // Ignore, this is the expected exception. + } + } + + @Test + public void testMoreResults() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.execute(SELECT), is(true)); + ResultSet rs = statement.getResultSet(); + assertThat(statement.getMoreResults(), is(false)); + assertThat(statement.getResultSet(), is(nullValue())); + assertThat(rs.isClosed(), is(true)); + + assertThat(statement.execute(SELECT), is(true)); + rs = statement.getResultSet(); + assertThat(statement.getMoreResults(Statement.KEEP_CURRENT_RESULT), is(false)); + assertThat(statement.getResultSet(), is(nullValue())); + assertThat(rs.isClosed(), is(false)); + } + @Test public void testNoBatchMixing() throws SQLException { thrown.expect(SQLException.class); From f7d7940258a017c88c8127acb6b05452de790dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 16:47:48 +0200 Subject: [PATCH 0024/1979] spanner-jdbc: Fix and add tests for JdbcTypeConverter (#6150) * fix and add tests for JdbcTypeConverter * fix time conversion and add tests --- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 148 +++- .../spanner/jdbc/JdbcTypeConverterTest.java | 748 ++++++++++++++++++ 2 files changed, 861 insertions(+), 35 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index f8b9701c4155..a11cb5e899a1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -21,92 +21,162 @@ import com.google.cloud.Timestamp; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; -import com.google.common.base.Preconditions; import java.math.BigDecimal; import java.math.BigInteger; +import java.nio.charset.Charset; +import java.sql.Array; import java.sql.SQLException; import java.sql.Time; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.concurrent.TimeUnit; +import org.threeten.bp.Instant; +import org.threeten.bp.ZoneId; +import org.threeten.bp.ZonedDateTime; +import org.threeten.bp.format.DateTimeFormatter; /** Convenience class for converting values between Java, JDBC and Cloud Spanner. */ class JdbcTypeConverter { + private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + private static final Charset UTF8 = Charset.forName("UTF8"); /** - * Converts the given value from the Google {@link Type} to the Java {@link Class} type. + * Converts the given value from the Google {@link Type} to the Java {@link Class} type. The input + * value and the {@link Type} must be consistent with each other. * - * @param value The value to convert - * @param type The type in the database - * @param targetType The java class target type to convert to - * @return The converted value - * @throws CloudSpannerSQLException Thrown if the given value cannot be converted to the specified - * type + * @param value The value to convert. This value must be in the default type used for a Cloud + * Spanner database type. I.e. if the type argument is {@link Type#string()}, then the input + * value must be an instance of {@link java.lang.String}. + * @param type The type in the database. + * @param targetType The java class target type to convert to. + * @return The converted value. + * @throws SQLException if the given value cannot be converted to the specified type, or if the + * input value and input type are not consistent with each other. */ static Object convert(Object value, Type type, Class targetType) throws SQLException { - Preconditions.checkNotNull(type, "type may not be null"); - Preconditions.checkNotNull(targetType, "targetType may not be null"); - if (value == null) return null; - if (targetType.equals(String.class)) return value.toString(); + JdbcPreconditions.checkArgument(type != null, "type may not be null"); + JdbcPreconditions.checkArgument(targetType != null, "targetType may not be null"); + checkValidTypeAndValueForConvert(type, value); + if (value == null) return null; try { + if (targetType.equals(String.class)) { + if (type.getCode() == Code.BYTES) return new String((byte[]) value, UTF8); + if (type.getCode() == Code.TIMESTAMP) { + Timestamp timestamp = Timestamp.of((java.sql.Timestamp) value); + return TIMESTAMP_FORMAT.format( + ZonedDateTime.ofInstant( + Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()), + ZoneId.systemDefault())); + } + return value.toString(); + } + if (targetType.equals(byte[].class)) { + if (type.getCode() == Code.BYTES) return value; + if (type.getCode() == Code.STRING) return ((String) value).getBytes(UTF8); + } if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; if (type.getCode() == Code.INT64) return Boolean.valueOf((Long) value != 0); if (type.getCode() == Code.FLOAT64) return Boolean.valueOf((Double) value != 0d); - if (type.getCode() == Code.STRING) return Boolean.valueOf((String) value); } if (targetType.equals(BigDecimal.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; if (type.getCode() == Code.INT64) return BigDecimal.valueOf((Long) value); - if (type.getCode() == Code.FLOAT64) return BigDecimal.valueOf((Double) value); - if (type.getCode() == Code.STRING) return new BigDecimal((String) value); } if (targetType.equals(Long.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1L : 0L; if (type.getCode() == Code.INT64) return value; - if (type.getCode() == Code.FLOAT64) return ((Double) value).longValue(); - if (type.getCode() == Code.STRING) return Long.valueOf((String) value); } if (targetType.equals(Integer.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; - if (type.getCode() == Code.INT64) return ((Long) value).intValue(); - if (type.getCode() == Code.FLOAT64) return ((Double) value).intValue(); - if (type.getCode() == Code.STRING) return Integer.valueOf((String) value); + if (type.getCode() == Code.INT64) return AbstractJdbcWrapper.checkedCastToInt((Long) value); + } + if (targetType.equals(Short.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; + if (type.getCode() == Code.INT64) + return AbstractJdbcWrapper.checkedCastToShort((Long) value); + } + if (targetType.equals(Byte.class)) { + if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; + if (type.getCode() == Code.INT64) + return AbstractJdbcWrapper.checkedCastToByte((Long) value); } if (targetType.equals(BigInteger.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; if (type.getCode() == Code.INT64) return BigInteger.valueOf((Long) value); - if (type.getCode() == Code.FLOAT64) return BigInteger.valueOf(((Double) value).longValue()); - if (type.getCode() == Code.STRING) return new BigInteger((String) value); } if (targetType.equals(Float.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Float.valueOf(1f) : Float.valueOf(0f); - if (type.getCode() == Code.INT64) return ((Long) value).floatValue(); - if (type.getCode() == Code.FLOAT64) return ((Double) value).floatValue(); - if (type.getCode() == Code.STRING) return Float.valueOf((String) value); + if (type.getCode() == Code.FLOAT64) + return AbstractJdbcWrapper.checkedCastToFloat((Double) value); } if (targetType.equals(Double.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Double.valueOf(1d) : Double.valueOf(0d); - if (type.getCode() == Code.INT64) return ((Long) value).doubleValue(); if (type.getCode() == Code.FLOAT64) return value; - if (type.getCode() == Code.STRING) return Double.valueOf((String) value); } + if (targetType.equals(java.sql.Date.class)) { + if (type.getCode() == Code.DATE) return value; + } + if (targetType.equals(java.sql.Timestamp.class)) { + if (type.getCode() == Code.TIMESTAMP) return value; + } + if (targetType.equals(java.sql.Array.class)) { + if (type.getCode() == Code.ARRAY) return value; + } + } catch (SQLException e) { + throw e; } catch (Exception e) { throw JdbcSqlExceptionFactory.of( "Cannot convert " + value + " to " + targetType.getName(), com.google.rpc.Code.INVALID_ARGUMENT, e); } - throw JdbcSqlExceptionFactory.of( "Cannot convert " + type.getCode().name() + " to " + targetType.getName(), com.google.rpc.Code.INVALID_ARGUMENT); } + private static void checkValidTypeAndValueForConvert(Type type, Object value) + throws SQLException { + if (value == null) return; + JdbcPreconditions.checkArgument( + (type.getCode() == Code.ARRAY && Array.class.isAssignableFrom(value.getClass())) + || type.getCode() != Code.ARRAY, + "input type is array, but input value is not an instance of java.sql.Array"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.BOOL && value.getClass().equals(Boolean.class)) + || type.getCode() != Code.BOOL, + "input type is bool, but input value is not an instance of Boolean"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.BYTES && value.getClass().equals(byte[].class)) + || type.getCode() != Code.BYTES, + "input type is bytes, but input value is not an instance of byte[]"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.DATE && value.getClass().equals(java.sql.Date.class)) + || type.getCode() != Code.DATE, + "input type is date, but input value is not an instance of java.sql.Date"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.FLOAT64 && value.getClass().equals(Double.class)) + || type.getCode() != Code.FLOAT64, + "input type is float64, but input value is not an instance of Double"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.INT64 && value.getClass().equals(Long.class)) + || type.getCode() != Code.INT64, + "input type is int64, but input value is not an instance of Long"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.STRING && value.getClass().equals(String.class)) + || type.getCode() != Code.STRING, + "input type is string, but input value is not an instance of String"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.TIMESTAMP && value.getClass().equals(java.sql.Timestamp.class)) + || type.getCode() != Code.TIMESTAMP, + "input type is timestamp, but input value is not an instance of java.sql.Timestamp"); + } + @SuppressWarnings("deprecation") static Date toGoogleDate(java.sql.Date date) { return date == null @@ -240,18 +310,26 @@ static List toGoogleTimestamps(java.sql.Timestamp[] timestamps) { return res; } + @SuppressWarnings("deprecation") static Time toSqlTime(Timestamp ts) { - return toSqlTime(ts, Calendar.getInstance()); + if (ts != null) { + java.sql.Timestamp sqlTs = toSqlTimestamp(ts); + Time time = new Time(sqlTs.getHours(), sqlTs.getMinutes(), sqlTs.getSeconds()); + time.setTime( + time.getTime() + TimeUnit.MILLISECONDS.convert(sqlTs.getNanos(), TimeUnit.NANOSECONDS)); + return time; + } + return null; } + @SuppressWarnings("deprecation") static Time toSqlTime(Timestamp ts, Calendar cal) { if (ts != null) { - cal.set(1970, 0, 1, 0, 0, 0); - cal.clear(Calendar.MILLISECOND); - cal.setTimeInMillis( - ts.getSeconds() * 1000 - + TimeUnit.MILLISECONDS.convert(ts.getNanos(), TimeUnit.NANOSECONDS)); - return new Time(cal.getTimeInMillis()); + java.sql.Timestamp sqlTs = getAsSqlTimestamp(ts, cal); + Time time = new Time(sqlTs.getHours(), sqlTs.getMinutes(), sqlTs.getSeconds()); + time.setTime( + time.getTime() + TimeUnit.MILLISECONDS.convert(sqlTs.getNanos(), TimeUnit.NANOSECONDS)); + return time; } return null; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java new file mode 100644 index 000000000000..5978f3ac345c --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -0,0 +1,748 @@ +/* + * Copyright 2019 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 com.google.cloud.spanner.jdbc.JdbcTypeConverter.*; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.rpc.Code; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.sql.Array; +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.TimeZone; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcTypeConverterTest { + private static final Charset UTF8 = Charset.forName("UTF8"); + + @Test + public void testConvertArray() throws SQLException { + Array testValue = JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}); + for (Type t : + new Type[] { + Type.bool(), + Type.bytes(), + Type.date(), + Type.float64(), + Type.int64(), + Type.string(), + Type.timestamp() + }) { + assertConvertThrows(testValue, Type.array(t), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.array(t), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValue, Type.array(t), Array.class)).isEqualTo(testValue); + assertThat(convert(testValue, Type.array(t), String.class)).isEqualTo("{1,2,3}"); + } + } + + @Test + public void testConvertBool() throws SQLException { + Boolean[] testValues = new Boolean[] {Boolean.TRUE, Boolean.FALSE}; + for (Boolean b : testValues) { + assertThat(convert(b, Type.bool(), Boolean.class)).isEqualTo(b); + assertThat(convert(b, Type.bool(), Byte.class)) + .isEqualTo(Byte.valueOf(b ? (byte) 1 : (byte) 0)); + assertThat(convert(b, Type.bool(), Short.class)) + .isEqualTo(Short.valueOf(b ? (short) 1 : (short) 0)); + assertThat(convert(b, Type.bool(), Integer.class)).isEqualTo(Integer.valueOf(b ? 1 : 0)); + assertThat(convert(b, Type.bool(), Long.class)).isEqualTo(Long.valueOf(b ? 1L : 0L)); + assertThat(convert(b, Type.bool(), Float.class)).isEqualTo(Float.valueOf(b ? 1F : 0F)); + assertThat(convert(b, Type.bool(), Double.class)).isEqualTo(Double.valueOf(b ? 1D : 0D)); + assertThat(convert(b, Type.bool(), BigInteger.class)) + .isEqualTo(b ? BigInteger.ONE : BigInteger.ZERO); + assertThat(convert(b, Type.bool(), BigDecimal.class)) + .isEqualTo(b ? BigDecimal.ONE : BigDecimal.ZERO); + assertThat(convert(b, Type.bool(), String.class)).isEqualTo(String.valueOf(b)); + } + } + + @Test + public void testConvertBytes() throws SQLException { + byte[] testValues = "test".getBytes(UTF8); + assertConvertThrows(testValues, Type.bytes(), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.bytes(), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValues, Type.bytes(), byte[].class)).isEqualTo(testValues); + assertThat(convert(testValues, Type.bytes(), String.class)).isEqualTo("test"); + } + + private TimeZone[] getTestTimeZones() { + return new TimeZone[] { + TimeZone.getTimeZone("GMT-12:00"), + TimeZone.getTimeZone("GMT-9:00"), + TimeZone.getTimeZone("GMT-1:00"), + TimeZone.getTimeZone("GMT"), + TimeZone.getTimeZone("GMT+1:00"), + TimeZone.getTimeZone("GMT+12:00") + }; + } + + @Test + public void testConvertDate() throws SQLException { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + @SuppressWarnings("deprecation") + Date testValue = new Date(2019 - 1900, 7, 24); + assertConvertThrows(testValue, Type.date(), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.date(), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValue, Type.date(), Date.class)).isEqualTo(testValue); + assertThat(convert(testValue, Type.date(), String.class)).isEqualTo("2019-08-24"); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @Test + public void testConvertTimestamp() throws SQLException { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + @SuppressWarnings("deprecation") + Timestamp testValue = new Timestamp(2019 - 1900, 7, 24, 7, 20, 19, 123456789); + assertConvertThrows(testValue, Type.timestamp(), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.timestamp(), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValue, Type.timestamp(), Timestamp.class)).isEqualTo(testValue); + int offset = zone.getOffset(testValue.getTime()); + int offsetHours = offset / (60_000 * 60); + DecimalFormat fmt = new DecimalFormat("+##00;-#"); + String offsetString = offset == 0 ? "Z" : fmt.format(offsetHours) + ":00"; + assertThat(convert(testValue, Type.timestamp(), String.class)) + .isEqualTo("2019-08-24T07:20:19.123456789" + offsetString); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @Test + public void testConvertString() throws SQLException { + String testValue = "test"; + assertConvertThrows(testValue, Type.string(), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.string(), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValue, Type.string(), String.class)).isEqualTo(testValue); + assertThat(convert(testValue, Type.string(), byte[].class)).isEqualTo(testValue.getBytes(UTF8)); + } + + @Test + public void testConvertInt64() throws SQLException { + Long[] testValues = + new Long[] { + 0L, + -1L, + 1L, + Long.MIN_VALUE, + Long.MAX_VALUE, + Long.valueOf(Integer.MIN_VALUE), + Long.valueOf(Integer.MAX_VALUE), + Long.valueOf(Integer.MIN_VALUE - 1), + Long.valueOf(Integer.MAX_VALUE + 1), + Long.valueOf(Short.MIN_VALUE), + Long.valueOf(Short.MAX_VALUE), + Long.valueOf(Short.MIN_VALUE - 1), + Long.valueOf(Short.MAX_VALUE + 1), + Long.valueOf(Byte.MIN_VALUE), + Long.valueOf(Byte.MAX_VALUE), + Long.valueOf(Byte.MIN_VALUE - 1), + Long.valueOf(Byte.MAX_VALUE + 1) + }; + testConvertInt64ToNumber(testValues, Long.class, Long.MIN_VALUE, Long.MAX_VALUE); + testConvertInt64ToNumber(testValues, Integer.class, Integer.MIN_VALUE, Integer.MAX_VALUE); + testConvertInt64ToNumber(testValues, Short.class, Short.MIN_VALUE, Short.MAX_VALUE); + testConvertInt64ToNumber(testValues, Byte.class, Byte.MIN_VALUE, Byte.MAX_VALUE); + testConvertInt64ToNumber(testValues, BigInteger.class, Long.MIN_VALUE, Long.MAX_VALUE); + testConvertInt64ToNumber(testValues, BigDecimal.class, Long.MIN_VALUE, Long.MAX_VALUE); + + for (Long l : testValues) { + assertThat(convert(l, Type.int64(), String.class)).isEqualTo(String.valueOf(l)); + assertThat(convert(l, Type.int64(), Boolean.class)).isEqualTo(Boolean.valueOf(l != 0L)); + assertConvertThrows(l, Type.int64(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(l, Type.int64(), Float.class, Code.INVALID_ARGUMENT); + } + } + + private void testConvertInt64ToNumber( + Long[] testValues, Class targetType, Number minValue, Number maxValue) + throws SQLException { + for (Long t : testValues) { + if (t < minValue.longValue() || t > maxValue.longValue()) { + assertConvertThrows(t, Type.int64(), targetType, Code.OUT_OF_RANGE); + } else { + assertThat(((Number) convert(t, Type.int64(), targetType)).longValue()).isEqualTo(t); + assertThat(convert(t, Type.int64(), targetType)).isInstanceOf(targetType); + } + } + } + + @Test + public void testConvertFloat64() throws SQLException { + Double[] testValues = + new Double[] { + 0D, + -1D, + 1D, + Double.MIN_VALUE, + Double.MAX_VALUE, + Double.valueOf(Float.MIN_VALUE), + Double.valueOf(Float.MAX_VALUE), + Double.valueOf(Float.MAX_VALUE + 1D) + }; + for (Double d : testValues) { + assertThat(convert(d, Type.float64(), Double.class)).isEqualTo(d); + if (d > Float.MAX_VALUE || d < -Float.MAX_VALUE) { + assertConvertThrows(d, Type.float64(), Float.class, Code.OUT_OF_RANGE); + } else { + assertThat(convert(d, Type.float64(), Float.class)).isEqualTo(d.floatValue()); + } + assertThat(convert(d, Type.float64(), String.class)).isEqualTo(String.valueOf(d)); + assertThat(convert(d, Type.float64(), Boolean.class)).isEqualTo(Boolean.valueOf(d != 0D)); + assertConvertThrows(d, Type.float64(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(d, Type.float64(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(d, Type.float64(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(d, Type.float64(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(d, Type.float64(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(d, Type.float64(), BigDecimal.class, Code.INVALID_ARGUMENT); + } + } + + private void assertConvertThrows(Object t, Type type, Class destinationType, Code code) + throws SQLException { + try { + convert(t, type, destinationType); + fail("missing conversion exception for " + t); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode()).isEqualTo(code); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testToGoogleDate() { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + assertThat(toGoogleDate(new Date(2019 - 1900, 7, 24))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 8, 24)); + assertThat(toGoogleDate(new Date(2019 - 1900, 0, 1))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 1, 1)); + assertThat(toGoogleDate(new Date(2019 - 1900, 11, 31))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 12, 31)); + assertThat(toGoogleDate(new Date(2016 - 1900, 1, 29))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2016, 2, 29)); + assertThat(toGoogleDate(new Date(2000 - 1900, 1, 29))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2000, 2, 29)); + + assertThat(toGoogleDate(new Time(12, 0, 0))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1)); + assertThat(toGoogleDate(new Time(0, 0, 0))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1)); + assertThat(toGoogleDate(new Time(23, 59, 59))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1)); + + assertThat(toGoogleDate(new Timestamp(2019 - 1900, 7, 24, 8, 51, 21, 987))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 8, 24)); + assertThat(toGoogleDate(new Timestamp(2019 - 1900, 0, 1, 0, 0, 0, 0))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 1, 1)); + assertThat(toGoogleDate(new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 100))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2019, 12, 31)); + assertThat(toGoogleDate(new Timestamp(2016 - 1900, 1, 29, 23, 59, 59, 0))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2016, 2, 29)); + assertThat(toGoogleDate(new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0))) + .isEqualTo(com.google.cloud.Date.fromYearMonthDay(2000, 2, 29)); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @Test + public void testToGoogleDates() { + @SuppressWarnings("deprecation") + Date[] dates = + new Date[] { + new Date(2019 - 1900, 7, 24), + new Date(2019 - 1900, 0, 1), + new Date(2019 - 1900, 11, 31), + new Date(2016 - 1900, 1, 29), + new Date(2000 - 1900, 1, 29) + }; + List expected = + Arrays.asList( + com.google.cloud.Date.fromYearMonthDay(2019, 8, 24), + com.google.cloud.Date.fromYearMonthDay(2019, 1, 1), + com.google.cloud.Date.fromYearMonthDay(2019, 12, 31), + com.google.cloud.Date.fromYearMonthDay(2016, 2, 29), + com.google.cloud.Date.fromYearMonthDay(2000, 2, 29)); + assertThat(toGoogleDates(dates)).isEqualTo(expected); + } + + @SuppressWarnings("deprecation") + @Test + public void testToSqlDate() { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + assertThat(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2019, 8, 24))) + .isEqualTo(new Date(2019 - 1900, 7, 24)); + assertThat(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2019, 1, 1))) + .isEqualTo(new Date(2019 - 1900, 0, 1)); + assertThat(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2019, 12, 31))) + .isEqualTo(new Date(2019 - 1900, 11, 31)); + assertThat(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2016, 2, 29))) + .isEqualTo(new Date(2016 - 1900, 1, 29)); + assertThat(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2000, 2, 29))) + .isEqualTo(new Date(2000 - 1900, 1, 29)); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @Test + public void testToSqlDateWithCalendar() { + for (TimeZone zone : getTestTimeZones()) { + Calendar cal = Calendar.getInstance(zone); + cal.set(2019, 7, 24, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + assertThat( + toSqlDate( + com.google.cloud.Date.fromYearMonthDay(2019, 8, 24), Calendar.getInstance(zone))) + .isEqualTo(new Date(cal.getTimeInMillis())); + + cal.set(2019, 0, 1, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + assertThat( + toSqlDate( + com.google.cloud.Date.fromYearMonthDay(2019, 1, 1), Calendar.getInstance(zone))) + .isEqualTo(new Date(cal.getTimeInMillis())); + + cal.set(2019, 11, 31, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + assertThat( + toSqlDate( + com.google.cloud.Date.fromYearMonthDay(2019, 12, 31), Calendar.getInstance(zone))) + .isEqualTo(new Date(cal.getTimeInMillis())); + + cal.set(2016, 1, 29, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + assertThat( + toSqlDate( + com.google.cloud.Date.fromYearMonthDay(2016, 2, 29), Calendar.getInstance(zone))) + .isEqualTo(new Date(cal.getTimeInMillis())); + + cal.set(2000, 1, 29, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + assertThat( + toSqlDate( + com.google.cloud.Date.fromYearMonthDay(2000, 2, 29), Calendar.getInstance(zone))) + .isEqualTo(new Date(cal.getTimeInMillis())); + } + } + + @Test + public void testToSqlDates() { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + List input = + Arrays.asList( + com.google.cloud.Date.fromYearMonthDay(2019, 8, 24), + com.google.cloud.Date.fromYearMonthDay(2019, 1, 1), + com.google.cloud.Date.fromYearMonthDay(2019, 12, 31), + com.google.cloud.Date.fromYearMonthDay(2016, 2, 29), + com.google.cloud.Date.fromYearMonthDay(2000, 2, 29)); + @SuppressWarnings("deprecation") + List expected = + Arrays.asList( + new Date(2019 - 1900, 7, 24), + new Date(2019 - 1900, 0, 1), + new Date(2019 - 1900, 11, 31), + new Date(2016 - 1900, 1, 29), + new Date(2000 - 1900, 1, 29)); + assertThat(toSqlDates(input)).isEqualTo(expected); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testToSqlTimestamp() throws SQLException { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + List sqlTimestamps = new ArrayList<>(); + List gTimestamps = new ArrayList<>(); + TimeZone.setDefault(zone); + + // Create a timestamp in the current default timezone, but do not set the nanosecond value + // yet, as it would be lost by the ts.getTime() call on the next line. + Timestamp ts = new Timestamp(2019 - 1900, 7, 24, 11 - 2, 23, 1, 0); + ts.setTime(ts.getTime() + zone.getRawOffset()); + ts.setNanos(199800000); + com.google.cloud.Timestamp gts = + ReadOnlyStalenessUtil.parseRfc3339("2019-08-24T11:23:01.1998+02:00"); + assertThat(toSqlTimestamp(gts)).isEqualTo(ts); + sqlTimestamps.add(ts); + gTimestamps.add(gts); + + ts = new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 0); + ts.setTime(ts.getTime() + zone.getRawOffset()); + ts.setNanos(999999999); + gts = ReadOnlyStalenessUtil.parseRfc3339("2019-12-31T23:59:59.999999999Z"); + assertThat(toSqlTimestamp(gts)).isEqualTo(ts); + sqlTimestamps.add(ts); + gTimestamps.add(gts); + + ts = new Timestamp(2016 - 1900, 1, 29, 12 + 2, 0, 1, 0); + ts.setTime(ts.getTime() + zone.getRawOffset()); + ts.setNanos(1000); + gts = ReadOnlyStalenessUtil.parseRfc3339("2016-02-29T12:00:01.000001000-02:00"); + assertThat(toSqlTimestamp(gts)).isEqualTo(ts); + sqlTimestamps.add(ts); + gTimestamps.add(gts); + + ts = new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0); + ts.setTime(ts.getTime() + zone.getRawOffset()); + ts.setNanos(100000000); + gts = ReadOnlyStalenessUtil.parseRfc3339("2000-02-29T00:00:00.100000000Z"); + assertThat(toSqlTimestamp(gts)).isEqualTo(ts); + sqlTimestamps.add(ts); + gTimestamps.add(gts); + + assertThat(toSqlTimestamps(gTimestamps)).isEqualTo(sqlTimestamps); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @Test + public void testGetAsSqlTimestamp() throws SQLException { + for (TimeZone zone : getTestTimeZones()) { + com.google.cloud.Timestamp gts = + ReadOnlyStalenessUtil.parseRfc3339("2019-08-24T11:23:01.1998+03:00"); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+03:00")); + cal.set(2019, 7, 24, 11, 23, 1); + cal.set(Calendar.MILLISECOND, 0); + Timestamp ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); + ts.setNanos(199800000); + assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2019-12-31T23:59:59.999999999-03:00"); + cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-03:00")); + cal.set(2019, 11, 31, 23, 59, 59); + cal.set(Calendar.MILLISECOND, 0); + ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); + ts.setNanos(999999999); + assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2016-02-29T12:00:00Z"); + cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + cal.set(2016, 1, 29, 12, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); + assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2000-02-29T00:00:00.000000000-10:00"); + cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-10:00")); + cal.set(2000, 1, 29, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); + assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testSetTimestampInCalendar() throws SQLException { + for (TimeZone zone : getTestTimeZones()) { + Calendar cal = Calendar.getInstance(zone); + cal.set(2019, 7, 24, 11, 23, 1); + cal.set(Calendar.MILLISECOND, 0); + Timestamp ts = new Timestamp(2019 - 1900, 7, 24, 11, 23, 1, 0); + Timestamp tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); + assertThat(tsInCal.getTime()) + .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); + + cal = Calendar.getInstance(zone); + cal.set(2019, 11, 31, 23, 59, 59); + cal.set(Calendar.MILLISECOND, 999); + ts = new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 999000000); + tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); + assertThat(tsInCal.getTime()) + .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); + + cal = Calendar.getInstance(zone); + cal.set(2016, 1, 29, 12, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + ts = new Timestamp(2016 - 1900, 1, 29, 12, 0, 0, 0); + tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); + assertThat(tsInCal.getTime()) + .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); + + cal = Calendar.getInstance(zone); + cal.set(2000, 1, 29, 0, 0, 0); + cal.set(Calendar.MILLISECOND, 0); + ts = new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0); + tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); + assertThat(tsInCal.getTime()) + .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testToGoogleTimestamp() { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + assertThat(toGoogleTimestamp(new Date(2019 - 1900, 7, 24))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 7, 24, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Date(2019 - 1900, 0, 1))) + .isEqualTo(com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 0, 1, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Date(2019 - 1900, 11, 31))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 11, 31, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Date(2016 - 1900, 1, 29))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2016 - 1900, 1, 29, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Date(2000 - 1900, 1, 29))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0))); + + assertThat(toGoogleTimestamp(new Time(12, 0, 0))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(1970 - 1900, 0, 1, 12, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Time(0, 0, 0))) + .isEqualTo(com.google.cloud.Timestamp.of(new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Time(23, 59, 59))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(1970 - 1900, 0, 1, 23, 59, 59, 0))); + + assertThat(toGoogleTimestamp(new Timestamp(2019 - 1900, 7, 24, 8, 51, 21, 987))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 7, 24, 8, 51, 21, 987))); + assertThat(toGoogleTimestamp(new Timestamp(2019 - 1900, 0, 1, 0, 0, 0, 0))) + .isEqualTo(com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 0, 1, 0, 0, 0, 0))); + assertThat(toGoogleTimestamp(new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 100))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 100))); + assertThat(toGoogleTimestamp(new Timestamp(2016 - 1900, 1, 29, 23, 59, 59, 0))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2016 - 1900, 1, 29, 23, 59, 59, 0))); + assertThat(toGoogleTimestamp(new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0))) + .isEqualTo( + com.google.cloud.Timestamp.of(new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0))); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testToSqlTime() { + TimeZone initialDefault = TimeZone.getDefault(); + try { + for (TimeZone zone : getTestTimeZones()) { + TimeZone.setDefault(zone); + + com.google.cloud.Timestamp gts = + ReadOnlyStalenessUtil.parseRfc3339("2019-08-24T11:23:01.1998+03:00"); + // Subtract 3 hours to compensate for +03 timezone. + Time time = new Time(11 - 3, 23, 1); + time.setTime(time.getTime() + zone.getRawOffset()); + Time convertedTime = toSqlTime(gts); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2019-12-31T23:59:59.999999999Z"); + time = new Time(23, 59, 59); + time.setTime(time.getTime() + zone.getRawOffset()); + convertedTime = toSqlTime(gts); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2016-02-29T12:00:01.000001000-02:00"); + time = new Time(12 + 2, 0, 1); + time.setTime(time.getTime() + zone.getRawOffset()); + convertedTime = toSqlTime(gts); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2000-02-29T00:00:00.100000000Z"); + time = new Time(0, 0, 0); + time.setTime(time.getTime() + zone.getRawOffset()); + convertedTime = toSqlTime(gts); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + } + } finally { + TimeZone.setDefault(initialDefault); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testToSqlTimeWithCalendar() { + for (TimeZone zone : getTestTimeZones()) { + com.google.cloud.Timestamp gts = + ReadOnlyStalenessUtil.parseRfc3339("2019-08-24T11:23:01.1998+03:00"); + // Compensate for +03 + Time time = new Time(11 - 3, 23, 1); + // Compensate for the test timezone. + time.setHours(time.getHours() + ((int) (zone.getRawOffset() / 60_000L / 60))); + // Compensate for the timezone of the environment on the parsed date. + time.setHours( + time.getHours() + + ((int) + (TimeZone.getDefault().getOffset(gts.toSqlTimestamp().getTime()) + / 60_000L + / 60))); + Time convertedTime = toSqlTime(gts, Calendar.getInstance(zone)); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2019-12-31T23:59:59.999999999Z"); + time = new Time(23, 59, 59); + time.setHours(time.getHours() + ((int) (zone.getRawOffset() / 60_000L / 60))); + time.setHours( + time.getHours() + + ((int) + (TimeZone.getDefault().getOffset(gts.toSqlTimestamp().getTime()) + / 60_000L + / 60))); + convertedTime = toSqlTime(gts, Calendar.getInstance(zone)); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2016-02-29T12:00:01.000001000-02:00"); + time = new Time(12 + 2, 0, 1); + time.setHours(time.getHours() + ((int) (zone.getRawOffset() / 60_000L / 60))); + time.setHours( + time.getHours() + + ((int) + (TimeZone.getDefault().getOffset(gts.toSqlTimestamp().getTime()) + / 60_000L + / 60))); + convertedTime = toSqlTime(gts, Calendar.getInstance(zone)); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + + gts = ReadOnlyStalenessUtil.parseRfc3339("2000-02-29T00:00:00.100000000Z"); + time = new Time(0, 0, 0); + time.setHours(time.getHours() + ((int) (zone.getRawOffset() / 60_000L / 60))); + time.setHours( + time.getHours() + + ((int) + (TimeZone.getDefault().getOffset(gts.toSqlTimestamp().getTime()) + / 60_000L + / 60))); + convertedTime = toSqlTime(gts, Calendar.getInstance(zone)); + assertThat(convertedTime.getHours()).isEqualTo(time.getHours()); + assertThat(convertedTime.getMinutes()).isEqualTo(time.getMinutes()); + assertThat(convertedTime.getSeconds()).isEqualTo(time.getSeconds()); + } + } + + @Test + public void testToGoogleBytes() { + assertThat(toGoogleBytes(new byte[][] {"test1".getBytes(UTF8), "test2".getBytes(UTF8)})) + .isEqualTo(Arrays.asList(ByteArray.copyFrom("test1"), ByteArray.copyFrom("test2"))); + } + + @Test + public void testToJavaByteArrays() { + List input = Arrays.asList(ByteArray.copyFrom("test3"), ByteArray.copyFrom("test4")); + List expected = Arrays.asList("test3".getBytes(UTF8), "test4".getBytes(UTF8)); + List output = toJavaByteArrays(input); + assertThat(Arrays.deepEquals(expected.toArray(), output.toArray())).isTrue(); + } +} From 691f32420bc117114ebb79624f44235f63ed90eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 17:50:19 +0200 Subject: [PATCH 0025/1979] spanner-jdbc: Add tests for AbstractJdbcResultSet (#6156) * keep track of fetch size hint Although the hint is currently not used, it is better to keep track of it to keep the get/set methods consistent. According to the JDBC spec, these methods must be implemented, but it is not required that the driver actually uses the hint. * remove unused code * add test cases for methods in AbstractResultSet --- .../spanner/jdbc/AbstractJdbcResultSet.java | 6 +- .../jdbc/AbstractJdbcResultSetTest.java | 855 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcResultSetTest.java | 189 +--- 3 files changed, 860 insertions(+), 190 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java index a85a3d3de244..6016bd2c3033 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java @@ -38,6 +38,8 @@ abstract class AbstractJdbcResultSet extends AbstractJdbcWrapper implements ResultSet { /** The underlying Cloud Spanner {@link com.google.cloud.spanner.ResultSet}. */ final com.google.cloud.spanner.ResultSet spanner; + /** Current fetch size hint for this result set. */ + private int fetchSize; AbstractJdbcResultSet(com.google.cloud.spanner.ResultSet spanner) { this.spanner = spanner; @@ -108,12 +110,12 @@ public int getFetchDirection() throws SQLException { @Override public void setFetchSize(int rows) throws SQLException { - // no-op + this.fetchSize = rows; } @Override public int getFetchSize() throws SQLException { - return 0; + return fetchSize; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java new file mode 100644 index 000000000000..a267d224fc15 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java @@ -0,0 +1,855 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.common.collect.Sets; +import com.google.rpc.Code; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.math.BigDecimal; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Set; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AbstractJdbcResultSetTest { + + private JdbcResultSet rs; + + @Before + public void setup() { + rs = JdbcResultSet.of(mock(Statement.class), JdbcResultSetTest.getMockResultSet()); + } + + @Test + public void testFetchSize() throws SQLException { + assertThat(rs.getFetchSize(), is(equalTo(0))); + for (int size : new int[] {0, 1, 10, 100}) { + rs.setFetchSize(size); + assertThat(rs.getFetchSize(), is(equalTo(size))); + } + } + + @Test + public void testGetType() throws SQLException { + assertThat(rs.getType(), is(equalTo(ResultSet.TYPE_FORWARD_ONLY))); + } + + @Test + public void testGetConcurrency() throws SQLException { + assertThat(rs.getConcurrency(), is(equalTo(ResultSet.CONCUR_READ_ONLY))); + } + + @Test + public void testRowInsertedUpdatedDeleted() throws SQLException { + assertThat(rs.rowInserted(), is(false)); + assertThat(rs.rowUpdated(), is(false)); + assertThat(rs.rowDeleted(), is(false)); + } + + @Test + public void testGetFetchDirection() throws SQLException { + assertThat(rs.getFetchDirection(), is(equalTo(ResultSet.FETCH_FORWARD))); + } + + @Test + public void testSetFetchDirection() throws SQLException { + Set supported = Sets.newHashSet(ResultSet.FETCH_FORWARD); + for (int direction : + new int[] {ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, ResultSet.FETCH_UNKNOWN}) { + try { + rs.setFetchDirection(direction); + assertThat(supported.contains(direction), is(true)); + } catch (JdbcSqlExceptionImpl e) { + assertThat(supported.contains(direction), is(false)); + assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + } + } + } + + private static interface SqlRunnable { + void run() throws SQLException; + } + + @Test + public void testUnsupportedFeatures() throws SQLException { + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getCursorName(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.isLast(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.beforeFirst(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.afterLast(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.first(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.last(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.absolute(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.relative(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.previous(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNull(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNull("test"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBoolean(1, Boolean.TRUE); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBoolean("test", Boolean.TRUE); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateByte(1, (byte) 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateByte("test", (byte) 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateShort(1, (short) 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateShort("test", (short) 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateInt(1, 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateInt("test", 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateLong(1, 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateLong("test", 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateFloat(1, 1F); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateFloat("test", 1F); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateDouble(1, 1D); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateDouble("test", 1D); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBigDecimal(1, BigDecimal.ONE); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBigDecimal("test", BigDecimal.ONE); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateString(1, "value"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateString("test", "value"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBytes(1, "value".getBytes()); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBytes("test", "value".getBytes()); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateDate(1, new Date(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateDate("test", new Date(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateTimestamp(1, new Timestamp(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateTimestamp("test", new Timestamp(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateTime(1, new Time(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateTime("test", new Time(System.currentTimeMillis())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes())); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream(1, new StringReader("value")); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream("test", new StringReader("value")); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream(1, new StringReader("value"), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream("test", new StringReader("value"), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream(1, new StringReader("value"), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateCharacterStream("test", new StringReader("value"), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject(1, new Object()); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject("test", new Object()); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject(1, new Object(), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject("test", new Object(), 1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.insertRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.deleteRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.refreshRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.cancelRowUpdates(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.moveToInsertRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.moveToCurrentRow(); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getRef(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getRef("test"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateRef(1, mock(Ref.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateRef("test", mock(Ref.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob(1, mock(Blob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob("test", mock(Blob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob(1, mock(InputStream.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob("test", mock(InputStream.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob(1, mock(InputStream.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateBlob("test", mock(InputStream.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob(1, mock(Clob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob("test", mock(Clob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob(1, mock(Reader.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob("test", mock(Reader.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob(1, mock(Reader.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateClob("test", mock(Reader.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateArray(1, mock(Array.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateArray("test", mock(Array.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getRowId(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getRowId("test"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateRowId(1, mock(RowId.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateRowId("test", mock(RowId.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNString(1, "value"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNString("test", "value"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob(1, mock(NClob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob("test", mock(NClob.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob(1, mock(Reader.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob("test", mock(Reader.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob(1, mock(Reader.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNClob("test", mock(Reader.class), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getSQLXML(1); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.getSQLXML("test"); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateSQLXML(1, mock(SQLXML.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateSQLXML("test", mock(SQLXML.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNCharacterStream(1, new StringReader("value")); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNCharacterStream("test", new StringReader("value")); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNCharacterStream(1, new StringReader("value"), 1L); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateNCharacterStream("test", new StringReader("value"), 1L); + } + }); + } + + private void assertUnsupported(SqlRunnable runnable) throws SQLException { + try { + runnable.run(); + fail("missing expected SQLFeatureNotSupportedException"); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of("unexpected exception", Code.INTERNAL, e); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index dbe75a86437c..d564ad0f2a10 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import com.google.cloud.ByteArray; import com.google.cloud.Date; @@ -56,7 +55,6 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.internal.stubbing.answers.Returns; @RunWith(JUnit4.class) public class JdbcResultSetTest { @@ -117,8 +115,7 @@ public class JdbcResultSetTest { private JdbcResultSet subject; - private static ResultSet getMockResultSet() { - + static ResultSet getMockResultSet() { return ResultSets.forRows( Type.struct( StructField.of(STRING_COL_NULL, Type.string()), @@ -186,190 +183,6 @@ private static ResultSet getMockResultSet() { .build())); } - static ResultSet getMockResultSet_old() { - ResultSet res = mock(ResultSet.class); - when(res.getString(STRING_COL_NULL)).thenReturn(null); - when(res.isNull(STRING_COL_NULL)).thenReturn(true); - when(res.getString(STRING_COL_NOT_NULL)).thenReturn("FOO"); - when(res.isNull(STRING_COL_NOT_NULL)).thenReturn(false); - when(res.getString(STRING_COLINDEX_NULL - 1)).thenReturn(null); - when(res.isNull(STRING_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getString(STRING_COLINDEX_NOTNULL - 1)).thenReturn("BAR"); - when(res.isNull(STRING_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(STRING_COL_NULL)).thenReturn(Type.string()); - when(res.getColumnType(STRING_COL_NOT_NULL)).thenReturn(Type.string()); - when(res.getColumnType(STRING_COLINDEX_NULL - 1)).thenReturn(Type.string()); - when(res.getColumnType(STRING_COLINDEX_NOTNULL - 1)).thenReturn(Type.string()); - - when(res.getString(URL_COL_NULL)).thenReturn(null); - when(res.isNull(URL_COL_NULL)).thenReturn(true); - when(res.getString(URL_COL_NOT_NULL)).thenReturn("https://github.com/"); - when(res.isNull(URL_COL_NOT_NULL)).thenReturn(false); - when(res.getString(URL_COLINDEX_NULL - 1)).thenReturn(null); - when(res.isNull(URL_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getString(URL_COLINDEX_NOTNULL - 1)).thenReturn("https://github.com/"); - when(res.isNull(URL_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(URL_COL_NULL)).thenReturn(Type.string()); - when(res.getColumnType(URL_COL_NOT_NULL)).thenReturn(Type.string()); - when(res.getColumnType(URL_COLINDEX_NULL - 1)).thenReturn(Type.string()); - when(res.getColumnType(URL_COLINDEX_NOTNULL - 1)).thenReturn(Type.string()); - - when(res.getBoolean(BOOLEAN_COL_NULL)).thenReturn(false); - when(res.isNull(BOOLEAN_COL_NULL)).thenReturn(true); - when(res.getBoolean(BOOLEAN_COL_NOT_NULL)).thenReturn(true); - when(res.isNull(BOOLEAN_COL_NOT_NULL)).thenReturn(false); - when(res.getBoolean(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(false); - when(res.isNull(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getBoolean(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.isNull(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(BOOLEAN_COL_NULL)).thenReturn(Type.bool()); - when(res.getColumnType(BOOLEAN_COL_NOT_NULL)).thenReturn(Type.bool()); - when(res.getColumnType(BOOLEAN_COLINDEX_NULL - 1)).thenReturn(Type.bool()); - when(res.getColumnType(BOOLEAN_COLINDEX_NOTNULL - 1)).thenReturn(Type.bool()); - - when(res.getDouble(DOUBLE_COL_NULL)).thenReturn(0d); - when(res.isNull(DOUBLE_COL_NULL)).thenReturn(true); - when(res.getDouble(DOUBLE_COL_NOT_NULL)).thenReturn(1.123456789d); - when(res.isNull(DOUBLE_COL_NOT_NULL)).thenReturn(false); - when(res.getDouble(DOUBLE_COLINDEX_NULL - 1)).thenReturn(0d); - when(res.isNull(DOUBLE_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getDouble(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(2.123456789d); - when(res.isNull(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(DOUBLE_COL_NULL)).thenReturn(Type.float64()); - when(res.getColumnType(DOUBLE_COL_NOT_NULL)).thenReturn(Type.float64()); - when(res.getColumnType(DOUBLE_COLINDEX_NULL - 1)).thenReturn(Type.float64()); - when(res.getColumnType(DOUBLE_COLINDEX_NOTNULL - 1)).thenReturn(Type.float64()); - - when(res.getString(BYTES_COL_NULL)).thenReturn(null); - when(res.isNull(BYTES_COL_NULL)).thenReturn(true); - when(res.getBytes(BYTES_COL_NOT_NULL)).thenReturn(ByteArray.copyFrom("FOO")); - when(res.isNull(BYTES_COL_NOT_NULL)).thenReturn(false); - when(res.getBytes(BYTES_COLINDEX_NULL - 1)).thenReturn(null); - when(res.isNull(BYTES_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getBytes(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(ByteArray.copyFrom("BAR")); - when(res.isNull(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(BYTES_COL_NULL)).thenReturn(Type.bytes()); - when(res.getColumnType(BYTES_COL_NOT_NULL)).thenReturn(Type.bytes()); - when(res.getColumnType(BYTES_COLINDEX_NULL - 1)).thenReturn(Type.bytes()); - when(res.getColumnType(BYTES_COLINDEX_NOTNULL - 1)).thenReturn(Type.bytes()); - - when(res.getLong(LONG_COL_NULL)).thenReturn(0l); - when(res.isNull(LONG_COL_NULL)).thenReturn(true); - when(res.getLong(LONG_COL_NOT_NULL)).thenReturn(1l); - when(res.isNull(LONG_COL_NOT_NULL)).thenReturn(false); - when(res.getLong(LONG_COLINDEX_NULL - 1)).thenReturn(0l); - when(res.isNull(LONG_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getLong(LONG_COLINDEX_NOTNULL - 1)).thenReturn(2l); - when(res.isNull(LONG_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(LONG_COL_NULL)).thenReturn(Type.int64()); - when(res.getColumnType(LONG_COL_NOT_NULL)).thenReturn(Type.int64()); - when(res.getColumnType(LONG_COLINDEX_NULL - 1)).thenReturn(Type.int64()); - when(res.getColumnType(LONG_COLINDEX_NOTNULL - 1)).thenReturn(Type.int64()); - - when(res.getDate(DATE_COL_NULL)).thenAnswer(new Returns(null)); - when(res.isNull(DATE_COL_NULL)).thenAnswer(new Returns(true)); - when(res.getDate(DATE_COL_NOT_NULL)) - .thenAnswer(new Returns(Date.fromYearMonthDay(2017, 9, 10))); - when(res.isNull(DATE_COL_NOT_NULL)).thenAnswer(new Returns(false)); - when(res.getDate(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(null)); - when(res.isNull(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(true)); - when(res.getDate(DATE_COLINDEX_NOTNULL - 1)) - .thenAnswer(new Returns(Date.fromYearMonthDay(2017, 9, 10))); - when(res.isNull(DATE_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(false)); - when(res.getColumnType(DATE_COL_NULL)).thenAnswer(new Returns(Type.date())); - when(res.getColumnType(DATE_COL_NOT_NULL)).thenAnswer(new Returns(Type.date())); - when(res.getColumnType(DATE_COLINDEX_NULL - 1)).thenAnswer(new Returns(Type.date())); - when(res.getColumnType(DATE_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(Type.date())); - - Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal1.clear(); - cal1.set(2017, 8, 10, 8, 15, 59); - Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal2.clear(); - cal2.set(2017, 8, 11, 8, 15, 59); - when(res.getTimestamp(TIMESTAMP_COL_NULL)).thenReturn(null); - when(res.isNull(TIMESTAMP_COL_NULL)).thenReturn(true); - when(res.getTimestamp(TIMESTAMP_COL_NOT_NULL)).thenReturn(Timestamp.of(cal1.getTime())); - when(res.isNull(TIMESTAMP_COL_NOT_NULL)).thenReturn(false); - when(res.getTimestamp(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(null); - when(res.isNull(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(Timestamp.of(cal2.getTime())); - when(res.isNull(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(TIMESTAMP_COL_NULL)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIMESTAMP_COL_NOT_NULL)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIMESTAMP_COLINDEX_NULL - 1)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIMESTAMP_COLINDEX_NOTNULL - 1)).thenReturn(Type.timestamp()); - - Calendar cal3 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal3.clear(); - cal3.set(1970, 0, 1, 14, 6, 15); - Calendar cal4 = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal4.clear(); - cal4.set(1970, 0, 1, 14, 6, 15); - when(res.getTimestamp(TIME_COL_NULL)).thenReturn(null); - when(res.isNull(TIME_COL_NULL)).thenReturn(true); - when(res.getTimestamp(TIME_COL_NOT_NULL)).thenReturn(Timestamp.of(cal3.getTime())); - when(res.isNull(TIME_COL_NOT_NULL)).thenReturn(false); - when(res.getTimestamp(TIME_COLINDEX_NULL - 1)).thenReturn(null); - when(res.isNull(TIME_COLINDEX_NULL - 1)).thenReturn(true); - when(res.getTimestamp(TIME_COLINDEX_NOTNULL - 1)).thenReturn(Timestamp.of(cal4.getTime())); - when(res.isNull(TIME_COLINDEX_NOTNULL - 1)).thenReturn(false); - when(res.getColumnType(TIME_COL_NULL)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIME_COL_NOT_NULL)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIME_COLINDEX_NULL - 1)).thenReturn(Type.timestamp()); - when(res.getColumnType(TIME_COLINDEX_NOTNULL - 1)).thenReturn(Type.timestamp()); - - when(res.getLongList(ARRAY_COL_NULL)).thenAnswer(new Returns(null)); - when(res.isNull(ARRAY_COL_NULL)).thenAnswer(new Returns(true)); - when(res.getLongList(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(Arrays.asList(1L, 2L, 3L))); - when(res.isNull(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(false)); - when(res.getLongList(ARRAY_COLINDEX_NULL - 1)).thenAnswer(new Returns(null)); - when(res.isNull(ARRAY_COLINDEX_NULL - 1)).thenAnswer(new Returns(true)); - when(res.getLongList(ARRAY_COLINDEX_NOTNULL - 1)) - .thenAnswer(new Returns(Arrays.asList(1L, 2L, 3L))); - when(res.isNull(ARRAY_COLINDEX_NOTNULL - 1)).thenAnswer(new Returns(false)); - when(res.getColumnType(ARRAY_COL_NULL)).thenAnswer(new Returns(Type.array(Type.int64()))); - when(res.getColumnType(ARRAY_COL_NOT_NULL)).thenAnswer(new Returns(Type.array(Type.int64()))); - when(res.getColumnType(ARRAY_COLINDEX_NULL - 1)) - .thenAnswer(new Returns(Type.array(Type.int64()))); - when(res.getColumnType(ARRAY_COLINDEX_NOTNULL - 1)) - .thenAnswer(new Returns(Type.array(Type.int64()))); - - when(res.getColumnIndex(STRING_COL_NOT_NULL)).thenAnswer(new Returns(1)); - when(res.getColumnIndex(UNKNOWN_COLUMN)).thenThrow(new IllegalArgumentException()); - when(res.getColumnIndex(DATE_COL_NOT_NULL)).thenAnswer(new Returns(DATE_COLINDEX_NOTNULL - 1)); - when(res.getColumnIndex(ARRAY_COL_NOT_NULL)) - .thenAnswer(new Returns(ARRAY_COLINDEX_NOTNULL - 1)); - when(res.getColumnIndex(ARRAY_COL_NULL)).thenAnswer(new Returns(ARRAY_COLINDEX_NULL - 1)); - - when(res.getType()) - .thenReturn( - Type.struct( - StructField.of(STRING_COL_NULL, Type.string()), - StructField.of(STRING_COL_NOT_NULL, Type.string()), - StructField.of(BOOLEAN_COL_NULL, Type.bool()), - StructField.of(BOOLEAN_COL_NOT_NULL, Type.bool()), - StructField.of(DOUBLE_COL_NULL, Type.float64()), - StructField.of(DOUBLE_COL_NOT_NULL, Type.float64()), - StructField.of(BYTES_COL_NULL, Type.bytes()), - StructField.of(BYTES_COL_NOT_NULL, Type.bytes()), - StructField.of(LONG_COL_NULL, Type.int64()), - StructField.of(LONG_COL_NOT_NULL, Type.int64()), - StructField.of(DATE_COL_NULL, Type.date()), - StructField.of(DATE_COL_NOT_NULL, Type.date()), - StructField.of(TIMESTAMP_COL_NULL, Type.timestamp()), - StructField.of(TIMESTAMP_COL_NOT_NULL, Type.timestamp()), - StructField.of(TIME_COL_NULL, Type.timestamp()), - StructField.of(TIME_COL_NOT_NULL, Type.timestamp()), - StructField.of(URL_COL_NULL, Type.string()), - StructField.of(URL_COL_NOT_NULL, Type.string()))); - - // Next behaviour. - when(res.next()).thenReturn(true, true, true, true, false); - - return res; - } - public JdbcResultSetTest() throws SQLException { subject = JdbcResultSet.of(mock(Statement.class), getMockResultSet()); subject.next(); From a7ad4c545014e319b8c5f8f2dd2e0e8164e75ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 18:37:56 +0200 Subject: [PATCH 0026/1979] add tests for setting invalid parameter values (#6153) --- .../spanner/jdbc/JdbcParameterStoreTest.java | 135 +++++++++++++++++- 1 file changed, 129 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index f0b3fe12848e..336bfc1a5edf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -21,16 +21,19 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import com.google.cloud.ByteArray; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.common.io.CharStreams; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Reader; import java.io.StringReader; import java.math.BigDecimal; import java.net.URL; @@ -259,9 +262,9 @@ public void testSetParameterWithType() throws SQLException, IOException { params.setParameter(1, (byte) 1, type); assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); verifyParameter(params, Value.bool(true)); - params.setParameter(1, (short) 1, type); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); - verifyParameter(params, Value.bool(true)); + params.setParameter(1, (short) 0, type); + assertThat((Short) params.getParameter(1), is(equalTo((short) 0))); + verifyParameter(params, Value.bool(false)); params.setParameter(1, 1, type); assertThat((Integer) params.getParameter(1), is(equalTo(1))); verifyParameter(params, Value.bool(true)); @@ -274,9 +277,119 @@ public void testSetParameterWithType() throws SQLException, IOException { params.setParameter(1, (double) 1, type); assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); verifyParameter(params, Value.bool(true)); - params.setParameter(1, BigDecimal.ONE, type); - assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); - verifyParameter(params, Value.bool(true)); + params.setParameter(1, BigDecimal.ZERO, type); + assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ZERO))); + verifyParameter(params, Value.bool(false)); + } + } + + @Test + public void testSetInvalidParameterWithType() throws SQLException, IOException { + JdbcParameterStore params = new JdbcParameterStore(); + + // types that should lead to int64, but with invalid values. + for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + } + + // types that should lead to float64 + for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + } + + // types that should lead to date + for (int type : new int[] {Types.DATE}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + assertInvalidParameter(params, 1, type); + assertInvalidParameter(params, 1L, type); + } + + // types that should lead to timestamp + for (int type : new int[] {Types.TIME, Types.TIMESTAMP}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + assertInvalidParameter(params, 1, type); + assertInvalidParameter(params, 1L, type); + } + + // types that should lead to bytes (except BLOB which is handled separately) + for (int type : new int[] {Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + assertInvalidParameter(params, 1, type); + assertInvalidParameter(params, 1L, type); + assertInvalidParameter(params, new JdbcBlob(), type); + } + + for (int type : + new int[] { + Types.CHAR, + Types.VARCHAR, + Types.LONGVARCHAR, + Types.NCHAR, + Types.NVARCHAR, + Types.LONGNVARCHAR + }) { + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + assertInvalidParameter(params, 1, type); + assertInvalidParameter(params, 1L, type); + assertInvalidParameter(params, new JdbcBlob(), type); + assertInvalidParameter(params, new JdbcClob(), type); + } + + // types that should lead to bool + for (int type : new int[] {Types.BOOLEAN, Types.BIT}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, "true", type); + assertInvalidParameter(params, new Object(), type); + } + + assertInvalidParameter(params, BigDecimal.ONE, Types.DECIMAL); + assertInvalidParameter(params, BigDecimal.ZERO, Types.NUMERIC); + + // test setting closed readers and streams. + for (int type : + new int[] { + Types.CHAR, + Types.VARCHAR, + Types.LONGVARCHAR, + Types.NCHAR, + Types.NVARCHAR, + Types.LONGNVARCHAR + }) { + Reader reader = new StringReader("test"); + reader.close(); + params.setParameter(1, reader, type); + verifyParameterBindFails(params); + + InputStream stream = + new InputStream() { + @Override + public int read() throws IOException { + throw new IOException(); + } + }; + params.setParameter(1, stream, type); + verifyParameterBindFails(params); + } + } + + private void assertInvalidParameter(JdbcParameterStore params, Object value, int type) + throws SQLException { + try { + params.setParameter(1, value, type); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); } } @@ -520,6 +633,16 @@ private void verifyParameter(JdbcParameterStore params, Value value) throws SQLE assertThat(builder.build().getParameters().get("p1"), is(equalTo(value))); } + private void verifyParameterBindFails(JdbcParameterStore params) throws SQLException { + Statement.Builder builder = Statement.newBuilder("SELECT * FROM FOO WHERE BAR=:p1"); + try { + params.bindParameterValue(builder.bind("p1"), 1); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + } + } + @Test public void testConvertPositionalParametersToNamedParameters() throws SQLException { assertThat( From c0157f795189373ef62f1189dacd8e020e335b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Aug 2019 18:38:13 +0200 Subject: [PATCH 0027/1979] spanner-jdbc: Add additional tests for JdbcDatabaseMetaData (#6154) * nullsAreSortedAtStart should be false Cloud Spanner treats null values as the lowest possible value, and sorts these accordingly. That means that when sort order is descending, null values will be sorted at the end, while when sort order is ascending null values will be sorted at the start. This method should only return true if nulls are ALWAYS sorted at start. * document how Cloud Spanner supports UNION * add missing trivial test cases --- .../spanner/jdbc/JdbcDatabaseMetaData.java | 4 +- .../jdbc/JdbcDatabaseMetaDataTest.java | 68 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 828bb06bbbf2..9ab38d9d2254 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -115,7 +115,7 @@ public boolean nullsAreSortedLow() throws SQLException { @Override public boolean nullsAreSortedAtStart() throws SQLException { - return true; + return false; } @Override @@ -502,6 +502,8 @@ public boolean supportsCorrelatedSubqueries() throws SQLException { @Override public boolean supportsUnion() throws SQLException { + // Note that Cloud Spanner requires the user to specify 'UNION DISTINCT' or 'UNION ALL' in a + // query. 'UNION DISTINCT' is equal to the SQL operation 'UNION'. return true; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index db7c7f812837..6c3363be3832 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -31,6 +31,7 @@ import java.sql.ResultSetMetaData; import java.sql.RowIdLifetime; import java.sql.SQLException; +import java.sql.Types; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -61,6 +62,13 @@ public void testTrivialMethods() throws SQLException { }) { assertThat(meta.deletesAreDetected(type), is(false)); assertThat(meta.insertsAreDetected(type), is(false)); + assertThat(meta.updatesAreDetected(type), is(false)); + assertThat(meta.ownDeletesAreVisible(type), is(false)); + assertThat(meta.ownInsertsAreVisible(type), is(false)); + assertThat(meta.ownUpdatesAreVisible(type), is(false)); + assertThat(meta.othersDeletesAreVisible(type), is(false)); + assertThat(meta.othersInsertsAreVisible(type), is(false)); + assertThat(meta.othersUpdatesAreVisible(type), is(false)); } assertThat(meta.doesMaxRowSizeIncludeBlobs(), is(true)); assertThat(meta.generatedKeyAlwaysReturned(), is(false)); @@ -72,6 +80,8 @@ public void testTrivialMethods() throws SQLException { assertThat( meta.getDatabaseProductVersion(), is(equalTo(DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION))); + assertThat( + meta.getDefaultTransactionIsolation(), is(equalTo(Connection.TRANSACTION_SERIALIZABLE))); assertThat(meta.getDriverName(), is(equalTo("com.google.cloud.spanner.jdbc.JdbcDriver"))); assertThat(meta.getExtraNameCharacters(), is(equalTo(""))); assertThat(meta.getIdentifierQuoteString(), is(equalTo("`"))); @@ -104,6 +114,12 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.getSchemaTerm(), is(equalTo("SCHEMA"))); assertThat(meta.getSearchStringEscape(), is(equalTo("\\"))); assertThat(meta.getSQLStateType(), is(equalTo(DatabaseMetaData.sqlStateSQL))); + assertThat(meta.locatorsUpdateCopy(), is(true)); + assertThat(meta.nullsAreSortedHigh(), is(false)); + assertThat(meta.nullsAreSortedLow(), is(true)); + assertThat(meta.nullsAreSortedAtStart(), is(false)); + assertThat(meta.nullsAreSortedAtEnd(), is(false)); + assertThat(meta.nullPlusNonNullIsNull(), is(true)); assertThat(meta.isCatalogAtStart(), is(false)); assertThat(meta.isReadOnly(), is(equalTo(connection.isReadOnly()))); assertThat(meta.storesLowerCaseIdentifiers(), is(false)); @@ -124,7 +140,54 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.supportsCatalogsInProcedureCalls(), is(false)); assertThat(meta.supportsCatalogsInTableDefinitions(), is(false)); assertThat(meta.supportsColumnAliasing(), is(true)); + // Note that the supportsConvert() method indicates whether the server side function CONVERT is + // supported, not what the JDBC driver might be able to convert on the client side. assertThat(meta.supportsConvert(), is(false)); + int[] types = + new int[] { + Types.ARRAY, + Types.BIGINT, + Types.BINARY, + Types.BIT, + Types.BLOB, + Types.BOOLEAN, + Types.CHAR, + Types.CLOB, + Types.DATALINK, + Types.DATE, + Types.DECIMAL, + Types.DISTINCT, + Types.DOUBLE, + Types.FLOAT, + Types.INTEGER, + Types.JAVA_OBJECT, + Types.LONGNVARCHAR, + Types.LONGVARCHAR, + Types.LONGVARBINARY, + Types.LONGVARCHAR, + Types.NCHAR, + Types.NCLOB, + Types.NULL, + Types.NUMERIC, + Types.NVARCHAR, + Types.OTHER, + Types.REAL, + Types.REF, + Types.ROWID, + Types.SMALLINT, + Types.SQLXML, + Types.STRUCT, + Types.TIME, + Types.TIMESTAMP, + Types.TINYINT, + Types.VARBINARY, + Types.VARCHAR + }; + for (int from : types) { + for (int to : types) { + assertThat(meta.supportsConvert(from, to), is(false)); + } + } assertThat(meta.supportsCoreSQLGrammar(), is(false)); assertThat(meta.supportsCorrelatedSubqueries(), is(true)); assertThat(meta.supportsDataDefinitionAndDataManipulationTransactions(), is(false)); @@ -186,6 +249,11 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.supportsSubqueriesInIns(), is(true)); assertThat(meta.supportsSubqueriesInQuantifieds(), is(true)); assertThat(meta.supportsTableCorrelationNames(), is(true)); + assertThat(meta.supportsTransactions(), is(true)); + assertThat(meta.supportsUnion(), is(true)); + assertThat(meta.supportsUnionAll(), is(true)); + assertThat(meta.usesLocalFiles(), is(false)); + assertThat(meta.usesLocalFilePerTable(), is(false)); assertThat( meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE), is(true)); for (int level : From c065227d7fd5f20e275772e71fad73a6efb15114 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Mon, 26 Aug 2019 12:50:31 -0400 Subject: [PATCH 0028/1979] Bump next snapshot (#6162) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2373443ebb21..1f9b76008fce 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.3.0 + 0.3.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.106.0-alpha + 0.106.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.33.0 + 1.33.1-SNAPSHOT test-jar test From e8d42f6058ecf7bb27f66b5e7b757adee2063274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 27 Aug 2019 07:16:27 +0200 Subject: [PATCH 0029/1979] spanner-jdbc: Add tests for JdbcConnection (#6157) * isValid should return false and not SQLException when closed * add tests for JdbcConnection --- .../cloud/spanner/jdbc/JdbcConnection.java | 23 +- .../spanner/jdbc/JdbcConnectionTest.java | 253 ++++++++++++++++++ 2 files changed, 266 insertions(+), 10 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 8d5d55bcc25a..c71c21b74086 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -41,6 +41,8 @@ class JdbcConnection extends AbstractJdbcConnection { 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"; + private Map> typeMap = new HashMap<>(); JdbcConnection(String connectionUrl, ConnectionOptions options) { @@ -228,20 +230,21 @@ public void setTypeMap(Map> map) throws SQLException { @Override public boolean isValid(int timeout) throws SQLException { - checkClosed(); JdbcPreconditions.checkArgument(timeout >= 0, "timeout must be >= 0"); - try { - Statement statement = createStatement(); - statement.setQueryTimeout(timeout); - try (ResultSet rs = statement.executeQuery("select 1")) { - if (rs.next()) { - if (rs.getLong(1) == 1L) { - return true; + if (!isClosed()) { + try { + Statement statement = createStatement(); + statement.setQueryTimeout(timeout); + try (ResultSet rs = statement.executeQuery(IS_VALID_QUERY)) { + if (rs.next()) { + if (rs.getLong(1) == 1L) { + return true; + } } } + } catch (SQLException e) { + // ignore } - } catch (SQLException e) { - // ignore } return false; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 68bf06058b54..6740782a4aa3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -21,17 +21,29 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.rpc.Code; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLWarning; import java.sql.Savepoint; +import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Properties; @@ -45,6 +57,10 @@ @RunWith(JUnit4.class) public class JdbcConnectionTest { @Rule public final ExpectedException exception = ExpectedException.none(); + private static final com.google.cloud.spanner.ResultSet SELECT1_RESULTSET = + ResultSets.forRows( + Type.struct(StructField.of("", Type.int64())), + Arrays.asList(Struct.newBuilder().set("").to(1L).build())); private JdbcConnection createConnection(ConnectionOptions options) { com.google.cloud.spanner.jdbc.Connection spannerConnection = @@ -413,4 +429,241 @@ public void testSetClientInfo() throws SQLException { is(equalTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED))); } } + + @Test + public void testIsValid() throws SQLException { + // Setup. + ConnectionOptions options = mock(ConnectionOptions.class); + com.google.cloud.spanner.jdbc.Connection spannerConnection = + mock(com.google.cloud.spanner.jdbc.Connection.class); + when(options.getConnection()).thenReturn(spannerConnection); + Statement statement = Statement.of(JdbcConnection.IS_VALID_QUERY); + + // Verify that an opened connection that returns a result set is valid. + try (JdbcConnection connection = new JdbcConnection("url", options)) { + when(spannerConnection.executeQuery(statement)).thenReturn(SELECT1_RESULTSET); + assertThat(connection.isValid(1), is(true)); + try { + // Invalid timeout value. + connection.isValid(-1); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + } + + // Now let the query return an error. isValid should now return false. + when(spannerConnection.executeQuery(statement)) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.ABORTED, "the current transaction has been aborted")); + assertThat(connection.isValid(1), is(false)); + } + } + + @Test + public void testIsValidOnClosedConnection() throws SQLException { + Connection connection = createConnection(mock(ConnectionOptions.class)); + connection.close(); + assertThat(connection.isValid(1), is(false)); + } + + @Test + public void testCreateStatement() throws SQLException { + try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + for (int resultSetType : + new int[] { + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE + }) { + for (int resultSetConcurrency : + new int[] {ResultSet.CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}) { + if (resultSetType == ResultSet.TYPE_FORWARD_ONLY // Only FORWARD_ONLY is supported + && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY) // Only READ_ONLY is supported + { + java.sql.Statement statement = + connection.createStatement(resultSetType, resultSetConcurrency); + assertThat(statement.getResultSetType(), is(equalTo(resultSetType))); + assertThat(statement.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + } else { + assertCreateStatementFails(connection, resultSetType, resultSetConcurrency); + } + for (int resultSetHoldability : + new int[] {ResultSet.CLOSE_CURSORS_AT_COMMIT, ResultSet.HOLD_CURSORS_OVER_COMMIT}) { + if (resultSetType == ResultSet.TYPE_FORWARD_ONLY // Only FORWARD_ONLY is supported + && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY // Only READ_ONLY is supported + && resultSetHoldability + == ResultSet + .CLOSE_CURSORS_AT_COMMIT) // Only CLOSE_CURSORS_AT_COMMIT is supported + { + java.sql.Statement statement = + connection.createStatement( + resultSetType, resultSetConcurrency, resultSetHoldability); + assertThat(statement.getResultSetType(), is(equalTo(resultSetType))); + assertThat(statement.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + assertThat(statement.getResultSetHoldability(), is(equalTo(resultSetHoldability))); + } else { + assertCreateStatementFails( + connection, resultSetType, resultSetConcurrency, resultSetHoldability); + } + } + } + } + } + } + + private void assertCreateStatementFails( + JdbcConnection connection, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException { + try { + connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + fail( + String.format( + "missing expected exception for %d %d %d", + resultSetType, resultSetConcurrency, resultSetHoldability)); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } + } + + private void assertCreateStatementFails( + JdbcConnection connection, int resultSetType, int resultSetConcurrency) throws SQLException { + try { + connection.createStatement(resultSetType, resultSetConcurrency); + fail( + String.format( + "missing expected exception for %d %d", resultSetType, resultSetConcurrency)); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } + } + + @Test + public void testPrepareStatement() throws SQLException { + try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + for (int resultSetType : + new int[] { + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_SCROLL_SENSITIVE + }) { + for (int resultSetConcurrency : + new int[] {ResultSet.CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}) { + if (resultSetType == ResultSet.TYPE_FORWARD_ONLY // Only FORWARD_ONLY is supported + && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY) // Only READ_ONLY is supported + { + PreparedStatement ps = + connection.prepareStatement("SELECT 1", resultSetType, resultSetConcurrency); + assertThat(ps.getResultSetType(), is(equalTo(resultSetType))); + assertThat(ps.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + } else { + assertPrepareStatementFails(connection, resultSetType, resultSetConcurrency); + } + for (int resultSetHoldability : + new int[] {ResultSet.CLOSE_CURSORS_AT_COMMIT, ResultSet.HOLD_CURSORS_OVER_COMMIT}) { + if (resultSetType == ResultSet.TYPE_FORWARD_ONLY // Only FORWARD_ONLY is supported + && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY // Only READ_ONLY is supported + && resultSetHoldability + == ResultSet + .CLOSE_CURSORS_AT_COMMIT) // Only CLOSE_CURSORS_AT_COMMIT is supported + { + PreparedStatement ps = + connection.prepareStatement( + "SELECT 1", resultSetType, resultSetConcurrency, resultSetHoldability); + assertThat(ps.getResultSetType(), is(equalTo(resultSetType))); + assertThat(ps.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + assertThat(ps.getResultSetHoldability(), is(equalTo(resultSetHoldability))); + } else { + assertPrepareStatementFails( + connection, resultSetType, resultSetConcurrency, resultSetHoldability); + } + } + } + } + } + } + + private void assertPrepareStatementFails( + JdbcConnection connection, + int resultSetType, + int resultSetConcurrency, + int resultSetHoldability) + throws SQLException { + try { + connection.prepareStatement( + "SELECT 1", resultSetType, resultSetConcurrency, resultSetHoldability); + fail( + String.format( + "missing expected exception for %d %d %d", + resultSetType, resultSetConcurrency, resultSetHoldability)); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } + } + + private void assertPrepareStatementFails( + JdbcConnection connection, int resultSetType, int resultSetConcurrency) throws SQLException { + try { + connection.prepareStatement("SELECT 1", resultSetType, resultSetConcurrency); + fail( + String.format( + "missing expected exception for %d %d", resultSetType, resultSetConcurrency)); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } + } + + @Test + public void testPrepareStatementWithAutoGeneratedKeys() throws SQLException { + String sql = "INSERT INTO FOO (COL1) VALUES (?)"; + try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + PreparedStatement statement = + connection.prepareStatement(sql, java.sql.Statement.NO_GENERATED_KEYS); + ResultSet rs = statement.getGeneratedKeys(); + assertThat(rs.next(), is(false)); + try { + statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS); + fail("missing expected SQLFeatureNotSupportedException"); + } catch (SQLFeatureNotSupportedException e) { + // ignore, this is the expected exception. + } + } + } + + @Test + public void testCatalog() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.getDatabaseName()).thenReturn("test"); + try (JdbcConnection connection = createConnection(options)) { + assertThat(connection.getCatalog(), is(equalTo("test"))); + // 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(), is(equalTo(Code.INVALID_ARGUMENT))); + } + } + } + + @Test + public void testSchema() throws SQLException { + try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + assertThat(connection.getSchema(), is(equalTo(""))); + // 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(), is(equalTo(Code.INVALID_ARGUMENT))); + } + } + } } From c0359ae63b1502168d60a95f511d6433be743888 Mon Sep 17 00:00:00 2001 From: nevinheintze <32204684+nevinheintze@users.noreply.github.com> Date: Wed, 28 Aug 2019 00:17:43 +1000 Subject: [PATCH 0030/1979] Remove use of getExitingExecutorService since we want (#6170) ThreadPoolExecutor to be GC'd when StatementExecutor is finished (getExitingExecutorService will keep it around until application exits). Keeping all ThreadPoolExecutors around is effectively a memory leak, and can lead to substantial memory increase if an app uses many StatementExecutors. --- .../com/google/cloud/spanner/jdbc/StatementExecutor.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java index 797599816af4..994c4c44d994 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java @@ -130,9 +130,8 @@ public boolean hasDuration() { /** Creates an {@link ExecutorService} for a {@link StatementExecutor}. */ private static ExecutorService createExecutorService() { - return MoreExecutors.getExitingExecutorService( - new ThreadPoolExecutor( - 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), THREAD_FACTORY)); + return new ThreadPoolExecutor( + 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), THREAD_FACTORY); } private ExecutorService executor = createExecutorService(); From 8918f60e7cd4785e4bf6b8d76d723a48c22d8806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 28 Aug 2019 06:05:04 +0200 Subject: [PATCH 0031/1979] use NoCredentials for tests (#6145) --- .../cloud/spanner/jdbc/ConnectionOptions.java | 16 ++++++++++++---- .../ConnectionImplGeneratedSqlScriptTest.java | 6 +++++- .../jdbc/SetStatementTimeoutSqlScriptTest.java | 6 +++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java index f483d1250c44..ff1bdff49ec0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -19,6 +19,7 @@ import com.google.auth.Credentials; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.NoCredentials; import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.ErrorCode; @@ -370,10 +371,17 @@ private ConnectionOptions(Builder builder) { + matcher.group(Builder.HOST_GROUP); this.instanceId = matcher.group(Builder.INSTANCE_GROUP); this.databaseName = matcher.group(Builder.DATABASE_GROUP); - this.credentials = - builder.credentials == null - ? getCredentialsService().createCredentials(this.credentialsUrl) - : builder.credentials; + // Using credentials on a plain text connection is not allowed, so if the user has not specified + // any credentials and is using a plain text connection, we should not try to get the + // credentials from the environment, but default to NoCredentials. + if (builder.credentials == null && this.credentialsUrl == null && this.usePlainText) { + this.credentials = NoCredentials.getInstance(); + } else { + this.credentials = + builder.credentials == null + ? getCredentialsService().createCredentials(this.credentialsUrl) + : builder.credentials; + } String numChannelsValue = parseNumChannels(builder.uri); if (numChannelsValue != null) { try { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java index 6e2008eb1a37..fff50fa89821 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.NoCredentials; import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; @@ -52,7 +53,10 @@ static class TestConnectionProvider implements GenericConnectionProvider { public GenericConnection getConnection() { return SpannerGenericConnection.of( ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder().setUri(ConnectionImplTest.URI).build())); + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI) + .build())); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java index 62b76b3fe389..90afdf05bafb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.NoCredentials; import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; @@ -31,7 +32,10 @@ static class TestConnectionProvider implements GenericConnectionProvider { public GenericConnection getConnection() { return SpannerGenericConnection.of( ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder().setUri(ConnectionImplTest.URI).build())); + ConnectionOptions.newBuilder() + .setUri(ConnectionImplTest.URI) + .setCredentials(NoCredentials.getInstance()) + .build())); } } From 7158c830a72b6805cd3e30397a409b77805ca58c Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 28 Aug 2019 19:39:57 -0400 Subject: [PATCH 0032/1979] Release v0.107.0 (#6188) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 335e966c3b72..6dc4f64148a9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 0.3.0 + 0.4.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:0.3.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:0.4.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.3.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.4.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1f9b76008fce..cdaca58838ce 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.3.1-SNAPSHOT + 0.4.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.106.1-alpha-SNAPSHOT + 0.107.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.33.1-SNAPSHOT + 1.34.0 test-jar test From ae3904f5b4d201f3c267e8f1ab2bab1bf5932b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 29 Aug 2019 08:07:25 +0200 Subject: [PATCH 0033/1979] spanner-jdbc: Fix possible IllegalArgumentException in SingleUseTransaction (#6175) * remove fireAndForget rollback as it could cause an IAE The fireAndForgetRollbackAndCloseTxManager method could cause an IllegalArgumentException if it happened to execute after a different method had already closed the TransactionManager. The fireAndForgetRollback method has therefore been removed. This is something that should rather be added to the TransactionManager itself. * added comments to clearify how the tx is rollbacked --- .../spanner/jdbc/SingleUseTransaction.java | 97 ++++++------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java index 6dd43997449e..a5d61d5bd778 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java @@ -42,8 +42,6 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** @@ -365,23 +363,25 @@ private abstract class AbstractUpdateCallable implements Callable { @Override public T call() throws Exception { - txManager = dbClient.transactionManager(); - // Check the interrupted state after each (possible) round-trip to the db to allow the - // statement to be cancelled. - checkInterrupted(); - try (TransactionContext txContext = - txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.ABORTED - ? txManager.resetForRetry() - : txManager.begin()) { - checkInterrupted(); - T res = executeUpdate(txContext); - checkInterrupted(); - txManager.commit(); + try { + txManager = dbClient.transactionManager(); + // Check the interrupted state after each (possible) round-trip to the db to allow the + // statement to be cancelled. checkInterrupted(); - return res; + try (TransactionContext txContext = txManager.begin()) { + checkInterrupted(); + T res = executeUpdate(txContext); + checkInterrupted(); + txManager.commit(); + checkInterrupted(); + return res; + } } finally { - txManager.close(); + if (txManager != null) { + // Calling txManager.close() will rollback the transaction if it is still active, i.e. if + // an error occurred before the commit() call returned successfully. + txManager.close(); + } } } } @@ -424,32 +424,22 @@ private T executeAsyncTransactionalUpdate( // handle timeouts and canceling of a statement. while (true) { try { + return asyncExecuteStatement(update, callable); + } catch (AbortedException e) { try { - return asyncExecuteStatement(update, callable); - } catch (AbortedException e) { - try { - Thread.sleep(e.getRetryDelayInMillis() / 1000); - } catch (InterruptedException e1) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.CANCELLED, "Statement execution was interrupted", e1); - } - // Check whether the timeout time has been exceeded. - long executionTime = System.currentTimeMillis() - startedTime; - if (getStatementTimeout().hasTimeout() - && executionTime > getStatementTimeout().getTimeoutValue(TimeUnit.MILLISECONDS)) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.DEADLINE_EXCEEDED, - "Statement execution timeout occurred for " + update.getSqlWithoutComments()); - } + Thread.sleep(e.getRetryDelayInMillis() / 1000); + } catch (InterruptedException e1) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "Statement execution was interrupted", e1); } - } catch (Exception e) { - if (txManager != null) { - if (txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { - fireAndForgetRollbackAndCloseTxManager(txManager); - } + // Check whether the timeout time has been exceeded. + long executionTime = System.currentTimeMillis() - startedTime; + if (getStatementTimeout().hasTimeout() + && executionTime > getStatementTimeout().getTimeoutValue(TimeUnit.MILLISECONDS)) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.DEADLINE_EXCEEDED, + "Statement execution timeout occurred for " + update.getSqlWithoutComments()); } - throw e; } } } @@ -460,33 +450,6 @@ private void checkInterrupted() throws InterruptedException { } } - /** - * Do a fire-and-forget rollback and close the transaction manager. Fire-and-forget is ok as Cloud - * Spanner will abort the transaction automatically after a while if the rollback request should - * not actually reach Cloud Spanner. - */ - private void fireAndForgetRollbackAndCloseTxManager(final TransactionManager txManager) { - Preconditions.checkNotNull(txManager); - Preconditions.checkArgument( - txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.STARTED); - ExecutorService rollbackExecutor = - Executors.newSingleThreadExecutor(new ConnectionImpl.DaemonThreadFactory()); - rollbackExecutor.submit( - new Callable() { - @Override - public Void call() throws Exception { - try { - txManager.rollback(); - return null; - } finally { - txManager.close(); - } - } - }); - rollbackExecutor.shutdown(); - } - @Override public void write(final Mutation mutation) { write(Arrays.asList(mutation)); From c471a5d757c623618cac7fa1a7e8b5cb18702704 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 29 Aug 2019 13:46:14 -0400 Subject: [PATCH 0034/1979] Bump next snapshot (#6194) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cdaca58838ce..2fd98c6880fc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.4.0 + 0.4.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.107.0-alpha + 0.107.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.34.0 + 1.34.1-SNAPSHOT test-jar test From f0b9283605f8bd78171a8cc59608a7ff39b7c15a Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 5 Sep 2019 11:11:12 -0700 Subject: [PATCH 0035/1979] Release google-cloud-java v0.108.0 (#6223) * Release v0.108.0 * Spanner JDBC to 1.0.0 --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 6dc4f64148a9..7ccf28032fd2 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 0.4.0 + 1.0.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:0.4.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.0.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "0.4.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.0.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2fd98c6880fc..247dcb6892ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 0.4.1-SNAPSHOT + 1.0.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.107.1-alpha-SNAPSHOT + 0.108.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.34.1-SNAPSHOT + 1.35.0 test-jar test From 95bd355464d4b88cd2d7397759cfa1422fa7e141 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Fri, 6 Sep 2019 08:52:12 -0700 Subject: [PATCH 0036/1979] Bump next snapshot (#6231) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 247dcb6892ab..a70e1b2754e2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.0.0 + 1.0.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.108.0-alpha + 0.108.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.35.0 + 1.35.1-SNAPSHOT test-jar test From ad1f17efb04996ecdd256d56bedd4313d392e72c Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 11 Sep 2019 15:02:51 -0400 Subject: [PATCH 0037/1979] Release v0.109.0 (#6252) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7ccf28032fd2..1ec6d0cfc4a2 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.0.0 + 1.1.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.0.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.1.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.0.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.1.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a70e1b2754e2..e3001d86e3df 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.0.1-SNAPSHOT + 1.1.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.108.1-alpha-SNAPSHOT + 0.109.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.35.1-SNAPSHOT + 1.36.0 test-jar test From 38989eb04a8066cffc603c5eb9010653077028a0 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 11 Sep 2019 18:44:09 -0400 Subject: [PATCH 0038/1979] Bump next snapshot (#6256) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e3001d86e3df..a5ba52cdef3f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.1.0 + 1.1.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.109.0-alpha + 0.109.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.36.0 + 1.36.1-SNAPSHOT test-jar test From 1846913770058a6b44b289b0b718cca5fc9d1357 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 18 Sep 2019 15:28:29 -0700 Subject: [PATCH 0039/1979] Release google-cloud-java v0.110.0 (#6294) * Release v0.110.0 * fix TranlateIT. use numbers for translation * fix TranlateIT. use numbers for translation --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 1ec6d0cfc4a2..07997ebe281f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.1.0 + 1.2.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.1.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.2.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.1.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.2.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a5ba52cdef3f..148715190153 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.1.1-SNAPSHOT + 1.2.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.109.1-alpha-SNAPSHOT + 0.110.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.36.1-SNAPSHOT + 1.37.0 test-jar test From 283a4f5634cd2cd461ce600204694be6b6cfd743 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 19 Sep 2019 08:16:44 -0700 Subject: [PATCH 0040/1979] Bump next snapshot (#6305) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 148715190153..ed0a724761e8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.2.0 + 1.2.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.110.0-alpha + 0.110.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.37.0 + 1.37.1-SNAPSHOT test-jar test From 463608fbc4174822e7dcb2d1174793aed81cbcbc Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Wed, 25 Sep 2019 13:14:57 -0400 Subject: [PATCH 0041/1979] Release google-cloud-java v0.111.0 (#6347) * Release v0.111.0 * Change Bigtable version to 1.0.0. --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 07997ebe281f..06af645d1e6f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.2.0 + 1.3.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.2.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.3.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.2.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.3.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ed0a724761e8..a692ab479474 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.2.1-SNAPSHOT + 1.3.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.110.1-alpha-SNAPSHOT + 0.111.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.37.1-SNAPSHOT + 1.38.0 test-jar test From 40c87de771d248ee9d5674405d0b9cf5eeda1684 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 26 Sep 2019 13:29:08 -0400 Subject: [PATCH 0042/1979] Bump next snapshot (#6353) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a692ab479474..b26185740345 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.3.0 + 1.3.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.111.0-alpha + 0.111.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.38.0 + 1.38.1-SNAPSHOT test-jar test From a19ecea4fecaf6c1de734005cc0f67703a451c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 27 Sep 2019 02:10:45 +0200 Subject: [PATCH 0043/1979] Spanner: Add BatchCreateSessions rpc and use rotating channel number (#6185) * add BatchCreateSessions rpc and use rotating channel number * add test for batchCreateSessions * use BatchCreateSessions * use batchCreateSessions * fix formatting * revert unnecessary changes * fix formatting * synchronize around increasing channel counter * remove printStackTrace() * do session creation in loop * take consumer instead of returning enumerator * add some documentation to session pool * processed review comments * unflake test case * fix potential infinite loop * unflake testSpannerReturnsAllAvailableSessionsAndThenNoSessions * prevent infinite loop in session retry * fail if exhausted * temp throw error to debug hanging test * remove test code * processed review comments * mock batchCreateSessions after rebase * retry if the number of returned sessions is 0 --- .../com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 6c9d276e69a8..b99aa03085b1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -322,7 +322,8 @@ public void readOnlyExecuteStreamingSql() throws SQLException { @Test public void autocommitCreateSession() throws SQLException { expected.expect(testExceptionMatcher); - mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setBatchCreateSessionsExecutionTime( + SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); } @@ -331,7 +332,8 @@ public void autocommitCreateSession() throws SQLException { @Test public void transactionalCreateSession() throws SQLException { expected.expect(testExceptionMatcher); - mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setBatchCreateSessionsExecutionTime( + SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); @@ -341,7 +343,8 @@ public void transactionalCreateSession() throws SQLException { @Test public void readOnlyCreateSession() throws SQLException { expected.expect(testExceptionMatcher); - mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setBatchCreateSessionsExecutionTime( + SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); From c350aeeb1170019fa4b6aa5f867626d088544e14 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 2 Oct 2019 15:32:18 -0700 Subject: [PATCH 0044/1979] Release google-cloud-java v0.112.0 (#6420) * Release v0.112.0 * Fix translate pom --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 06af645d1e6f..7bbcdce1bbb0 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.3.0 + 1.6.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.3.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.6.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.3.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.6.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b26185740345..54dc3678e8a3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.3.1-SNAPSHOT + 1.6.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.111.1-alpha-SNAPSHOT + 0.114.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.38.1-SNAPSHOT + 1.41.0 test-jar test From 19cb2ac4286204c09385e7ad0d3356ecd1a82f5c Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 3 Oct 2019 12:05:30 -0700 Subject: [PATCH 0045/1979] Bump next snapshot (#6434) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 54dc3678e8a3..15649229e074 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.6.0 + 1.6.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.114.0-alpha + 0.114.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.41.0 + 1.41.1-SNAPSHOT test-jar test From 145ca457830a766f89f8b6a624964d76dbcc7bd2 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 10 Oct 2019 12:37:13 -0700 Subject: [PATCH 0046/1979] Release google-cloud-java v0.115.0 (#6476) * Release v0.115.0 * fix bigtable-it config --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7bbcdce1bbb0..c607df7e2de4 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.6.0 + 1.7.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.6.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.7.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.6.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.7.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 15649229e074..ef567cddaafc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.6.1-SNAPSHOT + 1.7.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.114.1-alpha-SNAPSHOT + 0.115.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.41.1-SNAPSHOT + 1.42.0 test-jar test From d1eb54d7204f9af798e79914ae9d4f2655df3b3a Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 10 Oct 2019 13:48:03 -0700 Subject: [PATCH 0047/1979] Bump next snapshot (#6485) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ef567cddaafc..ffc25cbab867 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.7.0 + 1.7.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.115.0-alpha + 0.115.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.42.0 + 1.42.1-SNAPSHOT test-jar test From a83bcc176ef286cdf8cbd8e13ff1afb48208d74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 15 Oct 2019 03:44:42 +0200 Subject: [PATCH 0048/1979] Spanner: Change default MinSessions to 100 (#6429) * change default MinSessions to 100 Changes the default MinSessions configuration for Cloud Spanner to 100 sessions. The sessions are created using the new BatchCreateSessions API of Spanner, meaning that initializing the pool will finish quickly. Fixes #6169 * fix test failures for the JDBC driver * fix JDBC integration tests * remove commented code * fix internal error in mock spanner * fix potential npe * allow MinSessions>MaxSessions if MinSessions not set --- .../cloud/spanner/jdbc/AbortedTest.java | 184 ++++++++++++++++++ .../spanner/jdbc/ITAbstractSpannerTest.java | 7 +- .../jdbc/JdbcAbortedTransactionTest.java | 20 +- .../cloud/spanner/jdbc/JdbcDriverTest.java | 38 +++- .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 23 ++- 5 files changed, 249 insertions(+), 23 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java new file mode 100644 index 000000000000..af5fcdceb7e2 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; +import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.AbortInterceptor; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.ITConnection; +import com.google.cloud.spanner.jdbc.it.ITTransactionRetryTest.CountTransactionRetryListener; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +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 io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Arrays; +import java.util.List; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AbortedTest { + private static final Statement SELECT_COUNT = + Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"); + private static final ResultSetMetadata SELECT_COUNT_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("C") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build(); + private static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_BEFORE_INSERT = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("0").build()) + .build()) + .setMetadata(SELECT_COUNT_METADATA) + .build(); + private static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_AFTER_INSERT = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("1").build()) + .build()) + .setMetadata(SELECT_COUNT_METADATA) + .build(); + private static final Statement INSERT_STATEMENT = + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"); + private static final int UPDATE_COUNT = 1; + + private static MockSpannerServiceImpl mockSpanner; + private static MockInstanceAdminImpl mockInstanceAdmin; + private static MockDatabaseAdminImpl mockDatabaseAdmin; + private static Server server; + private static InetSocketAddress address; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. + mockInstanceAdmin = new MockInstanceAdminImpl(); + mockDatabaseAdmin = new MockDatabaseAdminImpl(); + address = new InetSocketAddress("localhost", 0); + server = + NettyServerBuilder.forAddress(address) + .addService(mockSpanner) + .addService(mockInstanceAdmin) + .addService(mockDatabaseAdmin) + .build() + .start(); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + public ITConnection createConnection( + AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { + return createConnection( + Arrays.asList(interceptor), + Arrays.asList(transactionRetryListener)); + } + + public ITConnection createConnection( + List interceptors, + List transactionRetryListeners) { + StringBuilder url = + new StringBuilder( + String.format( + "cloudspanner://localhost:%d/projects/proj/instances/inst/databases/db?usePlainText=true;autocommit=false;retryAbortsInternally=true", + server.getPort())); + ConnectionOptions.Builder builder = + ConnectionOptions.newBuilder() + .setUri(url.toString()) + .setStatementExecutionInterceptors(interceptors); + ConnectionOptions options = builder.build(); + ITConnection connection = createITConnection(options); + for (TransactionRetryListener listener : transactionRetryListeners) { + connection.addTransactionRetryListener(listener); + } + return connection; + } + + private ITConnection createITConnection(ConnectionOptions options) { + return new ITConnectionImpl(options); + } + + @Test + public void testCommitAborted() { + // Do two iterations to ensure that each iteration gets its own transaction, and that each + // transaction is the most recent transaction of that session. + for (int i = 0; i < 2; i++) { + mockSpanner.putStatementResult( + StatementResult.query(SELECT_COUNT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + mockSpanner.putStatementResult(StatementResult.update(INSERT_STATEMENT, UPDATE_COUNT)); + AbortInterceptor interceptor = new AbortInterceptor(0); + try (ITConnection connection = + createConnection(interceptor, new CountTransactionRetryListener())) { + // verify that the there is no test record + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(0L))); + assertThat(rs.next(), is(false)); + } + // do an insert + connection.executeUpdate( + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); + // indicate that the next statement should abort + interceptor.setProbability(1.0); + interceptor.setOnlyInjectOnce(true); + // do a commit that will first abort, and then on retry will succeed + connection.commit(); + mockSpanner.putStatementResult( + StatementResult.query(SELECT_COUNT, SELECT_COUNT_RESULTSET_AFTER_INSERT)); + // verify that the insert succeeded + try (ResultSet rs = + connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong("C"), is(equalTo(1L))); + assertThat(rs.next(), is(false)); + } + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java index beb5b56bbfc2..7cd39c7a3ddc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java @@ -132,8 +132,11 @@ public void intercept( Field stateField = cls.getDeclaredField("txnState"); stateField.setAccessible(true); - // first rollback, and then pretend it aborted - tx.rollback(); + // First rollback the delegate, and then pretend it aborted. + // We should call rollback on the delegate and not the wrapping + // AutoClosingTransactionManager, as the latter would cause the session to be returned + // to the session pool. + delegate.rollback(); stateField.set(delegate, TransactionState.ABORTED); } catch (Exception e) { throw new RuntimeException(e); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java index acefaf2087e9..f55e383be8f6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -173,7 +173,7 @@ public void testAutocommitUpdateAborted() throws SQLException { // These retries are not picked up by the transaction retry listener, as that is only done for // actual JDBC transactions that are retried. try (java.sql.Connection connection = createConnection()) { - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); assertThat(updateCount, is(equalTo(UPDATE_COUNT))); } @@ -188,7 +188,7 @@ public void testTransactionalUpdateAborted() throws SQLException { } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); assertThat(updateCount, is(equalTo(UPDATE_COUNT))); assertThat(getRetryCount(connection), is(equalTo(1))); @@ -198,7 +198,7 @@ public void testTransactionalUpdateAborted() throws SQLException { @Test public void testAutocommitBatchUpdateAborted() throws SQLException { try (java.sql.Connection connection = createConnection()) { - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); @@ -215,7 +215,7 @@ public void testTransactionalBatchUpdateAborted() throws SQLException { } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); @@ -230,7 +230,7 @@ public void testTransactionalBatchUpdateAborted() throws SQLException { public void testAutocommitSelectAborted() throws SQLException { // Selects in autocommit are executed using a singleUse read-only transaction and cannot abort. try (java.sql.Connection connection = createConnection()) { - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { assertThat(rs.getLong(1), is(equalTo(1L))); @@ -246,7 +246,7 @@ public void testTransactionalSelectAborted() throws SQLException { } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - mockSpanner.abortNextTransaction(); + mockSpanner.abortNextStatement(); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { assertThat(rs.getLong(1), is(equalTo(1L))); @@ -277,7 +277,7 @@ public void testTransactionalUpdateWithConcurrentModificationsAborted() throws S mockSpanner.putStatementResult( StatementResult.query(SELECT_RANDOM, new RandomResultSetGenerator(25).generate())); // Abort all transactions (including the current one). - mockSpanner.abortAllTransactions(); + mockSpanner.abortNextStatement(); // This will abort and start an internal retry. connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); fail("missing expected aborted exception"); @@ -307,7 +307,7 @@ public void testTransactionalUpdateWithErrorOnOriginalAndRetry() throws SQLExcep } catch (SQLException e) { // ignore } - mockSpanner.abortAllTransactions(); + mockSpanner.abortNextStatement(); connection.commit(); } } @@ -331,7 +331,7 @@ public void testTransactionalUpdateWithErrorOnRetryAndNotOnOriginal() throws SQL StatementResult.exception( Statement.of(sql), Status.INVALID_ARGUMENT.withDescription("test").asRuntimeException())); - mockSpanner.abortAllTransactions(); + mockSpanner.abortNextStatement(); connection.commit(); fail("missing expected aborted exception"); } catch (JdbcAbortedDueToConcurrentModificationException e) { @@ -369,7 +369,7 @@ public void testTransactionalUpdateWithErrorOnOriginalAndNotOnRetry() throws SQL } // Set the update statement to return a result next time (i.e. during retry). mockSpanner.putStatementResult(StatementResult.update(Statement.of(sql), 1L)); - mockSpanner.abortAllTransactions(); + mockSpanner.abortNextStatement(); connection.commit(); fail("missing expected aborted exception"); } catch (JdbcAbortedDueToConcurrentModificationException e) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 94e0523e5645..68c252ebe347 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -19,18 +19,22 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import com.google.cloud.spanner.MockSpannerServiceImpl; +import io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JdbcDriverTest { - private static final String TEST_KEY_PATH = - ConnectionOptionsTest.class.getResource("test-key.json").getFile(); - /** * Make sure the JDBC driver class is loaded. This is needed when running the test using Maven. */ @@ -43,13 +47,33 @@ public class JdbcDriverTest { } } + private static MockSpannerServiceImpl mockSpanner; + private static Server server; + private static InetSocketAddress address; + private static final String TEST_KEY_PATH = + ConnectionOptionsTest.class.getResource("test-key.json").getFile(); + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + @Test public void testConnect() throws SQLException { try (Connection connection = DriverManager.getConnection( String.format( - "jdbc:cloudspanner:/projects/test-project/instances/static-test-instance/databases/test-database;credentials=%s", - TEST_KEY_PATH))) { + "jdbc:cloudspanner://localhost:%d/projects/test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s", + server.getPort(), TEST_KEY_PATH))) { assertThat(connection.isClosed(), is(false)); } } @@ -59,8 +83,8 @@ public void testInvalidConnect() throws SQLException { try (Connection connection = DriverManager.getConnection( String.format( - "jdbc:cloudspanner:/projects/test-project/instances/static-test-instance/databases/test-database;credentialsUrl=%s", - TEST_KEY_PATH))) { + "jdbc:cloudspanner://localhost:%d/projects/test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentialsUrl=%s", + server.getPort(), TEST_KEY_PATH))) { assertThat(connection.isClosed(), is(false)); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index b99aa03085b1..06ea2a343afc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -39,9 +39,10 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import org.junit.After; import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -120,13 +121,13 @@ public static void stopServer() throws Exception { server.awaitTermination(); } - @Before + @After public void reset() { - mockSpanner.removeAllExecutionTimes(); // Close Spanner pool to prevent reusage of the same Spanner instance (and thereby the same // session pool). - mockSpanner.reset(); SpannerPool.closeSpannerPool(); + mockSpanner.removeAllExecutionTimes(); + mockSpanner.reset(); } private String createUrl() { @@ -139,6 +140,8 @@ private Connection createConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitBeginTransaction() throws SQLException { expected.expect(testExceptionMatcher); @@ -149,6 +152,8 @@ public void autocommitBeginTransaction() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitBeginPDMLTransaction() throws SQLException { expected.expect(testExceptionMatcher); @@ -160,6 +165,8 @@ public void autocommitBeginPDMLTransaction() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void transactionalBeginTransaction() throws SQLException { expected.expect(testExceptionMatcher); @@ -171,6 +178,8 @@ public void transactionalBeginTransaction() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void readOnlyBeginTransaction() throws SQLException { expected.expect(testExceptionMatcher); @@ -319,6 +328,8 @@ public void readOnlyExecuteStreamingSql() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitCreateSession() throws SQLException { expected.expect(testExceptionMatcher); @@ -329,6 +340,8 @@ public void autocommitCreateSession() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void transactionalCreateSession() throws SQLException { expected.expect(testExceptionMatcher); @@ -340,6 +353,8 @@ public void transactionalCreateSession() throws SQLException { } } + @Ignore( + "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void readOnlyCreateSession() throws SQLException { expected.expect(testExceptionMatcher); From 78b8065a9194c8a7226762cdbdf1497864a01168 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 17 Oct 2019 07:37:39 -0700 Subject: [PATCH 0049/1979] Release v0.116.0 (#6518) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c607df7e2de4..c9b986add167 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.7.0 + 1.8.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.7.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.8.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.7.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.8.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ffc25cbab867..f9648175f7e5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.7.1-SNAPSHOT + 1.8.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.115.1-alpha-SNAPSHOT + 0.116.0-alpha google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.42.1-SNAPSHOT + 1.43.0 test-jar test From 53ab28525baf2d55b6862d9a9d25634198b3fc9d Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 17 Oct 2019 16:36:54 -0400 Subject: [PATCH 0050/1979] Bump next snapshot (#6525) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f9648175f7e5..acad0a480ebc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.8.0 + 1.8.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.116.0-alpha + 0.116.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -31,7 +31,7 @@ ${project.groupId} google-cloud-spanner - 1.43.0 + 1.43.1-SNAPSHOT test-jar test From af7b9056c677353dadfe69b4667eb51371a85c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 22 Oct 2019 04:07:46 +0200 Subject: [PATCH 0051/1979] spanner-jdbc: GCS dependency should be scope provided (#6528) The Google Cloud Storage dependency is only used for loading credentials from storage if a user specifies a GCS URL. Adding the entire GCS client library as a dependency only for this feature is not very user friendly. Instead the dependency should be scope provided, and users wanting to use this feature should add a GCS dependency explicitly. Fixes #6474. --- java-spanner-jdbc/pom.xml | 1 + .../java/com/google/cloud/spanner/jdbc/ConnectionOptions.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index acad0a480ebc..0804466dcb65 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -27,6 +27,7 @@ com.google.cloud google-cloud-storage + provided ${project.groupId} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java index ff1bdff49ec0..3b03aca5e82d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -291,7 +291,9 @@ public Builder setUri(String uri) { * Sets the URL of the credentials file to use for this connection. The URL may be a reference * to a file on the local file system, or to a file on Google Cloud Storage. References to * Google Cloud Storage files are only allowed when the application is running on Google Cloud - * and the environment has access to the specified storage location. + * and the environment has access to the specified storage location. It also requires that the + * Google Cloud Storage client library is present on the class path. The Google Cloud Storage + * library is not automatically added as a dependency by the JDBC driver. * *

If you do not specify a credentialsUrl (either by using this setter, or by specifying on * the connection URI), the credentials returned by {@link From 0667e19df114d6bb61a28534297372d38798ac66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 25 Oct 2019 08:59:16 +0200 Subject: [PATCH 0052/1979] spanner-jdbc: Support query hints (#6553) The Spanner JDBC driver would consider queries that started with a statement hint as invalid statements. This change adds a check for statement hints at the beginning of a query, and accepts these as valid queries. Fixes #6540. --- .../cloud/spanner/jdbc/StatementParser.java | 22 +++++++++++++++++++ .../spanner/jdbc/StatementParserTest.java | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java index 5587712904cb..9ed1ecd23ba1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java @@ -239,6 +239,10 @@ boolean isDdlStatement(String sql) { * @return true if the statement is a SELECT statement (i.e. starts with 'SELECT'). */ boolean isQuery(String sql) { + // Skip any query hints at the beginning of the query. + if (sql.startsWith("@")) { + sql = removeStatementHint(sql); + } return statementStartsWith(sql, selectStatements); } @@ -378,4 +382,22 @@ static String removeCommentsAndTrim(String sql) { } return res.toString().trim(); } + + /** Removes any statement hints at the beginning of the statement. */ + static String removeStatementHint(String sql) { + // Valid statement hints at the beginning of a SQL statement can only contain a fixed set of + // possible values. Although it is possible to add a @{FORCE_INDEX=...} as a statement hint, the + // only allowed value is _BASE_TABLE. This means that we can safely assume that the statement + // hint will not contain any special characters, for example a closing curly brace, and + // that we can keep the check simple by just searching for the first occurrence of a closing + // curly brace at the end of the statement hint. + int startStatementHintIndex = sql.indexOf('{'); + int endStatementHintIndex = sql.indexOf('}'); + if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex) { + // Looks like an invalid statement hint. Just ignore at this point and let the caller handle + // the invalid query. + return sql; + } + return removeCommentsAndTrim(sql.substring(endStatementHintIndex + 1)); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java index 7e17c6d3f052..9bfef7546ac4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java @@ -292,6 +292,28 @@ public void testIsQuery() { .isQuery()); } + @Test + public void testQueryHints() { + // Valid query hints. + assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); + assertTrue(parser.isQuery("@ {JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); + assertTrue(parser.isQuery("@{ JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); + assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN } SELECT * FROM PersonsTable")); + assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN}\nSELECT * FROM PersonsTable")); + assertTrue(parser.isQuery("@{\nJOIN_METHOD = HASH_JOIN \t}\n\t SELECT * FROM PersonsTable")); + assertTrue( + parser.isQuery( + "@{JOIN_METHOD=HASH_JOIN}\n -- Single line comment\nSELECT * FROM PersonsTable")); + assertTrue( + parser.isQuery( + "@{JOIN_METHOD=HASH_JOIN}\n /* Multi line comment\n with more comments\n */SELECT * FROM PersonsTable")); + + // Invalid query hints. + assertFalse(parser.isQuery("@{JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); + assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); + assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); + } + @Test public void testIsUpdate_InsertStatements() { assertFalse(parser.isUpdateStatement("")); From d48525c8920bbd0a2ab586737d57f54e1f88dafe Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 31 Oct 2019 08:34:14 -0700 Subject: [PATCH 0053/1979] Release v0.117.0 (#6664) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c9b986add167..a6273942bf53 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.8.0 + 1.9.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.8.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.9.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.8.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.9.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0804466dcb65..3279b1e6069c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.8.1-SNAPSHOT + 1.9.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.116.1-alpha-SNAPSHOT + 0.117.0-alpha google-cloud-spanner-jdbc @@ -32,7 +32,7 @@ ${project.groupId} google-cloud-spanner - 1.43.1-SNAPSHOT + 1.44.0 test-jar test From b577a898714b42febfe57ce2c9731c6d1f71abf0 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Mon, 4 Nov 2019 11:39:14 -0800 Subject: [PATCH 0054/1979] Bump next snapshot (#6674) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3279b1e6069c..7ca914727046 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.9.0 + 1.9.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.117.0-alpha + 0.117.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -32,7 +32,7 @@ ${project.groupId} google-cloud-spanner - 1.44.0 + 1.44.1-SNAPSHOT test-jar test From 87c650732e47b3230a6c132c26913f0b877683bf Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Wed, 6 Nov 2019 14:11:27 -0700 Subject: [PATCH 0055/1979] Release v0.118.0 (#6704) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a6273942bf53..8d76f0b8353b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.9.0 + 1.10.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.9.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.10.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.9.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.10.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ca914727046..7ad0ad2ee2c4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.9.1-SNAPSHOT + 1.10.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.117.1-alpha-SNAPSHOT + 0.118.0-alpha google-cloud-spanner-jdbc @@ -32,7 +32,7 @@ ${project.groupId} google-cloud-spanner - 1.44.1-SNAPSHOT + 1.45.0 test-jar test From aeee21119982a7cc848efb9e09a2ddfc1edc8da9 Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Fri, 8 Nov 2019 13:21:26 -0700 Subject: [PATCH 0056/1979] Bump next snapshot (#6712) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ad0ad2ee2c4..187d225c877e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.10.0 + 1.10.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.118.0-alpha + 0.118.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -32,7 +32,7 @@ ${project.groupId} google-cloud-spanner - 1.45.0 + 1.45.1-SNAPSHOT test-jar test From c9e39f0f13cb9b354133ea37273445af0bd0efab Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 13 Nov 2019 17:48:04 -0600 Subject: [PATCH 0057/1979] Release v0.119.0 (#6772) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8d76f0b8353b..0f9de64d1b5b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.10.0 + 1.11.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.10.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.11.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.10.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.11.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 187d225c877e..4233deeba056 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.10.1-SNAPSHOT + 1.11.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.118.1-alpha-SNAPSHOT + 0.119.0-alpha google-cloud-spanner-jdbc @@ -32,7 +32,7 @@ ${project.groupId} google-cloud-spanner - 1.45.1-SNAPSHOT + 1.46.0 test-jar test From ce7bdfb20b5fa874f9be7298a9c6882db4484ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 14 Nov 2019 18:06:07 +0100 Subject: [PATCH 0058/1979] Spanner: Remove dependency on GCS (#6762) * remove gcs dependency Remove the dependency on Google Cloud Storage and throw a descriptive exception for users who are currently using this feature. Fixes #6708. * fixed error msg according to review comment --- java-spanner-jdbc/pom.xml | 5 -- .../spanner/jdbc/CredentialsService.java | 65 ++----------------- .../spanner/jdbc/CredentialsServiceTest.java | 61 +++-------------- 3 files changed, 15 insertions(+), 116 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4233deeba056..b8578879591e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -24,11 +24,6 @@ ${project.groupId} google-cloud-spanner - - com.google.cloud - google-cloud-storage - provided - ${project.groupId} google-cloud-spanner diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java index b2f38a0d47d5..1bb314e794dd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java @@ -20,23 +20,17 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.storage.Blob; -import com.google.cloud.storage.Storage; -import com.google.cloud.storage.StorageOptions; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.channels.Channels; -/** Service class for getting credentials from key files stored locally or on cloud storage. */ +/** Service class for getting credentials from key files. */ class CredentialsService { - private static final String GOOGLE_CLOUD_STORAGE_PREFIX = "gs://"; - private static final String INVALID_GCS_PREFIX_MSG = - String.format("Storage URL must start with %s", GOOGLE_CLOUD_STORAGE_PREFIX); - + static final String GCS_NOT_SUPPORTED_MSG = + "Credentials that is stored on Google Cloud Storage is no longer supported. Download the credentials to a local file and reference the local file in the connection URL."; static final CredentialsService INSTANCE = new CredentialsService(); CredentialsService() {} @@ -75,8 +69,8 @@ private GoogleCredentials getCredentialsFromUrl(String credentialsUrl) throws IO Preconditions.checkNotNull(credentialsUrl); Preconditions.checkArgument( credentialsUrl.length() > 0, "credentialsUrl may not be an empty string"); - if (credentialsUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX)) { - return getCredentialsFromCloudStorage(credentialsUrl); + if (credentialsUrl.startsWith("gs://")) { + throw new IOException(GCS_NOT_SUPPORTED_MSG); } else { return getCredentialsFromLocalFile(credentialsUrl); } @@ -92,53 +86,4 @@ private GoogleCredentials getCredentialsFromLocalFile(String filePath) throws IO return GoogleCredentials.fromStream(credentialsStream); } } - - private GoogleCredentials getCredentialsFromCloudStorage(String credentialsUrl) - throws IOException { - Preconditions.checkArgument(credentialsUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX)); - try { - Storage storage = internalCreateStorage(); - String bucketName = internalGetBucket(credentialsUrl); - String blobName = internalGetBlob(credentialsUrl); - Blob blob = storage.get(bucketName, blobName); - return GoogleCredentials.fromStream(internalCreateInputStream(blob)); - } catch (Exception e) { - throw new IOException( - String.format( - "Could not retrieve credentials from %s. " - + "Credentials on Google Cloud Storage can only be used when the application is running " - + "in an environment that already has default credentials to access Google Cloud Storage", - credentialsUrl), - e); - } - } - - @VisibleForTesting - Storage internalCreateStorage() { - return StorageOptions.newBuilder().build().getService(); - } - - @VisibleForTesting - InputStream internalCreateInputStream(Blob blob) { - return Channels.newInputStream(blob.reader()); - } - - @VisibleForTesting - String internalGetBucket(String storageUrl) { - Preconditions.checkArgument( - storageUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX), INVALID_GCS_PREFIX_MSG); - Preconditions.checkArgument( - storageUrl.substring(5).contains("/"), "Storage URL must contain a blob name"); - return storageUrl.substring(5, storageUrl.indexOf('/', 5)); - } - - @VisibleForTesting - String internalGetBlob(String storageUrl) { - Preconditions.checkArgument( - storageUrl.startsWith(GOOGLE_CLOUD_STORAGE_PREFIX), - String.format("Storage URL must start with %s", GOOGLE_CLOUD_STORAGE_PREFIX)); - Preconditions.checkArgument( - storageUrl.substring(5).contains("/"), "Storage URL must contain a blob name"); - return storageUrl.substring(storageUrl.indexOf('/', 5) + 1); - } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java index d38ac23da9ee..fbc35f7286e5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java @@ -19,19 +19,14 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.junit.Assert.fail; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; +import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; -import com.google.cloud.storage.Blob; -import com.google.cloud.storage.Storage; -import com.google.cloud.storage.StorageException; -import com.google.rpc.Code; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -43,35 +38,12 @@ public class CredentialsServiceTest { CredentialsServiceTest.class.getResource("test-key.json").getFile(); private static final String APP_DEFAULT_FILE_TEST_PATH = CredentialsServiceTest.class.getResource("test-key-app-default.json").getFile(); - private static final String CLOUD_FILE_TEST_PATH = - CredentialsServiceTest.class.getResource("test-key-cloud-storage.json").getFile(); - private static final String GS_TEST_PATH = "gs://test-bucket/test-key-cloud-storage.json"; - private static final String GS_INVALID_TEST_PATH = "gs://test-bucket/non-existing-key.json"; private static final String TEST_PROJECT_ID = "test-project"; private static final String APP_DEFAULT_PROJECT_ID = "app-default-test-project"; - private static final String GS_PROJECT_ID = "gs-test-project"; private final CredentialsService service = new CredentialsService() { - @Override - Storage internalCreateStorage() { - Storage storage = mock(Storage.class); - when(storage.get("test-bucket", "test-key-cloud-storage.json")) - .thenReturn(mock(Blob.class)); - when(storage.get("test-bucket", "non-existing-key.json")) - .thenThrow(new StorageException(Code.NOT_FOUND_VALUE, "Unknown blob")); - return storage; - } - - @Override - InputStream internalCreateInputStream(Blob blob) { - try { - return new FileInputStream(CLOUD_FILE_TEST_PATH); - } catch (IOException e) { - throw new RuntimeException(e); - } - } @Override GoogleCredentials internalGetApplicationDefault() throws IOException { @@ -95,32 +67,19 @@ public void testCreateCredentialsFile() throws IOException { assertThat(credentials.getProjectId(), is(equalTo(TEST_PROJECT_ID))); } - @Test - public void testCreateCredentialsCloudStorage() throws IOException { - ServiceAccountCredentials credentials = - (ServiceAccountCredentials) service.createCredentials(GS_TEST_PATH); - assertThat(credentials.getProjectId(), is(equalTo(GS_PROJECT_ID))); - } - @Test(expected = SpannerException.class) public void testCreateCredentialsInvalidFile() { service.createCredentials("invalid_file_path.json"); } - @Test(expected = SpannerException.class) - public void testCreateCredentialsInvalidCloudStorage() { - service.createCredentials(GS_INVALID_TEST_PATH); - } - @Test - public void testGetBlob() { - assertThat(service.internalGetBlob("gs://test-bucket/test-blob"), is(equalTo("test-blob"))); - assertThat(service.internalGetBlob("gs://test-bucket/blob-test"), is(equalTo("blob-test"))); - } - - @Test - public void testGetBucket() { - assertThat(service.internalGetBucket("gs://test-bucket/test-blob"), is(equalTo("test-bucket"))); - assertThat(service.internalGetBucket("gs://bucket-test/blob-test"), is(equalTo("bucket-test"))); + public void testCreateCredentialsInvalidCloudStorage() { + try { + service.createCredentials("gs://test-bucket/test-blob"); + fail("missing expected exception"); + } catch (SpannerException e) { + assertThat(e.getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); + assertThat(e.getCause().getMessage(), is(equalTo(CredentialsService.GCS_NOT_SUPPORTED_MSG))); + } } } From 75157186353816715f76248ffafa3ecc2bcf431c Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Fri, 15 Nov 2019 09:36:23 -0600 Subject: [PATCH 0059/1979] Bump next snapshot (#6790) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b8578879591e..70376b90acab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.11.0 + 1.11.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.119.0-alpha + 0.119.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -27,7 +27,7 @@ ${project.groupId} google-cloud-spanner - 1.46.0 + 1.46.1-SNAPSHOT test-jar test From 05e82008138f28c61e15c4542a13efc0252f119c Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Tue, 26 Nov 2019 12:18:18 -0600 Subject: [PATCH 0060/1979] deps: google-cloud-clients should not import google-cloud-bom (#6903) * deps: google-cloud-clients should not import google-cloud-bom * manage storage http client in google-cloud-storage * google-cloud-examples should let the google-cloud-bom handle versions update the securitycenter versions in the bom --- java-spanner-jdbc/pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 70376b90acab..7e9fca479e79 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -21,11 +21,12 @@ - ${project.groupId} + com.google.cloud google-cloud-spanner + 1.46.1-SNAPSHOT - ${project.groupId} + com.google.cloud google-cloud-spanner 1.46.1-SNAPSHOT test-jar From 1a424eecf2043e4cc1319062309d5762d14726e0 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 27 Nov 2019 20:08:07 +0100 Subject: [PATCH 0061/1979] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.0.0-m4 (#6940) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e9fca479e79..1f3f44e654dd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -55,7 +55,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M3 + 3.0.0-M4 com.google.cloud.spanner.IntegrationTest sponge_log From b4ea53409532a3ee3b8ae32734c27de29fd4a456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 3 Dec 2019 08:46:51 +0100 Subject: [PATCH 0062/1979] spanner-jdbc: Metadata queries should be allowed during a DDL batch (#6939) * Metadata queries should be allowed in a DDL batch A DDL batch would refuse any query that would be executed during an active batch. This causes problems for frameworks, such as Hibernate, that might execute such queries during datamodel generation to check which database objects (tables, indices, ...) already exist in the database. This change will allow specifically internally generated metadata queries to be executed during a DDL batch. All other queries will still be refused. The metadata queries will be executed using a single use read-only transaction. * ignore non-internal options * run code formatter --- .../spanner/jdbc/AbstractJdbcStatement.java | 16 +- .../cloud/spanner/jdbc/ConnectionImpl.java | 14 +- .../google/cloud/spanner/jdbc/DdlBatch.java | 39 ++- .../cloud/spanner/jdbc/JdbcConnection.java | 2 +- .../spanner/jdbc/JdbcDatabaseMetaData.java | 46 +-- .../spanner/jdbc/JdbcPreparedStatement.java | 6 + .../cloud/spanner/jdbc/DdlBatchTest.java | 30 ++ ...cDatabaseMetaDataWithMockedServerTest.java | 299 ++++++++++++++++++ 8 files changed, 422 insertions(+), 30 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index ef52e5be1f56..94ddaf17d695 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -25,6 +25,7 @@ import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; +import java.util.Arrays; import java.util.concurrent.TimeUnit; /** Base class for Cloud Spanner JDBC {@link Statement}s */ @@ -46,11 +47,13 @@ public JdbcConnection getConnection() { return connection; } - private Options.QueryOption[] getQueryOptions() throws SQLException { + private Options.QueryOption[] getQueryOptions(QueryOption... options) throws SQLException { + QueryOption[] res = options == null ? new QueryOption[0] : options; if (getFetchSize() > 0) { - return new Options.ReadAndQueryOption[] {Options.prefetchChunks(getFetchSize())}; + res = Arrays.copyOf(res, res.length + 1); + res[res.length - 1] = Options.prefetchChunks(getFetchSize()); } - return new QueryOption[0]; + return res; } /** The {@link TimeUnit}s that are supported for timeout and staleness durations */ @@ -147,14 +150,17 @@ private void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLE * Executes a SQL statement on the connection of this {@link Statement} as a query. * * @param statement The SQL statement to executed. + * @param options {@link QueryOption}s that should be applied to the query. * @return the result of the SQL statement as a {@link ResultSet}. * @throws SQLException if a database error occurs. */ - ResultSet executeQuery(com.google.cloud.spanner.Statement statement) throws SQLException { + ResultSet executeQuery(com.google.cloud.spanner.Statement statement, QueryOption... options) + throws SQLException { StatementTimeout originalTimeout = setTemporaryStatementTimeout(); try { return JdbcResultSet.of( - this, connection.getSpannerConnection().executeQuery(statement, getQueryOptions())); + this, + connection.getSpannerConnection().executeQuery(statement, getQueryOptions(options))); } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); } finally { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java index b0fd4e426384..8490dfcd5f90 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java @@ -110,6 +110,17 @@ enum BatchMode { DML; } + /** + * This query option is used internally to indicate that a query is executed by the library itself + * to fetch metadata. These queries are specifically allowed to be executed even when a DDL batch + * is active. + */ + static final class InternalMetadataQuery implements QueryOption { + static final InternalMetadataQuery INSTANCE = new InternalMetadataQuery(); + + private InternalMetadataQuery() {} + } + /** The combination of all transaction modes and batch modes. */ enum UnitOfWorkType { READ_ONLY_TRANSACTION { @@ -678,7 +689,7 @@ private ResultSet parseAndExecuteQuery( .execute(connectionStatementExecutor, parsedStatement.getSqlWithoutComments()) .getResultSet(); case QUERY: - return internalExecuteQuery(parsedStatement, analyzeMode); + return internalExecuteQuery(parsedStatement, analyzeMode, options); case UPDATE: case DDL: case UNKNOWN: @@ -845,6 +856,7 @@ private UnitOfWork createNewUnitOfWork() { case DDL_BATCH: return DdlBatch.newBuilder() .setDdlClient(ddlClient) + .setDatabaseClient(dbClient) .setStatementTimeout(statementTimeout) .withStatementExecutor(statementExecutor) .build(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java index d69271ffc3f0..3431b29624bb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java @@ -18,6 +18,7 @@ import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.Options.QueryOption; @@ -25,6 +26,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; import com.google.cloud.spanner.jdbc.StatementParser.StatementType; import com.google.common.annotations.VisibleForTesting; @@ -37,6 +39,7 @@ import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import org.apache.commons.lang3.ArrayUtils; /** * {@link UnitOfWork} that is used when a DDL batch is started. These batches only accept DDL @@ -48,11 +51,13 @@ */ class DdlBatch extends AbstractBaseUnitOfWork { private final DdlClient ddlClient; + private final DatabaseClient dbClient; private final List statements = new ArrayList<>(); private UnitOfWorkState state = UnitOfWorkState.STARTED; static class Builder extends AbstractBaseUnitOfWork.Builder { private DdlClient ddlClient; + private DatabaseClient dbClient; private Builder() {} @@ -62,9 +67,16 @@ Builder setDdlClient(DdlClient client) { return this; } + Builder setDatabaseClient(DatabaseClient client) { + Preconditions.checkNotNull(client); + this.dbClient = client; + return this; + } + @Override DdlBatch build() { Preconditions.checkState(ddlClient != null, "No DdlClient specified"); + Preconditions.checkState(dbClient != null, "No DbClient specified"); return new DdlBatch(this); } } @@ -76,6 +88,7 @@ static Builder newBuilder() { private DdlBatch(Builder builder) { super(builder); this.ddlClient = builder.ddlClient; + this.dbClient = builder.dbClient; } @Override @@ -100,7 +113,31 @@ public boolean isReadOnly() { @Override public ResultSet executeQuery( - ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { + final ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { + if (options != null) { + for (int i = 0; i < options.length; i++) { + if (options[i] instanceof InternalMetadataQuery) { + Preconditions.checkNotNull(statement); + Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); + Preconditions.checkArgument( + analyzeMode == AnalyzeMode.NONE, "Analyze is not allowed for DDL batch"); + // Queries marked with internal metadata queries are allowed during a DDL batch. + // These can only be generated by library internal methods and may be used to check + // whether a database object such as table or an index exists. + final QueryOption[] internalOptions = ArrayUtils.remove(options, i); + Callable callable = + new Callable() { + @Override + public ResultSet call() throws Exception { + return DirectExecuteResultSet.ofResultSet( + dbClient.singleUse().executeQuery(statement.getStatement(), internalOptions)); + } + }; + return asyncExecuteStatement(statement, callable); + } + } + } + // Queries are by default not allowed on DDL batches. throw SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "Executing queries is not allowed for DDL batches."); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index c71c21b74086..08b2a823b619 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -56,7 +56,7 @@ public Statement createStatement() throws SQLException { } @Override - public PreparedStatement prepareStatement(String sql) throws SQLException { + public JdbcPreparedStatement prepareStatement(String sql) throws SQLException { checkClosed(); return new JdbcPreparedStatement(this, sql); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 9ab38d9d2254..a15ad721ee4f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -23,12 +23,13 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; +import com.google.common.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLException; @@ -45,8 +46,9 @@ class JdbcDatabaseMetaData extends AbstractJdbcWrapper implements DatabaseMetaDa private static final int DATABASE_MINOR_VERSION = 0; private static final String PRODUCT_NAME = "Google Cloud Spanner"; - private String readSqlFromFile(String filename) { - InputStream in = getClass().getResourceAsStream(filename); + @VisibleForTesting + static String readSqlFromFile(String filename) { + InputStream in = JdbcDatabaseMetaData.class.getResourceAsStream(filename); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder builder = new StringBuilder(); try (Scanner scanner = new Scanner(reader)) { @@ -721,9 +723,9 @@ public ResultSet getProcedureColumns( Collections.emptyList())); } - private PreparedStatement prepareStatementReplaceNullWithAnyString(String sql, String... params) - throws SQLException { - PreparedStatement statement = connection.prepareStatement(sql); + private JdbcPreparedStatement prepareStatementReplaceNullWithAnyString( + String sql, String... params) throws SQLException { + JdbcPreparedStatement statement = connection.prepareStatement(sql); int paramIndex = 1; for (String param : params) { if (param == null) { @@ -753,10 +755,10 @@ public ResultSet getTables( type1 = types[0]; type2 = types[1]; } - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString( sql, catalog, schemaPattern, tableNamePattern, type1, type2); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -787,10 +789,10 @@ public ResultSet getColumns( String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { String sql = readSqlFromFile("DatabaseMetaData_GetColumns.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString( sql, catalog, schemaPattern, tableNamePattern, columnNamePattern); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -865,9 +867,9 @@ public ResultSet getVersionColumns(String catalog, String schema, String table) public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { JdbcPreconditions.checkArgument(table != null, "table may not be null"); String sql = readSqlFromFile("DatabaseMetaData_GetPrimaryKeys.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -875,9 +877,9 @@ public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { JdbcPreconditions.checkArgument(table != null, "table may not be null"); String sql = readSqlFromFile("DatabaseMetaData_GetImportedKeys.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -885,9 +887,9 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { JdbcPreconditions.checkArgument(table != null, "table may not be null"); String sql = readSqlFromFile("DatabaseMetaData_GetExportedKeys.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString(sql, catalog, schema, table); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -900,7 +902,7 @@ public ResultSet getCrossReference( String foreignTable) throws SQLException { String sql = readSqlFromFile("DatabaseMetaData_GetCrossReferences.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString( sql, parentCatalog, @@ -909,7 +911,7 @@ public ResultSet getCrossReference( foreignCatalog, foreignSchema, foreignTable); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -1220,10 +1222,10 @@ private ResultSet getIndexInfo( String catalog, String schema, String table, String indexName, boolean unique) throws SQLException { String sql = readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString( sql, catalog, schema, table, indexName, unique ? "YES" : "%"); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override @@ -1440,9 +1442,9 @@ public RowIdLifetime getRowIdLifetime() throws SQLException { @Override public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { String sql = readSqlFromFile("DatabaseMetaData_GetSchemas.sql"); - PreparedStatement statement = + JdbcPreparedStatement statement = prepareStatementReplaceNullWithAnyString(sql, catalog, schemaPattern); - return statement.executeQuery(); + return statement.executeQueryWithOptions(InternalMetadataQuery.INSTANCE); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index a42720ddc550..4d5cfe88955d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/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.Options.QueryOption; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; import java.sql.PreparedStatement; @@ -55,6 +56,11 @@ public ResultSet executeQuery() throws SQLException { return executeQuery(createStatement()); } + ResultSet executeQueryWithOptions(QueryOption... options) throws SQLException { + checkClosed(); + return executeQuery(createStatement(), options); + } + @Override public int executeUpdate() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java index 68234b599188..3700f4c71a11 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java @@ -32,12 +32,16 @@ import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ReadContext; +import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; import com.google.cloud.spanner.jdbc.StatementParser.StatementType; import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; @@ -121,8 +125,13 @@ private DdlBatch createSubject() { } private DdlBatch createSubject(DdlClient ddlClient) { + return createSubject(ddlClient, mock(DatabaseClient.class)); + } + + private DdlBatch createSubject(DdlClient ddlClient, DatabaseClient dbClient) { return DdlBatch.newBuilder() .setDdlClient(ddlClient) + .setDatabaseClient(dbClient) .withStatementExecutor(new StatementExecutor()) .build(); } @@ -134,6 +143,25 @@ public void testExecuteQuery() { batch.executeQuery(mock(ParsedStatement.class), AnalyzeMode.NONE); } + @Test + public void testExecuteMetadataQuery() { + Statement statement = Statement.of("SELECT * FROM INFORMATION_SCHEMA.TABLES"); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.isQuery()).thenReturn(true); + when(parsedStatement.getStatement()).thenReturn(statement); + DatabaseClient dbClient = mock(DatabaseClient.class); + ReadContext singleUse = mock(ReadContext.class); + ResultSet resultSet = mock(ResultSet.class); + when(singleUse.executeQuery(statement)).thenReturn(resultSet); + when(dbClient.singleUse()).thenReturn(singleUse); + DdlBatch batch = createSubject(createDefaultMockDdlClient(), dbClient); + assertThat( + batch + .executeQuery(parsedStatement, AnalyzeMode.NONE, InternalMetadataQuery.INSTANCE) + .hashCode(), + is(equalTo(resultSet.hashCode()))); + } + @Test public void testExecuteUpdate() { DdlBatch batch = createSubject(); @@ -331,6 +359,7 @@ public void testUpdateCount() throws InterruptedException, ExecutionException { DdlBatch.newBuilder() .withStatementExecutor(new StatementExecutor()) .setDdlClient(client) + .setDatabaseClient(mock(DatabaseClient.class)) .build(); batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE BAR"))); @@ -362,6 +391,7 @@ public void testFailedUpdateCount() throws InterruptedException, ExecutionExcept DdlBatch.newBuilder() .withStatementExecutor(new StatementExecutor()) .setDdlClient(client) + .setDatabaseClient(mock(DatabaseClient.class)) .build(); batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE INVALID_TABLE"))); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java new file mode 100644 index 000000000000..95e0acae24ef --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java @@ -0,0 +1,299 @@ +/* + * Copyright 2019 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.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +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 io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcDatabaseMetaDataWithMockedServerTest { + private static final ResultSetMetadata RESULTSET_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("TAB1") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build(); + private static final com.google.spanner.v1.ResultSet RESULTSET = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("TAB").build()) + .build()) + .setMetadata(RESULTSET_METADATA) + .build(); + + private static MockSpannerServiceImpl mockSpanner; + private static Server server; + private static InetSocketAddress address; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + @After + public void reset() { + // Close Spanner pool to prevent reusage of the same Spanner instance (and thereby the same + // session pool). + SpannerPool.closeSpannerPool(); + mockSpanner.removeAllExecutionTimes(); + mockSpanner.reset(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + server.getPort(), "proj", "inst", "db"); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void getTablesInDdlBatch() throws SQLException { + String sql = + StatementParser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetTables.sql")); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("CAT") + .bind("p2") + .to("SCH") + .bind("p3") + .to("TAB") + .bind("p4") + .to("TABLE") + .bind("p5") + .to("VIEW") + .build(), + RESULTSET)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + // Executing an internal metadata query should be allowed during a DDL batch. + // This query will be executed on a single use read-only transaction. + try (ResultSet tables = connection.getMetaData().getTables("CAT", "SCH", "TAB", null)) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } + + @Test + public void getColumnsInDdlBatch() throws SQLException { + String sql = + StatementParser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetColumns.sql")); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("CAT") + .bind("p2") + .to("SCH") + .bind("p3") + .to("TAB") + .bind("p4") + .to("%") + .build(), + RESULTSET)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + try (ResultSet tables = connection.getMetaData().getColumns("CAT", "SCH", "TAB", null)) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } + + @Test + public void getKeysInDdlBatch() throws SQLException { + for (String fileName : + new String[] { + "DatabaseMetaData_GetPrimaryKeys.sql", + "DatabaseMetaData_GetImportedKeys.sql", + "DatabaseMetaData_GetExportedKeys.sql" + }) { + String sql = + StatementParser.removeCommentsAndTrim(JdbcDatabaseMetaData.readSqlFromFile(fileName)); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("CAT") + .bind("p2") + .to("SCH") + .bind("p3") + .to("TAB") + .build(), + RESULTSET)); + } + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + try (ResultSet tables = connection.getMetaData().getPrimaryKeys("CAT", "SCH", "TAB")) { + while (tables.next()) {} + } + try (ResultSet tables = connection.getMetaData().getImportedKeys("CAT", "SCH", "TAB")) { + while (tables.next()) {} + } + try (ResultSet tables = connection.getMetaData().getExportedKeys("CAT", "SCH", "TAB")) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } + + @Test + public void getCrossReferencesInDdlBatch() throws SQLException { + String sql = + StatementParser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetCrossReferences.sql")); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("CAT") + .bind("p2") + .to("SCH") + .bind("p3") + .to("TAB") + .bind("p4") + .to("CAT2") + .bind("p5") + .to("SCH2") + .bind("p6") + .to("TAB2") + .build(), + RESULTSET)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + try (ResultSet tables = + connection.getMetaData().getCrossReference("CAT", "SCH", "TAB", "CAT2", "SCH2", "TAB2")) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } + + @Test + public void getIndexInfoInDdlBatch() throws SQLException { + String sql = + StatementParser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql")); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("CAT") + .bind("p2") + .to("SCH") + .bind("p3") + .to("TAB") + .bind("p4") + .to("%") + .bind("p5") + .to("YES") + .build(), + RESULTSET)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + try (ResultSet tables = + connection.getMetaData().getIndexInfo("CAT", "SCH", "TAB", true, false)) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } + + @Test + public void getSchemasInDdlBatch() throws SQLException { + String sql = + StatementParser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetSchemas.sql")); + ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder(params.sqlWithNamedParameters) + .bind("p1") + .to("%") + .bind("p2") + .to("%") + .build(), + RESULTSET)); + try (java.sql.Connection connection = createConnection()) { + connection.createStatement().execute("START BATCH DDL"); + try (ResultSet tables = connection.getMetaData().getSchemas()) { + while (tables.next()) {} + } + try (ResultSet tables = connection.getMetaData().getSchemas(null, null)) { + while (tables.next()) {} + } + connection.createStatement().execute("CREATE TABLE FOO"); + connection.createStatement().execute("ABORT BATCH"); + } + } +} From 14902164ae2fbd0c2a41d48a031d931216580c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 5 Dec 2019 03:38:56 +0100 Subject: [PATCH 0063/1979] filter unwanted files from META-INF directory (#6956) --- java-spanner-jdbc/pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1f3f44e654dd..5e82136bca79 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,6 +166,17 @@ com.google.cloud.spanner.jdbc *.sql + + + META-INF/SIGNINGC.RSA + META-INF/SIGNINGC.SF + META-INF/DEPENDENCIES + META-INF/LICENSE + META-INF/LICENSE.txt + META-INF/NOTICE + META-INF/NOTICE.txt + + From fc2915ecc46a8a3ebb5266d17b439f9b8d39a44c Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 5 Dec 2019 11:05:16 -0500 Subject: [PATCH 0064/1979] Release v0.120.0 (#6988) --- java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0f9de64d1b5b..666bc7384d72 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.11.0 + 1.12.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.11.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.12.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.11.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.12.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5e82136bca79..9348bd1700fc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.11.1-SNAPSHOT + 1.12.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.119.1-alpha-SNAPSHOT + 0.120.0-alpha google-cloud-spanner-jdbc @@ -23,12 +23,12 @@ com.google.cloud google-cloud-spanner - 1.46.1-SNAPSHOT + 1.47.0 com.google.cloud google-cloud-spanner - 1.46.1-SNAPSHOT + 1.47.0 test-jar test From bb702b7fd87a1a3ace48590fc505245baaeeb1e7 Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:36:03 -0500 Subject: [PATCH 0065/1979] Bump next snapshot (#6989) --- java-spanner-jdbc/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9348bd1700fc..74f2bbfca0ff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.12.0 + 1.12.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc @@ -14,7 +14,7 @@ com.google.cloud google-cloud-contrib - 0.120.0-alpha + 0.120.1-alpha-SNAPSHOT google-cloud-spanner-jdbc @@ -23,12 +23,12 @@ com.google.cloud google-cloud-spanner - 1.47.0 + 1.47.1-SNAPSHOT com.google.cloud google-cloud-spanner - 1.47.0 + 1.47.1-SNAPSHOT test-jar test From ff4716471648301770e8128b5d67777b5e0187dd Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 18 Dec 2019 21:36:17 -0600 Subject: [PATCH 0066/1979] Make sure failsafe and surefire plugin versions match (#7029) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 74f2bbfca0ff..bde10c67c3be 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -64,7 +64,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M3 + 3.0.0-M4 com.google.cloud.spanner.GceTestEnvConfig From 31753360282134833c572eb43848a28b8f00b70c Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Mon, 30 Dec 2019 16:16:27 -0700 Subject: [PATCH 0067/1979] chore: make repo releasable (#4) * chore: make repo releasable * fix pom --- .../.github/ISSUE_TEMPLATE/bug_report.md | 51 +++ .../.github/ISSUE_TEMPLATE/feature_request.md | 21 ++ .../.github/ISSUE_TEMPLATE/support_request.md | 7 + .../.github/PULL_REQUEST_TEMPLATE.md | 1 + java-spanner-jdbc/.github/release-please.yml | 1 + java-spanner-jdbc/.gitignore | 42 +++ java-spanner-jdbc/.kokoro/build.bat | 3 + java-spanner-jdbc/.kokoro/build.sh | 60 ++++ java-spanner-jdbc/.kokoro/coerce_logs.sh | 38 ++ java-spanner-jdbc/.kokoro/common.cfg | 13 + .../.kokoro/continuous/common.cfg | 25 ++ .../.kokoro/continuous/dependencies.cfg | 12 + .../.kokoro/continuous/integration.cfg | 7 + .../.kokoro/continuous/java11.cfg | 7 + .../.kokoro/continuous/java7.cfg | 7 + .../.kokoro/continuous/java8-osx.cfg | 3 + .../.kokoro/continuous/java8-win.cfg | 3 + .../.kokoro/continuous/java8.cfg | 7 + java-spanner-jdbc/.kokoro/continuous/lint.cfg | 13 + .../.kokoro/continuous/propose_release.cfg | 53 +++ .../.kokoro/continuous/propose_release.sh | 29 ++ java-spanner-jdbc/.kokoro/dependencies.sh | 27 ++ java-spanner-jdbc/.kokoro/linkage-monitor.sh | 33 ++ java-spanner-jdbc/.kokoro/nightly/common.cfg | 25 ++ .../.kokoro/nightly/dependencies.cfg | 12 + .../.kokoro/nightly/integration.cfg | 7 + java-spanner-jdbc/.kokoro/nightly/java11.cfg | 7 + java-spanner-jdbc/.kokoro/nightly/java7.cfg | 7 + .../.kokoro/nightly/java8-osx.cfg | 3 + .../.kokoro/nightly/java8-win.cfg | 3 + java-spanner-jdbc/.kokoro/nightly/java8.cfg | 7 + java-spanner-jdbc/.kokoro/nightly/lint.cfg | 13 + java-spanner-jdbc/.kokoro/presubmit/clirr.cfg | 13 + .../.kokoro/presubmit/common.cfg | 34 ++ .../.kokoro/presubmit/dependencies.cfg | 12 + .../.kokoro/presubmit/integration.cfg | 31 ++ .../.kokoro/presubmit/java11.cfg | 7 + java-spanner-jdbc/.kokoro/presubmit/java7.cfg | 7 + .../.kokoro/presubmit/java8-osx.cfg | 3 + .../.kokoro/presubmit/java8-win.cfg | 3 + java-spanner-jdbc/.kokoro/presubmit/java8.cfg | 7 + .../.kokoro/presubmit/linkage-monitor.cfg | 12 + java-spanner-jdbc/.kokoro/presubmit/lint.cfg | 13 + .../.kokoro/release/bump_snapshot.cfg | 53 +++ .../.kokoro/release/bump_snapshot.sh | 30 ++ java-spanner-jdbc/.kokoro/release/common.cfg | 49 +++ java-spanner-jdbc/.kokoro/release/common.sh | 50 +++ java-spanner-jdbc/.kokoro/release/drop.cfg | 9 + java-spanner-jdbc/.kokoro/release/drop.sh | 32 ++ java-spanner-jdbc/.kokoro/release/promote.cfg | 10 + java-spanner-jdbc/.kokoro/release/promote.sh | 34 ++ .../.kokoro/release/publish_javadoc.cfg | 19 + .../.kokoro/release/publish_javadoc.sh | 55 +++ .../.kokoro/release/snapshot.cfg | 6 + java-spanner-jdbc/.kokoro/release/snapshot.sh | 33 ++ java-spanner-jdbc/.kokoro/release/stage.cfg | 44 +++ java-spanner-jdbc/.kokoro/release/stage.sh | 42 +++ java-spanner-jdbc/.kokoro/trampoline.sh | 24 ++ java-spanner-jdbc/.repo-metadata.json | 10 + java-spanner-jdbc/CODE_OF_CONDUCT.md | 93 +++++ java-spanner-jdbc/CONTRIBUTING.md | 28 ++ java-spanner-jdbc/LICENSE | 5 +- java-spanner-jdbc/codecov.yaml | 4 + java-spanner-jdbc/java.header | 15 + java-spanner-jdbc/license-checks.xml | 10 + java-spanner-jdbc/pom.xml | 336 +++++++++++++++++- java-spanner-jdbc/renovate.json | 27 ++ java-spanner-jdbc/synth.py | 25 ++ java-spanner-jdbc/versions.txt | 0 69 files changed, 1718 insertions(+), 14 deletions(-) create mode 100644 java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 java-spanner-jdbc/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 java-spanner-jdbc/.github/ISSUE_TEMPLATE/support_request.md create mode 100644 java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 java-spanner-jdbc/.github/release-please.yml create mode 100644 java-spanner-jdbc/.gitignore create mode 100644 java-spanner-jdbc/.kokoro/build.bat create mode 100755 java-spanner-jdbc/.kokoro/build.sh create mode 100755 java-spanner-jdbc/.kokoro/coerce_logs.sh create mode 100644 java-spanner-jdbc/.kokoro/common.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/common.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/dependencies.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/integration.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/java11.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/java7.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/java8-win.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/java8.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/lint.cfg create mode 100644 java-spanner-jdbc/.kokoro/continuous/propose_release.cfg create mode 100755 java-spanner-jdbc/.kokoro/continuous/propose_release.sh create mode 100755 java-spanner-jdbc/.kokoro/dependencies.sh create mode 100755 java-spanner-jdbc/.kokoro/linkage-monitor.sh create mode 100644 java-spanner-jdbc/.kokoro/nightly/common.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/dependencies.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/integration.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/java11.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/java7.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/java8-osx.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/java8-win.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/java8.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/lint.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/clirr.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/common.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/dependencies.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/integration.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java11.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java7.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java8-osx.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java8-win.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java8.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/linkage-monitor.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/lint.cfg create mode 100644 java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/bump_snapshot.sh create mode 100644 java-spanner-jdbc/.kokoro/release/common.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/common.sh create mode 100644 java-spanner-jdbc/.kokoro/release/drop.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/drop.sh create mode 100644 java-spanner-jdbc/.kokoro/release/promote.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/promote.sh create mode 100644 java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/publish_javadoc.sh create mode 100644 java-spanner-jdbc/.kokoro/release/snapshot.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/snapshot.sh create mode 100644 java-spanner-jdbc/.kokoro/release/stage.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/stage.sh create mode 100644 java-spanner-jdbc/.kokoro/trampoline.sh create mode 100644 java-spanner-jdbc/.repo-metadata.json create mode 100644 java-spanner-jdbc/CODE_OF_CONDUCT.md create mode 100644 java-spanner-jdbc/CONTRIBUTING.md create mode 100644 java-spanner-jdbc/codecov.yaml create mode 100644 java-spanner-jdbc/java.header create mode 100644 java-spanner-jdbc/license-checks.xml create mode 100644 java-spanner-jdbc/renovate.json create mode 100644 java-spanner-jdbc/synth.py create mode 100644 java-spanner-jdbc/versions.txt diff --git a/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000000..e1182687675c --- /dev/null +++ b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,51 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +Thanks for stopping by to let us know something could be better! + +**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. + +Please run down the following list and make sure you've tried the usual "quick fixes": + + - Search the issues already opened: https://github.com/googleapis/java-spanner-jdbc/issues + - Check for answers on StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform + +If you are still having issues, please include as much information as possible: + +#### Environment details + +1. Specify the API at the beginning of the title. For example, "BigQuery: ..."). + General, Core, and Other are also allowed as types +2. OS type and version: +3. Java version: +4. spanner-jdbc version(s): + +#### Steps to reproduce + + 1. ? + 2. ? + +#### Code example + +```java +// example +``` + +#### Stack trace +``` +Any relevant stacktrace here. +``` + +#### External references such as API reference guides + +- ? + +#### Any additional information below + + +Following these steps guarantees the quickest resolution possible. + +Thanks! diff --git a/java-spanner-jdbc/.github/ISSUE_TEMPLATE/feature_request.md b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000000..754e30c68a00 --- /dev/null +++ b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- +name: Feature request +about: Suggest an idea for this library + +--- + +Thanks for stopping by to let us know something could be better! + +**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. + +**Is your feature request related to a problem? Please describe.** +What the problem is. Example: I'm always frustrated when [...] + +**Describe the solution you'd like** +What you want to happen. + +**Describe alternatives you've considered** +Any alternative solutions or features you've considered. + +**Additional context** +Any other context or screenshots about the feature request. diff --git a/java-spanner-jdbc/.github/ISSUE_TEMPLATE/support_request.md b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/support_request.md new file mode 100644 index 000000000000..995869032125 --- /dev/null +++ b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/support_request.md @@ -0,0 +1,7 @@ +--- +name: Support request +about: If you have a support contract with Google, please create an issue in the Google Cloud Support console. + +--- + +**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. diff --git a/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000000..0bd0ee0620f9 --- /dev/null +++ b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1 @@ +Fixes # (it's a good idea to open an issue first for context and/or discussion) \ No newline at end of file diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml new file mode 100644 index 000000000000..827446828034 --- /dev/null +++ b/java-spanner-jdbc/.github/release-please.yml @@ -0,0 +1 @@ +releaseType: java-yoshi diff --git a/java-spanner-jdbc/.gitignore b/java-spanner-jdbc/.gitignore new file mode 100644 index 000000000000..48876580084e --- /dev/null +++ b/java-spanner-jdbc/.gitignore @@ -0,0 +1,42 @@ +# Packages +dist +bin +var +sdist +target + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg + +.metadata +.project +.pydevproject +*.iml +.idea +.settings +.DS_Store +.classpath + +# Built documentation +docs/ + + +# Wheel directory used in Travis builds. +gcloud-java-wheels/ +src/test/resources/gcd-head.zip +src/test/resources/gcd-v1beta2-rev1-2.1.1.zip + +# API key file containing value of GOOGLE_API_KEY for integration tests +api_key + +# Python utilities +*.pyc +artman-genfiles \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/build.bat b/java-spanner-jdbc/.kokoro/build.bat new file mode 100644 index 000000000000..680ad2804149 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/build.bat @@ -0,0 +1,3 @@ +:: See documentation in type-shell-output.bat + +"C:\Program Files\Git\bin\bash.exe" github/java-spanner-jdbc/.kokoro/build.sh diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh new file mode 100755 index 000000000000..fa132f410dcc --- /dev/null +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright 2019 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. + +set -eo pipefail + +## Get the directory of the build script +scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) +## cd to the parent directory, i.e. the root of the git repo +cd ${scriptDir}/.. + +# Print out Java version +java -version +echo ${JOB_TYPE} + +mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true \ + -Dmaven.javadoc.skip=true \ + -Dgcloud.download.skip=true \ + -T 1C + +# if GOOGLE_APPLICATION_CREDIENTIALS is specified as a relative path prepend Kokoro root directory onto it +if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTIALS}" != /* ]]; then + export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_ROOT}/src/${GOOGLE_APPLICATION_CREDENTIALS}) +fi + +case ${JOB_TYPE} in +test) + mvn test -B -Dclirr.skip=true + bash ${KOKORO_GFILE_DIR}/codecov.sh + bash .kokoro/coerce_logs.sh + ;; +lint) + mvn com.coveo:fmt-maven-plugin:check + ;; +javadoc) + mvn javadoc:javadoc javadoc:test-javadoc + ;; +integration) + mvn -B ${INTEGRATION_TEST_ARGS} -DtrimStackTrace=false -Dclirr.skip=true -fae verify + bash .kokoro/coerce_logs.sh + ;; +clirr) + mvn -B clirr:check + ;; +*) + ;; +esac \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/coerce_logs.sh b/java-spanner-jdbc/.kokoro/coerce_logs.sh new file mode 100755 index 000000000000..5cf7ba49e6bb --- /dev/null +++ b/java-spanner-jdbc/.kokoro/coerce_logs.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright 2019 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. + +# This script finds and moves sponge logs so that they can be found by placer +# and are not flagged as flaky by sponge. + +set -eo pipefail + +## Get the directory of the build script +scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) +## cd to the parent directory, i.e. the root of the git repo +cd ${scriptDir}/.. + +job=$(basename ${KOKORO_JOB_NAME}) + +echo "coercing sponge logs..." +for xml in `find . -name *-sponge_log.xml` +do + echo "processing ${xml}" + class=$(basename ${xml} | cut -d- -f2) + dir=$(dirname ${xml})/${job}/${class} + text=$(dirname ${xml})/${class}-sponge_log.txt + mkdir -p ${dir} + mv ${xml} ${dir}/sponge_log.xml + mv ${text} ${dir}/sponge_log.txt +done diff --git a/java-spanner-jdbc/.kokoro/common.cfg b/java-spanner-jdbc/.kokoro/common.cfg new file mode 100644 index 000000000000..bc068f6cb0ab --- /dev/null +++ b/java-spanner-jdbc/.kokoro/common.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Download trampoline resources. These will be in ${KOKORO_GFILE_DIR} +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# All builds use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +# Tell the trampoline which build file to use. +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/common.cfg b/java-spanner-jdbc/.kokoro/continuous/common.cfg new file mode 100644 index 000000000000..dbc14991ac47 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/common.cfg @@ -0,0 +1,25 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.txt" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "test" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg b/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg new file mode 100644 index 000000000000..2d09bcc0ac01 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg @@ -0,0 +1,12 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/dependencies.sh" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/integration.cfg b/java-spanner-jdbc/.kokoro/continuous/integration.cfg new file mode 100644 index 000000000000..3b017fc80f04 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/integration.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/java11.cfg b/java-spanner-jdbc/.kokoro/continuous/java11.cfg new file mode 100644 index 000000000000..709f2b4c73db --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/java11.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/java7.cfg b/java-spanner-jdbc/.kokoro/continuous/java7.cfg new file mode 100644 index 000000000000..cb24f44eea3b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg b/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg new file mode 100644 index 000000000000..c6980278d0ce --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.sh" diff --git a/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg b/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg new file mode 100644 index 000000000000..90e4b928aa49 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.bat" diff --git a/java-spanner-jdbc/.kokoro/continuous/java8.cfg b/java-spanner-jdbc/.kokoro/continuous/java8.cfg new file mode 100644 index 000000000000..3b017fc80f04 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/java8.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/lint.cfg b/java-spanner-jdbc/.kokoro/continuous/lint.cfg new file mode 100644 index 000000000000..6d323c8ae768 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/lint.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. + +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "lint" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg b/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg new file mode 100644 index 000000000000..1b7a1affa1cb --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg @@ -0,0 +1,53 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/continuous/propose_release.sh" +} + +# tokens used by release-please to keep an up-to-date release PR. +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-key-release-please" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-token-release-please" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-url-release-please" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/continuous/propose_release.sh b/java-spanner-jdbc/.kokoro/continuous/propose_release.sh new file mode 100755 index 000000000000..c2fb269ef2ec --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/propose_release.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright 2019 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 +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +export NPM_CONFIG_PREFIX=/home/node/.npm-global + +if [ -f ${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please ]; then + # Groom the release PR as new commits are merged. + npx release-please release-pr --token=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-token-release-please \ + --repo-url=googleapis/java-spanner-jdbc \ + --package-name="spanner-jdbc" \ + --api-url=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please \ + --proxy-key=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-key-release-please \ + --release-type=java-yoshi +fi diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh new file mode 100755 index 000000000000..50c307400c33 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2019 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. + +set -eo pipefail + +cd github/java-spanner-jdbc/ + +# Print out Java +java -version +echo $JOB_TYPE + +export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" + +mvn install -DskipTests=true -B -V +mvn -B dependency:analyze -DfailOnWarning=true diff --git a/java-spanner-jdbc/.kokoro/linkage-monitor.sh b/java-spanner-jdbc/.kokoro/linkage-monitor.sh new file mode 100755 index 000000000000..a3e5ab30e5b3 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/linkage-monitor.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Copyright 2019 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. + +set -eo pipefail +# Display commands being run. +set -x + +cd github/java-spanner-jdbc/ + +# Print out Java version +java -version +echo ${JOB_TYPE} + +mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgcloud.download.skip=true -B -V + +# Kokoro job cloud-opensource-java/ubuntu/linkage-monitor-gcs creates this JAR +JAR=linkage-monitor-latest-all-deps.jar +curl -v -O "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/${JAR}" + +# Fails if there's new linkage errors compared with baseline +java -jar ${JAR} com.google.cloud:libraries-bom diff --git a/java-spanner-jdbc/.kokoro/nightly/common.cfg b/java-spanner-jdbc/.kokoro/nightly/common.cfg new file mode 100644 index 000000000000..dbc14991ac47 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/common.cfg @@ -0,0 +1,25 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.txt" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "test" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg b/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg new file mode 100644 index 000000000000..2d09bcc0ac01 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg @@ -0,0 +1,12 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/dependencies.sh" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg new file mode 100644 index 000000000000..3b017fc80f04 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/java11.cfg b/java-spanner-jdbc/.kokoro/nightly/java11.cfg new file mode 100644 index 000000000000..709f2b4c73db --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java11.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/java7.cfg b/java-spanner-jdbc/.kokoro/nightly/java7.cfg new file mode 100644 index 000000000000..cb24f44eea3b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/java8-osx.cfg b/java-spanner-jdbc/.kokoro/nightly/java8-osx.cfg new file mode 100644 index 000000000000..c6980278d0ce --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java8-osx.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.sh" diff --git a/java-spanner-jdbc/.kokoro/nightly/java8-win.cfg b/java-spanner-jdbc/.kokoro/nightly/java8-win.cfg new file mode 100644 index 000000000000..90e4b928aa49 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java8-win.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.bat" diff --git a/java-spanner-jdbc/.kokoro/nightly/java8.cfg b/java-spanner-jdbc/.kokoro/nightly/java8.cfg new file mode 100644 index 000000000000..3b017fc80f04 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java8.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/lint.cfg b/java-spanner-jdbc/.kokoro/nightly/lint.cfg new file mode 100644 index 000000000000..6d323c8ae768 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/lint.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. + +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "lint" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/presubmit/clirr.cfg b/java-spanner-jdbc/.kokoro/presubmit/clirr.cfg new file mode 100644 index 000000000000..ec572442e2e7 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/clirr.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. + +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "clirr" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/presubmit/common.cfg b/java-spanner-jdbc/.kokoro/presubmit/common.cfg new file mode 100644 index 000000000000..175502fdc964 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/common.cfg @@ -0,0 +1,34 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.txt" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "test" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "dpebot_codecov_token" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/dependencies.cfg b/java-spanner-jdbc/.kokoro/presubmit/dependencies.cfg new file mode 100644 index 000000000000..2d09bcc0ac01 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/dependencies.cfg @@ -0,0 +1,12 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/dependencies.sh" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg new file mode 100644 index 000000000000..141f90c13c56 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -0,0 +1,31 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration" +} + +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "java_it_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/java11.cfg b/java-spanner-jdbc/.kokoro/presubmit/java11.cfg new file mode 100644 index 000000000000..709f2b4c73db --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java11.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/java7.cfg b/java-spanner-jdbc/.kokoro/presubmit/java7.cfg new file mode 100644 index 000000000000..cb24f44eea3b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/java8-osx.cfg b/java-spanner-jdbc/.kokoro/presubmit/java8-osx.cfg new file mode 100644 index 000000000000..c6980278d0ce --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java8-osx.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.sh" diff --git a/java-spanner-jdbc/.kokoro/presubmit/java8-win.cfg b/java-spanner-jdbc/.kokoro/presubmit/java8-win.cfg new file mode 100644 index 000000000000..90e4b928aa49 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java8-win.cfg @@ -0,0 +1,3 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "java-spanner-jdbc/.kokoro/build.bat" diff --git a/java-spanner-jdbc/.kokoro/presubmit/java8.cfg b/java-spanner-jdbc/.kokoro/presubmit/java8.cfg new file mode 100644 index 000000000000..3b017fc80f04 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java8.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/linkage-monitor.cfg b/java-spanner-jdbc/.kokoro/presubmit/linkage-monitor.cfg new file mode 100644 index 000000000000..0e904ec1f1de --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/linkage-monitor.cfg @@ -0,0 +1,12 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/linkage-monitor.sh" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/presubmit/lint.cfg b/java-spanner-jdbc/.kokoro/presubmit/lint.cfg new file mode 100644 index 000000000000..6d323c8ae768 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/lint.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. + +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "lint" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg b/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg new file mode 100644 index 000000000000..3dc06f216777 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg @@ -0,0 +1,53 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh" +} + +# tokens used by release-please to keep an up-to-date release PR. +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-key-release-please" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-token-release-please" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "github-magic-proxy-url-release-please" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh b/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh new file mode 100755 index 000000000000..4d76d4393c67 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Copyright 2019 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 +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eo pipefail + +export NPM_CONFIG_PREFIX=/home/node/.npm-global + +if [ -f ${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please ]; then + # Groom the snapshot release PR immediately after publishing a release + npx release-please release-pr --token=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-token-release-please \ + --repo-url=googleapis/java-spanner-jdbc \ + --package-name="spanner-jdbc" \ + --api-url=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please \ + --proxy-key=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-key-release-please \ + --snapshot \ + --release-type=java-auth-yoshi +fi diff --git a/java-spanner-jdbc/.kokoro/release/common.cfg b/java-spanner-jdbc/.kokoro/release/common.cfg new file mode 100644 index 000000000000..2ace079c9a1e --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/common.cfg @@ -0,0 +1,49 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-keyring" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-passphrase" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "maven-gpg-pubkeyring" + } + } +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 70247 + keyname: "sonatype-credentials" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/release/common.sh b/java-spanner-jdbc/.kokoro/release/common.sh new file mode 100755 index 000000000000..6e3f65999b3d --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/common.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright 2018 Google Inc. +# +# 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. + +set -eo pipefail + +# Get secrets from keystore and set and environment variables +setup_environment_secrets() { + export GPG_PASSPHRASE=$(cat ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-passphrase) + export GPG_TTY=$(tty) + export GPG_HOMEDIR=/gpg + mkdir $GPG_HOMEDIR + mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-pubkeyring $GPG_HOMEDIR/pubring.gpg + mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-keyring $GPG_HOMEDIR/secring.gpg + export SONATYPE_USERNAME=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f1 -d'|') + export SONATYPE_PASSWORD=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f2 -d'|') +} + +create_settings_xml_file() { + echo " + + + ossrh + ${SONATYPE_USERNAME} + ${SONATYPE_PASSWORD} + + + sonatype-nexus-staging + ${SONATYPE_USERNAME} + ${SONATYPE_PASSWORD} + + + sonatype-nexus-snapshots + ${SONATYPE_USERNAME} + ${SONATYPE_PASSWORD} + + +" > $1 +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/drop.cfg b/java-spanner-jdbc/.kokoro/release/drop.cfg new file mode 100644 index 000000000000..93afddf54a55 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/drop.cfg @@ -0,0 +1,9 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/drop.sh" +} + +# Download staging properties file. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/java/releases/java-spanner-jdbc" \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/drop.sh b/java-spanner-jdbc/.kokoro/release/drop.sh new file mode 100755 index 000000000000..5c4551efa2c0 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/drop.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright 2018 Google Inc. +# +# 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. + +set -eo pipefail + +# STAGING_REPOSITORY_ID must be set +if [ -z "${STAGING_REPOSITORY_ID}" ]; then + echo "Missing STAGING_REPOSITORY_ID environment variable" + exit 1 +fi + +source $(dirname "$0")/common.sh +pushd $(dirname "$0")/../../ + +setup_environment_secrets +create_settings_xml_file "settings.xml" + +mvn nexus-staging:drop -B \ + --settings=settings.xml \ + -DstagingRepositoryId=${STAGING_REPOSITORY_ID} diff --git a/java-spanner-jdbc/.kokoro/release/promote.cfg b/java-spanner-jdbc/.kokoro/release/promote.cfg new file mode 100644 index 000000000000..978cde7960d8 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/promote.cfg @@ -0,0 +1,10 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/promote.sh" +} + +# Download staging properties file. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/java/releases/java-spanner-jdbc" + diff --git a/java-spanner-jdbc/.kokoro/release/promote.sh b/java-spanner-jdbc/.kokoro/release/promote.sh new file mode 100755 index 000000000000..1fa95fa537a3 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/promote.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Copyright 2018 Google Inc. +# +# 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. + +set -eo pipefail + +# STAGING_REPOSITORY_ID must be set +if [ -z "${STAGING_REPOSITORY_ID}" ]; then + echo "Missing STAGING_REPOSITORY_ID environment variable" + exit 1 +fi + +source $(dirname "$0")/common.sh + +pushd $(dirname "$0")/../../ + +setup_environment_secrets +create_settings_xml_file "settings.xml" + +mvn nexus-staging:release -B \ + -DperformRelease=true \ + --settings=settings.xml \ + -DstagingRepositoryId=${STAGING_REPOSITORY_ID} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg new file mode 100644 index 000000000000..fc95786fa749 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -0,0 +1,19 @@ +# Format: //devtools/kokoro/config/proto/build.proto +env_vars: { + key: "STAGING_BUCKET" + value: "docs-staging" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "docuploader_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh new file mode 100755 index 000000000000..3ff4bddf8471 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2019 Google Inc. +# +# 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. + +set -eo pipefail + +if [[ -z "${CREDENTIALS}" ]]; then + CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account +fi + +if [[ -z "${STAGING_BUCKET}" ]]; then + echo "Need to set STAGING_BUCKET environment variable" + exit 1 +fi + +# work from the git root directory +pushd $(dirname "$0")/../../ + +# install docuploader package +python3 -m pip install gcp-docuploader + +# compile all packages +mvn clean install -B -DskipTests=true + +NAME=spanner-jdbc +VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) + +# build the docs +mvn site -B + +pushd target/site/apidocs + +# create metadata +python3 -m docuploader create-metadata \ + --name ${NAME} \ + --version ${VERSION} \ + --language java + +# upload docs +python3 -m docuploader upload . \ + --credentials ${CREDENTIALS} \ + --staging-bucket ${STAGING_BUCKET} + +popd diff --git a/java-spanner-jdbc/.kokoro/release/snapshot.cfg b/java-spanner-jdbc/.kokoro/release/snapshot.cfg new file mode 100644 index 000000000000..aa772391f1fa --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/snapshot.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/snapshot.sh" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/snapshot.sh b/java-spanner-jdbc/.kokoro/release/snapshot.sh new file mode 100755 index 000000000000..098168a7373c --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/snapshot.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Copyright 2019 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. + +set -eo pipefail + +source $(dirname "$0")/common.sh +MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml +pushd $(dirname "$0")/../../ + +# ensure we're trying to push a snapshot (no-result returns non-zero exit code) +grep SNAPSHOT versions.txt + +setup_environment_secrets +create_settings_xml_file "settings.xml" + +mvn clean install deploy -B \ + --settings ${MAVEN_SETTINGS_FILE} \ + -DperformRelease=true \ + -Dgpg.executable=gpg \ + -Dgpg.passphrase=${GPG_PASSPHRASE} \ + -Dgpg.homedir=${GPG_HOMEDIR} diff --git a/java-spanner-jdbc/.kokoro/release/stage.cfg b/java-spanner-jdbc/.kokoro/release/stage.cfg new file mode 100644 index 000000000000..8ea66bc79322 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/stage.cfg @@ -0,0 +1,44 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/release/stage.sh" +} + +# Need to save the properties file +action { + define_artifacts { + regex: "github/java-spanner-jdbc/target/nexus-staging/staging/*.properties" + strip_prefix: "github/java-spanner-jdbc" + } +} + +# Fetch the token needed for reporting release status to GitHub +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "yoshi-automation-github-key" + } + } +} + +# Fetch magictoken to use with Magic Github Proxy +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "releasetool-magictoken" + } + } +} + +# Fetch api key to use with Magic Github Proxy +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "magic-github-proxy-api-key" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh new file mode 100755 index 000000000000..3c482cbc55f1 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright 2018 Google Inc. +# +# 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. + +set -eo pipefail + +# Start the releasetool reporter +python3 -m pip install gcp-releasetool +python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script + +source $(dirname "$0")/common.sh +MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml +pushd $(dirname "$0")/../../ + +setup_environment_secrets +create_settings_xml_file "settings.xml" + +mvn clean install deploy -B \ + --settings ${MAVEN_SETTINGS_FILE} \ + -DskipTests=true \ + -DperformRelease=true \ + -Dgpg.executable=gpg \ + -Dgpg.passphrase=${GPG_PASSPHRASE} \ + -Dgpg.homedir=${GPG_HOMEDIR} + +if [[ -n "${AUTORELEASE_PR}" ]] +then + mvn nexus-staging:release -B \ + -DperformRelease=true \ + --settings=settings.xml +fi \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/trampoline.sh b/java-spanner-jdbc/.kokoro/trampoline.sh new file mode 100644 index 000000000000..ba17ce01466b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/trampoline.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright 2018 Google Inc. +# +# 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. +set -eo pipefail +# Always run the cleanup script, regardless of the success of bouncing into +# the container. +function cleanup() { + chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + echo "cleanup"; +} +trap cleanup EXIT +python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json new file mode 100644 index 000000000000..c4e07134b873 --- /dev/null +++ b/java-spanner-jdbc/.repo-metadata.json @@ -0,0 +1,10 @@ +{ + "name": "spanner-jdbc", + "name_pretty": "Google Cloud Spanner JDBC", + "product_documentation": "https://cloud.google.com/pubsub/docs/", + "client_documentation": "https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/spanner/jdbc/v1", + "release_level": "ga", + "language": "java", + "repo": "googleapis/java-spanner-jdbc", + "repo_short": "java-spanner-jdbc" +} \ No newline at end of file diff --git a/java-spanner-jdbc/CODE_OF_CONDUCT.md b/java-spanner-jdbc/CODE_OF_CONDUCT.md new file mode 100644 index 000000000000..6b2238bb75e0 --- /dev/null +++ b/java-spanner-jdbc/CODE_OF_CONDUCT.md @@ -0,0 +1,93 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +This Code of Conduct also applies outside the project spaces when the Project +Steward has a reasonable belief that an individual's behavior may have a +negative impact on the project or its community. + +## Conflict Resolution + +We do not believe that all conflict is bad; healthy debate and disagreement +often yield positive results. However, it is never okay to be disrespectful or +to engage in behavior that violates the project’s code of conduct. + +If you see someone violating the code of conduct, you are encouraged to address +the behavior directly with those involved. Many issues can be resolved quickly +and easily, and this gives people more control over the outcome of their +dispute. If you are unable to resolve the matter for any reason, or if the +behavior is threatening or harassing, report it. We are dedicated to providing +an environment where participants feel welcome and safe. + +Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the +Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to +receive and address reported violations of the code of conduct. They will then +work with a committee consisting of representatives from the Open Source +Programs Office and the Google Open Source Strategy team. If for any reason you +are uncomfortable reaching out the Project Steward, please email +opensource@google.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is taken. +The identity of the reporter will be omitted from the details of the report +supplied to the accused. In potentially harmful situations, such as ongoing +harassment or threats to anyone's safety, we may take action without notice. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html \ No newline at end of file diff --git a/java-spanner-jdbc/CONTRIBUTING.md b/java-spanner-jdbc/CONTRIBUTING.md new file mode 100644 index 000000000000..ebbb59e5310f --- /dev/null +++ b/java-spanner-jdbc/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Community Guidelines + +This project follows +[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). \ No newline at end of file diff --git a/java-spanner-jdbc/LICENSE b/java-spanner-jdbc/LICENSE index 4eedc0116add..d64569567334 100644 --- a/java-spanner-jdbc/LICENSE +++ b/java-spanner-jdbc/LICENSE @@ -1,4 +1,5 @@ -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a diff --git a/java-spanner-jdbc/codecov.yaml b/java-spanner-jdbc/codecov.yaml new file mode 100644 index 000000000000..5724ea9478d7 --- /dev/null +++ b/java-spanner-jdbc/codecov.yaml @@ -0,0 +1,4 @@ +--- +codecov: + ci: + - source.cloud.google.com diff --git a/java-spanner-jdbc/java.header b/java-spanner-jdbc/java.header new file mode 100644 index 000000000000..3a9b503aa24f --- /dev/null +++ b/java-spanner-jdbc/java.header @@ -0,0 +1,15 @@ +^/\*$ +^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)( All [rR]ights [rR]eserved\.)?$ +^ \*$ +^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ +^ \* you may not use this file except in compliance with the License\.$ +^ \* You may obtain a copy of the License at$ +^ \*$ +^ \*[ ]+https?://www.apache.org/licenses/LICENSE-2\.0$ +^ \*$ +^ \* Unless required by applicable law or agreed to in writing, software$ +^ \* distributed under the License is distributed on an "AS IS" BASIS,$ +^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ +^ \* See the License for the specific language governing permissions and$ +^ \* limitations under the License\.$ +^ \*/$ diff --git a/java-spanner-jdbc/license-checks.xml b/java-spanner-jdbc/license-checks.xml new file mode 100644 index 000000000000..6597fced808e --- /dev/null +++ b/java-spanner-jdbc/license-checks.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bde10c67c3be..188d1d74d4b9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -13,34 +13,241 @@ com.google.cloud - google-cloud-contrib - 0.120.1-alpha-SNAPSHOT + google-cloud-shared-config + 0.3.0 + + + chingor + Jeff Ching + chingor@google.com + Google + + Developer + + + + + Google LLC + + + scm:git:git@github.com:googleapis/java-spanner-jdbc.git + scm:git:git@github.com:googleapis/java-spanner-jdbc.git + https://github.com/googleapis/java-spanner-jdbc + HEAD + + + https://github.com/googleapis/java-spanner-jdbc/issues + GitHub Issues + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + Apache-2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + + google-cloud-spanner-jdbc + 1.25.0 + 1.30.7 + 1.92.0 + 1.52.0 + 1.34.0 + 28.2-android + 4.12 + 1.17.0 + 3.11.1 + 1.4.0 + 1.8.1 + 1.47.0 + 2.2 + 2.3.4 + 0.19.0 + + + + + io.grpc + grpc-bom + ${grpc.version} + pom + import + + + com.google.api-client + google-api-client-bom + ${api-client.version} + pom + import + + + com.google.cloud + google-cloud-core-bom + ${google.core.version} + pom + import + + + com.google.api + gax-bom + ${gax.version} + pom + import + + + com.google.http-client + google-http-client-bom + ${http-client-bom.version} + pom + import + + + com.google.guava + guava-bom + ${guava.version} + pom + import + + + com.google.auth + google-auth-library-bom + ${google.auth.version} + pom + import + + + com.google.errorprone + error_prone_annotations + ${error-prone.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + org.hamcrest + hamcrest-core + ${hamcrest.version} + test + + + + - com.google.cloud - google-cloud-spanner - 1.47.1-SNAPSHOT + com.google.api.grpc + proto-google-common-protos + ${google.common-protos.version} com.google.cloud google-cloud-spanner - 1.47.1-SNAPSHOT - test-jar - test + ${spanner.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + com.google.guava + guava + ${guava.version} com.google.api - gax-grpc - testlib + gax + ${gax.version} + + + org.threeten + threetenbp + ${threeten.version} + + + io.grpc + grpc-api + ${grpc.version} + + + com.google.api + api-common + ${google.api-common.version} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.google.http-client + google-http-client + ${http-client-bom.version} + + + com.google.auth + google-auth-library-oauth2-http + ${google.auth.version} + + + com.google.cloud + google-cloud-core + ${google.core.version} + + + com.google.code.gson + gson + 2.8.6 + + + com.google.auth + google-auth-library-credentials + ${google.auth.version} + + + org.apache.commons + commons-lang3 + 3.5 + + + com.google.api.grpc + proto-google-cloud-spanner-v1 + ${spanner.version} + + + com.google.api.grpc + proto-google-cloud-spanner-admin-database-v1 + ${spanner.version} + + + com.google.protobuf + protobuf-java-util + ${protobuf.version} + + + + com.google.cloud + google-cloud-spanner + ${spanner.version} + test-jar test com.google.truth truth + 1.0 test @@ -49,13 +256,38 @@ 1.9.5 test + + org.hamcrest + hamcrest + ${hamcrest.version} + test + + + junit + junit + ${junit.version} + test + + + io.grpc + grpc-netty-shaded + ${grpc.version} + test + + + com.google.api + gax-grpc + ${gax.version} + testlib + test + org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 3.0.0-M3 com.google.cloud.spanner.IntegrationTest sponge_log @@ -64,7 +296,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M4 + 3.0.0-M3 com.google.cloud.spanner.GceTestEnvConfig @@ -83,6 +315,17 @@ + + + + org.apache.maven.plugins + maven-dependency-plugin + + com.google.api:gax-grpc + + + + @@ -186,4 +429,73 @@ + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.0.0 + + + + index + dependency-info + team + ci-management + issue-management + licenses + scm + dependency-management + distribution-management + summary + modules + + + + + true + ${site.installationModule} + jar + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + html + + aggregate + javadoc + + + + + none + protected + true + ${project.build.directory}/javadoc + + + Test helpers packages + com.google.cloud.testing + + + SPI packages + com.google.cloud.spi* + + + + + https://grpc.io/grpc-java/javadoc/ + https://developers.google.com/protocol-buffers/docs/reference/java/ + https://googleapis.dev/java/google-auth-library/latest/ + https://googleapis.dev/java/gax/latest/ + https://googleapis.github.io/api-common-java/${google.api-common.version}/apidocs/ + + + + + diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json new file mode 100644 index 000000000000..99810470034c --- /dev/null +++ b/java-spanner-jdbc/renovate.json @@ -0,0 +1,27 @@ +{ + "extends": [ + "config:base" + ], + "ignoreDeps": [], + "packageRules": [ + { + "managers": ["maven"], + "packageNames": ["com.google.guava:guava*"], + "versionScheme": "docker" + }, + { + "packagePatterns": ["^io.grpc:grpc-"], + "groupName": "gRPC packages" + }, + { + "packagePatterns": ["^com.google.protobuf:protobuf-"], + "groupName": "Protobuf packages" + }, + { + "packagePatterns": ["^io.opencensus:opencensus-"], + "groupName": "OpenCensus packages" + } + ], + "semanticCommits": true, + "semanticCommitType": "deps" +} diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/synth.py new file mode 100644 index 000000000000..259352ead231 --- /dev/null +++ b/java-spanner-jdbc/synth.py @@ -0,0 +1,25 @@ +# Copyright 2018 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. + +"""This script is used to synthesize generated parts of this library.""" + +import synthtool as s +import synthtool.gcp as gcp + + +common_templates = gcp.CommonTemplates() +templates = common_templates.java_library() +s.copy(templates, excludes=[ + 'README.md' +]) \ No newline at end of file diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt new file mode 100644 index 000000000000..e69de29bb2d1 From 3cf5ea196aa7f8630e0480c3aaa487f1f32a1978 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 31 Dec 2019 18:01:45 +0200 Subject: [PATCH 0068/1979] chore(deps): update grpc packages to v1.26.0 (#10) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 188d1d74d4b9..ee3c4c975121 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 1.25.0 + 1.26.0 1.30.7 1.92.0 1.52.0 From 4fa8ed729953fbbe540984ca6e8091997ea6dae0 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 3 Jan 2020 22:05:21 +0200 Subject: [PATCH 0069/1979] chore(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.3.1 (#16) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ee3c4c975121..fe02b2bf7c57 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.3.0 + 0.3.1 From aefab095d823b3daa551195cf3c482a882d0b5b0 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Fri, 3 Jan 2020 14:55:16 -0600 Subject: [PATCH 0070/1979] chore: fix versions.txt file (#18) --- java-spanner-jdbc/versions.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e69de29bb2d1..de9c4df19ff4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -0,0 +1,4 @@ +# Format: +# module:released-version:current-version + +google-cloud-spanner-jdbc:1.12.0:1.12.1-SNAPSHOT From 19e91e35796b74a49032a0d9b6b873c27e551b65 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 20:33:51 +0200 Subject: [PATCH 0071/1979] chore(deps): update dependency junit:junit to v4.13 (#14) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fe02b2bf7c57..91f3e2bf8dd7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -64,7 +64,7 @@ 1.52.0 1.34.0 28.2-android - 4.12 + 4.13 1.17.0 3.11.1 1.4.0 From 02c2357857253b239f7de71b11c9e13044baa7e0 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 20:34:33 +0200 Subject: [PATCH 0072/1979] chore(deps): update dependency org.mockito:mockito-core to v1.10.19 (#9) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 91f3e2bf8dd7..c46a749c5205 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -253,7 +253,7 @@ org.mockito mockito-core - 1.9.5 + 1.10.19 test From 6d20f29c5ca3f29222583d95601020be44543249 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 20:35:35 +0200 Subject: [PATCH 0073/1979] chore(deps): update google.core.version to v1.92.1 (#15) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c46a749c5205..b845da9aac22 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -60,7 +60,7 @@ google-cloud-spanner-jdbc 1.26.0 1.30.7 - 1.92.0 + 1.92.1 1.52.0 1.34.0 28.2-android From 7159d44079ad8d9f02da5e0998df370c29b77119 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 21:11:29 +0200 Subject: [PATCH 0074/1979] chore(deps): update dependency org.apache.maven.plugins:maven-failsafe-plugin to v3.0.0-m4 (#7) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b845da9aac22..e6e493266e92 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -296,7 +296,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M3 + 3.0.0-M4 com.google.cloud.spanner.GceTestEnvConfig From 2030d36ee94cb9b0cfe886dba2013b45fac24e24 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 6 Jan 2020 21:11:51 +0200 Subject: [PATCH 0075/1979] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.0.0-m4 (#8) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e6e493266e92..06d216e56526 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -287,7 +287,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M3 + 3.0.0-M4 com.google.cloud.spanner.IntegrationTest sponge_log From d230068789fe38c110c780e0b19e45fd9788feab Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Tue, 7 Jan 2020 11:45:40 -0800 Subject: [PATCH 0076/1979] chore: allow unstable renovate updates --- java-spanner-jdbc/renovate.json | 61 ++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 99810470034c..f3a70c9703f1 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -1,27 +1,64 @@ { "extends": [ - "config:base" + ":separateMajorReleases", + ":combinePatchMinorReleases", + ":ignoreUnstable", + ":prImmediately", + ":updateNotScheduled", + ":automergeDisabled", + ":ignoreModulesAndTests", + ":maintainLockFilesDisabled", + ":autodetectPinVersions" ], - "ignoreDeps": [], "packageRules": [ { - "managers": ["maven"], - "packageNames": ["com.google.guava:guava*"], + "packagePatterns": [ + "^com.google.guava:" + ], "versionScheme": "docker" }, { - "packagePatterns": ["^io.grpc:grpc-"], - "groupName": "gRPC packages" + "packagePatterns": [ + "^com.google.api:gax", + "^com.google.auth:", + "^com.google.cloud:google-cloud-core", + "^io.grpc:" + ], + "groupName": "core dependencies" }, { - "packagePatterns": ["^com.google.protobuf:protobuf-"], - "groupName": "Protobuf packages" + "packagePatterns": [ + "^com.google.http-client:", + "^com.google.oauth-client:", + "^com.google.api-client:" + ], + "groupName": "core transport dependencies" }, { - "packagePatterns": ["^io.opencensus:opencensus-"], - "groupName": "OpenCensus packages" + "packagePatterns": [ + "*" + ], + "semanticCommitType": "deps", + "semanticCommitScope": null + }, + { + "packagePatterns": [ + "^org.apache.maven", + "^org.jacoco:", + "^org.codehaus.mojo:", + "^org.sonatype.plugins:", + "^com.coveo:", + "^com.google.cloud:google-cloud-shared-config" + ], + "semanticCommitType": "build", + "semanticCommitScope": "deps" + }, + { + "packagePatterns": [ + "^com.google.cloud:google-cloud-" + ], + "ignoreUnstable": false } ], - "semanticCommits": true, - "semanticCommitType": "deps" + "semanticCommits": true } From be8895ebb1ce4850d5d1907ef946f92af66a1a90 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 9 Jan 2020 12:56:55 -0800 Subject: [PATCH 0077/1979] chore: fix distribution_name in .repo-metadata (#24) Fixes #13 --- java-spanner-jdbc/.repo-metadata.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index c4e07134b873..83c6f64d76e5 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -6,5 +6,6 @@ "release_level": "ga", "language": "java", "repo": "googleapis/java-spanner-jdbc", - "repo_short": "java-spanner-jdbc" -} \ No newline at end of file + "repo_short": "java-spanner-jdbc", + "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc" +} From 510e6927a57fab1acfe86622210359e11335d8e3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 9 Jan 2020 21:57:16 +0100 Subject: [PATCH 0078/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.4.0 (#23) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 06d216e56526..8b1d63f70175 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.3.1 + 0.4.0 From 643621f2a14196e3cd1e8c00d95687196bfe0f0e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 13 Jan 2020 23:32:41 +0100 Subject: [PATCH 0079/1979] deps: update dependency org.threeten:threetenbp to v1.4.1 --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8b1d63f70175..4fe72fc9a4a4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -67,7 +67,7 @@ 4.13 1.17.0 3.11.1 - 1.4.0 + 1.4.1 1.8.1 1.47.0 2.2 From f3374701ce9c8aaeb4ae8b4e8d2e387a204c3bf4 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 13 Jan 2020 15:26:11 -0800 Subject: [PATCH 0080/1979] chore: update common templates (#26) --- java-spanner-jdbc/.github/release-please.yml | 1 + java-spanner-jdbc/.kokoro/build.sh | 29 ++++- .../.kokoro/continuous/samples.cfg | 31 ++++++ java-spanner-jdbc/.kokoro/dependencies.sh | 6 +- java-spanner-jdbc/.kokoro/nightly/samples.cfg | 31 ++++++ .../.kokoro/presubmit/samples.cfg | 31 ++++++ java-spanner-jdbc/.kokoro/release/drop.cfg | 3 - java-spanner-jdbc/.kokoro/release/promote.cfg | 4 - .../.kokoro/release/publish_javadoc.sh | 2 +- java-spanner-jdbc/CONTRIBUTING.md | 104 +++++++++++++++++- java-spanner-jdbc/synth.metadata | 12 ++ 11 files changed, 239 insertions(+), 15 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/continuous/samples.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/samples.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/samples.cfg create mode 100644 java-spanner-jdbc/synth.metadata diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index 827446828034..dce2c8450921 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -1 +1,2 @@ releaseType: java-yoshi +bumpMinorPreMajor: true \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index fa132f410dcc..f1ae58408da5 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -27,6 +27,7 @@ echo ${JOB_TYPE} mvn install -B -V \ -DskipTests=true \ -Dclirr.skip=true \ + -Denforcer.skip=true \ -Dmaven.javadoc.skip=true \ -Dgcloud.download.skip=true \ -T 1C @@ -38,23 +39,41 @@ fi case ${JOB_TYPE} in test) - mvn test -B -Dclirr.skip=true + mvn test -B -Dclirr.skip=true -Denforcer.skip=true bash ${KOKORO_GFILE_DIR}/codecov.sh bash .kokoro/coerce_logs.sh ;; lint) - mvn com.coveo:fmt-maven-plugin:check + mvn \ + -Penable-samples \ + com.coveo:fmt-maven-plugin:check ;; javadoc) mvn javadoc:javadoc javadoc:test-javadoc ;; integration) - mvn -B ${INTEGRATION_TEST_ARGS} -DtrimStackTrace=false -Dclirr.skip=true -fae verify + mvn -B ${INTEGRATION_TEST_ARGS} \ + -Penable-integration-tests \ + -DtrimStackTrace=false \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -fae \ + verify + bash .kokoro/coerce_logs.sh + ;; +samples) + mvn -B \ + -Penable-samples \ + -DtrimStackTrace=false \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -fae \ + verify bash .kokoro/coerce_logs.sh ;; clirr) - mvn -B clirr:check + mvn -B -Denforcer.skip=true clirr:check ;; *) ;; -esac \ No newline at end of file +esac diff --git a/java-spanner-jdbc/.kokoro/continuous/samples.cfg b/java-spanner-jdbc/.kokoro/continuous/samples.cfg new file mode 100644 index 000000000000..fa7b493d0b5c --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/samples.cfg @@ -0,0 +1,31 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "samples" +} + +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "java_it_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 50c307400c33..d1cb8dc2ca13 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -23,5 +23,9 @@ echo $JOB_TYPE export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" -mvn install -DskipTests=true -B -V +# this should run maven enforcer +mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true + mvn -B dependency:analyze -DfailOnWarning=true diff --git a/java-spanner-jdbc/.kokoro/nightly/samples.cfg b/java-spanner-jdbc/.kokoro/nightly/samples.cfg new file mode 100644 index 000000000000..9a9102490d54 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/samples.cfg @@ -0,0 +1,31 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "samples" +} + +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "java_it_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/samples.cfg b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg new file mode 100644 index 000000000000..fa7b493d0b5c --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg @@ -0,0 +1,31 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "samples" +} + +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "java_it_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/release/drop.cfg b/java-spanner-jdbc/.kokoro/release/drop.cfg index 93afddf54a55..245e96b4c4ee 100644 --- a/java-spanner-jdbc/.kokoro/release/drop.cfg +++ b/java-spanner-jdbc/.kokoro/release/drop.cfg @@ -4,6 +4,3 @@ env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/java-spanner-jdbc/.kokoro/release/drop.sh" } - -# Download staging properties file. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/java/releases/java-spanner-jdbc" \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/promote.cfg b/java-spanner-jdbc/.kokoro/release/promote.cfg index 978cde7960d8..1ee66ee99932 100644 --- a/java-spanner-jdbc/.kokoro/release/promote.cfg +++ b/java-spanner-jdbc/.kokoro/release/promote.cfg @@ -4,7 +4,3 @@ env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/java-spanner-jdbc/.kokoro/release/promote.sh" } - -# Download staging properties file. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/java/releases/java-spanner-jdbc" - diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 3ff4bddf8471..99de3944bc1c 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -33,7 +33,7 @@ python3 -m pip install gcp-docuploader # compile all packages mvn clean install -B -DskipTests=true -NAME=spanner-jdbc +NAME=google-cloud-spanner-jdbc VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) # build the docs diff --git a/java-spanner-jdbc/CONTRIBUTING.md b/java-spanner-jdbc/CONTRIBUTING.md index ebbb59e5310f..085021ddec26 100644 --- a/java-spanner-jdbc/CONTRIBUTING.md +++ b/java-spanner-jdbc/CONTRIBUTING.md @@ -25,4 +25,106 @@ information on using pull requests. ## Community Guidelines This project follows -[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). \ No newline at end of file +[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). + +## Building the project + +To build, package, and run all unit tests run the command + +``` +mvn clean verify +``` + +### Running Integration tests + +To include integration tests when building the project, you need access to +a GCP Project with a valid service account. + +For instructions on how to generate a service account and corresponding +credentials JSON see: [Creating a Service Account][1]. + +Then run the following to build, package, run all unit tests and run all +integration tests. + +```bash +export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json +mvn -Penable-integration-tests clean verify +``` + +## Code Samples + +Code Samples must be bundled in separate Maven modules, and guarded by a +Maven profile with the name `enable-samples`. + +The samples must be separate from the primary project for a few reasons: +1. Primary projects have a minimum Java version of Java 7 whereas samples have + a minimum Java version of Java 8. Due to this we need the ability to + selectively exclude samples from a build run. +2. Many code samples depend on external GCP services and need + credentials to access the service. +3. Code samples are not released as Maven artifacts and must be excluded from + release builds. + +### Building + +```bash +mvn -Penable-samples clean verify +``` + +Some samples require access to GCP services and require a service account: + +```bash +export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json +mvn -Penable-samples clean verify +``` + +### Profile Config + +1. To add samples in a profile to your Maven project, add the following to your +`pom.xml` + + ```xml + + [...] + + + enable-samples + + sample + + + + [...] + + ``` + +2. [Activate](#profile-activation) the profile. +3. Define your samples in a normal Maven project in the `samples/` directory + +### Profile Activation + +To include code samples when building and testing the project, enable the +`enable-samples` Maven profile. + +#### Command line + +To activate the Maven profile on the command line add `-Penable-samples` to your +Maven command. + +#### Maven `settings.xml` + +To activate the Maven profile in your `~/.m2/settings.xml` add an entry of +`enable-samples` following the instructions in [Active Profiles][2]. + +This method has the benefit of applying to all projects you build (and is +respected by IntelliJ IDEA) and is recommended if you are going to be +contributing samples to several projects. + +#### IntelliJ IDEA + +To activate the Maven Profile inside IntelliJ IDEA, follow the instructions in +[Activate Maven profiles][3] to activate `enable-samples`. + +[1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account +[2]: https://maven.apache.org/settings.html#Active_Profiles +[3]: https://www.jetbrains.com/help/idea/work-with-maven-profiles.html#activate_maven_profiles diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata new file mode 100644 index 000000000000..fac5b7239630 --- /dev/null +++ b/java-spanner-jdbc/synth.metadata @@ -0,0 +1,12 @@ +{ + "updateTime": "2020-01-10T09:11:13.740638Z", + "sources": [ + { + "template": { + "name": "java_library", + "origin": "synthtool.gcp", + "version": "2019.10.17" + } + } + ] +} \ No newline at end of file From b21ba7c3999dfc41b1a08d2c44f8a853d6d5602d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 14 Jan 2020 00:26:36 +0100 Subject: [PATCH 0081/1979] deps: update core dependencies (#25) --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4fe72fc9a4a4..fb78d97714ea 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -60,8 +60,8 @@ google-cloud-spanner-jdbc 1.26.0 1.30.7 - 1.92.1 - 1.52.0 + 1.92.2 + 1.53.0 1.34.0 28.2-android 4.13 From 382328449b5fb1c8ff1e5dfb2483c874d6482560 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 17 Jan 2020 10:11:46 -0800 Subject: [PATCH 0082/1979] chore(regen): update common renovate configuration --- java-spanner-jdbc/renovate.json | 6 + java-spanner-jdbc/synth.metadata | 808 ++++++++++++++++++++++++++++++- 2 files changed, 813 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index f3a70c9703f1..a5cdff45c319 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -58,6 +58,12 @@ "^com.google.cloud:google-cloud-" ], "ignoreUnstable": false + }, + { + "packagePatterns": [ + "^com.fasterxml.jackson.core" + ], + "groupName": "jackson dependencies" } ], "semanticCommits": true diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index fac5b7239630..50195b614ead 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,5 +1,5 @@ { - "updateTime": "2020-01-10T09:11:13.740638Z", + "updateTime": "2020-01-16T09:11:16.210833Z", "sources": [ { "template": { @@ -8,5 +8,811 @@ "version": "2019.10.17" } } + ], + "newFiles": [ + { + "path": "pom.xml" + }, + { + "path": ".repo-metadata.json" + }, + { + "path": "java.header" + }, + { + "path": "CONTRIBUTING.md" + }, + { + "path": "synth.metadata" + }, + { + "path": "renovate.json" + }, + { + "path": "versions.txt" + }, + { + "path": "synth.py" + }, + { + "path": "license-checks.xml" + }, + { + "path": "CODE_OF_CONDUCT.md" + }, + { + "path": "LICENSE" + }, + { + "path": "codecov.yaml" + }, + { + "path": ".gitignore" + }, + { + "path": "README.md" + }, + { + "path": ".github/release-please.yml" + }, + { + "path": ".github/PULL_REQUEST_TEMPLATE.md" + }, + { + "path": ".github/ISSUE_TEMPLATE/feature_request.md" + }, + { + "path": ".github/ISSUE_TEMPLATE/support_request.md" + }, + { + "path": ".github/ISSUE_TEMPLATE/bug_report.md" + }, + { + "path": ".kokoro/build.sh" + }, + { + "path": ".kokoro/common.cfg" + }, + { + "path": ".kokoro/build.bat" + }, + { + "path": ".kokoro/linkage-monitor.sh" + }, + { + "path": ".kokoro/coerce_logs.sh" + }, + { + "path": ".kokoro/dependencies.sh" + }, + { + "path": ".kokoro/trampoline.sh" + }, + { + "path": ".kokoro/continuous/samples.cfg" + }, + { + "path": ".kokoro/continuous/java8.cfg" + }, + { + "path": ".kokoro/continuous/integration.cfg" + }, + { + "path": ".kokoro/continuous/java11.cfg" + }, + { + "path": ".kokoro/continuous/propose_release.cfg" + }, + { + "path": ".kokoro/continuous/common.cfg" + }, + { + "path": ".kokoro/continuous/propose_release.sh" + }, + { + "path": ".kokoro/continuous/java7.cfg" + }, + { + "path": ".kokoro/continuous/lint.cfg" + }, + { + "path": ".kokoro/continuous/java8-osx.cfg" + }, + { + "path": ".kokoro/continuous/dependencies.cfg" + }, + { + "path": ".kokoro/continuous/java8-win.cfg" + }, + { + "path": ".kokoro/nightly/samples.cfg" + }, + { + "path": ".kokoro/nightly/java8.cfg" + }, + { + "path": ".kokoro/nightly/integration.cfg" + }, + { + "path": ".kokoro/nightly/java11.cfg" + }, + { + "path": ".kokoro/nightly/common.cfg" + }, + { + "path": ".kokoro/nightly/java7.cfg" + }, + { + "path": ".kokoro/nightly/lint.cfg" + }, + { + "path": ".kokoro/nightly/java8-osx.cfg" + }, + { + "path": ".kokoro/nightly/dependencies.cfg" + }, + { + "path": ".kokoro/nightly/java8-win.cfg" + }, + { + "path": ".kokoro/release/publish_javadoc.cfg" + }, + { + "path": ".kokoro/release/common.sh" + }, + { + "path": ".kokoro/release/promote.sh" + }, + { + "path": ".kokoro/release/common.cfg" + }, + { + "path": ".kokoro/release/publish_javadoc.sh" + }, + { + "path": ".kokoro/release/drop.sh" + }, + { + "path": ".kokoro/release/stage.sh" + }, + { + "path": ".kokoro/release/promote.cfg" + }, + { + "path": ".kokoro/release/snapshot.cfg" + }, + { + "path": ".kokoro/release/bump_snapshot.cfg" + }, + { + "path": ".kokoro/release/drop.cfg" + }, + { + "path": ".kokoro/release/bump_snapshot.sh" + }, + { + "path": ".kokoro/release/stage.cfg" + }, + { + "path": ".kokoro/release/snapshot.sh" + }, + { + "path": ".kokoro/presubmit/samples.cfg" + }, + { + "path": ".kokoro/presubmit/java8.cfg" + }, + { + "path": ".kokoro/presubmit/integration.cfg" + }, + { + "path": ".kokoro/presubmit/java11.cfg" + }, + { + "path": ".kokoro/presubmit/linkage-monitor.cfg" + }, + { + "path": ".kokoro/presubmit/common.cfg" + }, + { + "path": ".kokoro/presubmit/java7.cfg" + }, + { + "path": ".kokoro/presubmit/lint.cfg" + }, + { + "path": ".kokoro/presubmit/java8-osx.cfg" + }, + { + "path": ".kokoro/presubmit/dependencies.cfg" + }, + { + "path": ".kokoro/presubmit/clirr.cfg" + }, + { + "path": ".kokoro/presubmit/java8-win.cfg" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java" + }, + { + "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key.json" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt" + }, + { + "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/Connection.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java" + }, + { + "path": "src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql" + }, + { + "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql" + }, + { + "path": "src/main/resources/META-INF/services/java.sql.Driver" + } ] } \ No newline at end of file From c83c4e09d6b6c6873a0b35774fe1f5b58053059f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 22 Jan 2020 07:33:07 +0100 Subject: [PATCH 0083/1979] fix: allow dots and colons in project id (#36) * fix: allow dots and colons in project id The project ID part of a connection URL should allow the use of dots and colons. Fixes #33 * fix: escaping dot in square brackets is not needed --- .../cloud/spanner/jdbc/ConnectionOptions.java | 2 +- .../spanner/jdbc/ConnectionOptionsTest.java | 244 +++++++++--------- .../cloud/spanner/jdbc/JdbcDriverTest.java | 11 +- 3 files changed, 124 insertions(+), 133 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java index 3b03aca5e82d..ca25a5a257e4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -231,7 +231,7 @@ private Builder() {} /** Spanner {@link ConnectionOptions} URI format. */ public static final String SPANNER_URI_FORMAT = - "(?:cloudspanner:)(?//[\\w.-]+(?:\\.[\\w\\.-]+)*[\\w\\-\\._~:/?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=.]+)?/projects/(?(([a-z]|[-]|[0-9])+|(DEFAULT_PROJECT_ID)))(/instances/(?([a-z]|[-]|[0-9])+)(/databases/(?([a-z]|[-]|[_]|[0-9])+))?)?(?:[?|;].*)?"; + "(?:cloudspanner:)(?//[\\w.-]+(?:\\.[\\w\\.-]+)*[\\w\\-\\._~:/?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=.]+)?/projects/(?(([a-z]|[-.:]|[0-9])+|(DEFAULT_PROJECT_ID)))(/instances/(?([a-z]|[-]|[0-9])+)(/databases/(?([a-z]|[-]|[_]|[0-9])+))?)?(?:[?|;].*)?"; private static final String SPANNER_URI_REGEX = "(?is)^" + SPANNER_URI_FORMAT + "$"; private static final Pattern SPANNER_URI_PATTERN = Pattern.compile(SPANNER_URI_REGEX); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java index 1435cd1d9ca6..850836d3da82 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java @@ -16,12 +16,9 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; -import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.spanner.SpannerOptions; import java.util.Arrays; @@ -35,6 +32,23 @@ public class ConnectionOptionsTest { ConnectionOptionsTest.class.getResource("test-key.json").getFile(); private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; + @Test + public void testBuildWithURIWithDots() { + ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); + builder.setUri( + "cloudspanner:/projects/some-company.com:test-project-123/instances/test-instance-123/databases/test-database-123"); + builder.setCredentialsUrl(FILE_TEST_PATH); + ConnectionOptions options = builder.build(); + assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); + assertThat(options.getProjectId()).isEqualTo("some-company.com:test-project-123"); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); + assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); + } + @Test public void testBuildWithValidURIAndCredentialsFileURL() { ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); @@ -42,15 +56,14 @@ public void testBuildWithValidURIAndCredentialsFileURL() { "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); builder.setCredentialsUrl(FILE_TEST_PATH); ConnectionOptions options = builder.build(); - assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); - assertThat(options.getProjectId(), is(equalTo("test-project-123"))); - assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); - assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); - assertThat( - (GoogleCredentials) options.getCredentials(), - is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); - assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); - assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); + assertThat(options.getProjectId()).isEqualTo("test-project-123"); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); + assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); } @Test @@ -60,15 +73,14 @@ public void testBuildWithValidURIAndProperties() { "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123?autocommit=false;readonly=true"); builder.setCredentialsUrl(FILE_TEST_PATH); ConnectionOptions options = builder.build(); - assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); - assertThat(options.getProjectId(), is(equalTo("test-project-123"))); - assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); - assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); - assertThat( - (GoogleCredentials) options.getCredentials(), - is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); - assertThat(options.isAutocommit(), is(equalTo(false))); - assertThat(options.isReadOnly(), is(equalTo(true))); + assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); + assertThat(options.getProjectId()).isEqualTo("test-project-123"); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(false); + assertThat(options.isReadOnly()).isEqualTo(true); } @Test @@ -78,15 +90,14 @@ public void testBuildWithHostAndValidURI() { "cloudspanner://test-spanner.googleapis.com/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); builder.setCredentialsUrl(FILE_TEST_PATH); ConnectionOptions options = builder.build(); - assertThat(options.getHost(), is(equalTo("https://test-spanner.googleapis.com"))); - assertThat(options.getProjectId(), is(equalTo("test-project-123"))); - assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); - assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); - assertThat( - (GoogleCredentials) options.getCredentials(), - is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); - assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); - assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + assertThat(options.getHost()).isEqualTo("https://test-spanner.googleapis.com"); + assertThat(options.getProjectId()).isEqualTo("test-project-123"); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); + assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); } @Test @@ -96,15 +107,14 @@ public void testBuildWithLocalhostPortAndValidURI() { "cloudspanner://localhost:8443/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); builder.setCredentialsUrl(FILE_TEST_PATH); ConnectionOptions options = builder.build(); - assertThat(options.getHost(), is(equalTo("https://localhost:8443"))); - assertThat(options.getProjectId(), is(equalTo("test-project-123"))); - assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); - assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); - assertThat( - (GoogleCredentials) options.getCredentials(), - is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); - assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); - assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + assertThat(options.getHost()).isEqualTo("https://localhost:8443"); + assertThat(options.getProjectId()).isEqualTo("test-project-123"); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); + assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); } @Test @@ -114,21 +124,20 @@ public void testBuildWithDefaultProjectPlaceholder() { "cloudspanner:/projects/default_project_id/instances/test-instance-123/databases/test-database-123"); builder.setCredentialsUrl(FILE_TEST_PATH); ConnectionOptions options = builder.build(); - assertThat(options.getHost(), is(equalTo(DEFAULT_HOST))); + assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); String projectId = SpannerOptions.getDefaultProjectId(); if (projectId == null) { projectId = ((ServiceAccountCredentials) new CredentialsService().createCredentials(FILE_TEST_PATH)) .getProjectId(); } - assertThat(options.getProjectId(), is(equalTo(projectId))); - assertThat(options.getInstanceId(), is(equalTo("test-instance-123"))); - assertThat(options.getDatabaseName(), is(equalTo("test-database-123"))); - assertThat( - (GoogleCredentials) options.getCredentials(), - is(equalTo(new CredentialsService().createCredentials(FILE_TEST_PATH)))); - assertThat(options.isAutocommit(), is(equalTo(ConnectionOptions.DEFAULT_AUTOCOMMIT))); - assertThat(options.isReadOnly(), is(equalTo(ConnectionOptions.DEFAULT_READONLY))); + assertThat(options.getProjectId()).isEqualTo(projectId); + assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); + assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); + assertThat(options.getCredentials()) + .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); + assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); + assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); } @Test @@ -203,24 +212,21 @@ public void testBuilderSetUri() { } private void setInvalidUri(ConnectionOptions.Builder builder, String uri) { - boolean invalid = false; try { builder.setUri(uri); + fail(uri + " should be considered an invalid uri"); } catch (IllegalArgumentException e) { - invalid = true; } - assertThat(uri + " should be considered an invalid uri", invalid, is(true)); } private void setInvalidProperty( ConnectionOptions.Builder builder, String uri, String expectedInvalidProperties) { - boolean invalid = false; try { builder.setUri(uri); + fail("missing expected exception"); } catch (IllegalArgumentException e) { - invalid = e.getMessage().contains(expectedInvalidProperties); + assertThat(e.getMessage()).contains(expectedInvalidProperties); } - assertThat(uri + " should contain invalid properties", invalid, is(true)); } @Test @@ -228,86 +234,72 @@ public void testParseUriProperty() { final String baseUri = "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - assertThat(ConnectionOptions.parseUriProperty(baseUri, "autocommit"), is(nullValue())); - assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true", "autocommit"), - is(equalTo("true"))); + assertThat(ConnectionOptions.parseUriProperty(baseUri, "autocommit")).isNull(); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true", "autocommit")) + .isEqualTo("true"); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false", "autocommit")) + .isEqualTo("false"); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true;", "autocommit")) + .isEqualTo("true"); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false;", "autocommit")) + .isEqualTo("false"); assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=true;readOnly=false", "autocommit")) + .isEqualTo("true"); assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true;", "autocommit"), - is(equalTo("true"))); + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=false;readOnly=false", "autocommit")) + .isEqualTo("false"); assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false;", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=true", "autocommit")) + .isEqualTo("true"); assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=true;readOnly=false", "autocommit"), - is(equalTo("true"))); + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=false", "autocommit")) + .isEqualTo("false"); assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=false;readOnly=false", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=true;foo=bar", "autocommit")) + .isEqualTo("true"); assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=true", "autocommit"), - is(equalTo("true"))); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=false", "autocommit"), - is(equalTo("false"))); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=true;foo=bar", "autocommit"), - is(equalTo("true"))); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=false;foo=bar", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + "?readOnly=false;autocommit=false;foo=bar", "autocommit")) + .isEqualTo("false"); // case insensitive - assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=true", "autocommit"), - is(equalTo("true"))); - assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=false", "autocommit"), - is(equalTo("false"))); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=true", "autocommit")) + .isEqualTo("true"); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=false", "autocommit")) + .isEqualTo("false"); // ; instead of ? before the properties is ok - assertThat( - ConnectionOptions.parseUriProperty(baseUri + ";autocommit=true", "autocommit"), - is(equalTo("true"))); + assertThat(ConnectionOptions.parseUriProperty(baseUri + ";autocommit=true", "autocommit")) + .isEqualTo("true"); // forgot the ? or ; before the properties - assertThat( - ConnectionOptions.parseUriProperty(baseUri + "autocommit=true", "autocommit"), - is(nullValue())); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "autocommit=true", "autocommit")) + .isNull(); // substring is not ok - assertThat( - ConnectionOptions.parseUriProperty(baseUri + "?isautocommit=true", "autocommit"), - is(nullValue())); + assertThat(ConnectionOptions.parseUriProperty(baseUri + "?isautocommit=true", "autocommit")) + .isNull(); } @Test public void testParseProperties() { final String baseUri = "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - assertThat( - ConnectionOptions.parseProperties(baseUri + "?autocommit=true"), - is(equalTo(Arrays.asList("autocommit")))); - assertThat( - ConnectionOptions.parseProperties(baseUri + "?autocommit=true;readonly=false"), - is(equalTo(Arrays.asList("autocommit", "readonly")))); - assertThat( - ConnectionOptions.parseProperties(baseUri + "?autocommit=true;READONLY=false"), - is(equalTo(Arrays.asList("autocommit", "READONLY")))); - assertThat( - ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false"), - is(equalTo(Arrays.asList("autocommit", "readonly")))); - assertThat( - ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false;"), - is(equalTo(Arrays.asList("autocommit", "readonly")))); + assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true")) + .isEqualTo(Arrays.asList("autocommit")); + assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true;readonly=false")) + .isEqualTo(Arrays.asList("autocommit", "readonly")); + assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true;READONLY=false")) + .isEqualTo(Arrays.asList("autocommit", "READONLY")); + assertThat(ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false")) + .isEqualTo(Arrays.asList("autocommit", "readonly")); + assertThat(ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false;")) + .isEqualTo(Arrays.asList("autocommit", "readonly")); } @Test @@ -315,17 +307,17 @@ public void testParsePropertiesSpecifiedMultipleTimes() { final String baseUri = "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=true;autocommit=false", "autocommit"), - is(equalTo("true"))); + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=true;autocommit=false", "autocommit")) + .isEqualTo("true"); assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=false;autocommit=true", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + "?autocommit=false;autocommit=true", "autocommit")) + .isEqualTo("false"); assertThat( - ConnectionOptions.parseUriProperty( - baseUri + ";autocommit=false;readonly=false;autocommit=true", "autocommit"), - is(equalTo("false"))); + ConnectionOptions.parseUriProperty( + baseUri + ";autocommit=false;readonly=false;autocommit=true", "autocommit")) + .isEqualTo("false"); ConnectionOptions.newBuilder() .setUri( "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 68c252ebe347..77866dcbb411 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -16,8 +16,7 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static com.google.common.truth.Truth.assertThat; import com.google.cloud.spanner.MockSpannerServiceImpl; import io.grpc.Server; @@ -72,9 +71,9 @@ public void testConnect() throws SQLException { try (Connection connection = DriverManager.getConnection( String.format( - "jdbc:cloudspanner://localhost:%d/projects/test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s", + "jdbc:cloudspanner://localhost:%d/projects/some-company.com:test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s", server.getPort(), TEST_KEY_PATH))) { - assertThat(connection.isClosed(), is(false)); + assertThat(connection.isClosed()).isFalse(); } } @@ -83,9 +82,9 @@ public void testInvalidConnect() throws SQLException { try (Connection connection = DriverManager.getConnection( String.format( - "jdbc:cloudspanner://localhost:%d/projects/test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentialsUrl=%s", + "jdbc:cloudspanner://localhost:%d/projects/some-company.com:test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentialsUrl=%s", server.getPort(), TEST_KEY_PATH))) { - assertThat(connection.isClosed(), is(false)); + assertThat(connection.isClosed()).isFalse(); } } } From 1546d9a1a1caea20adc22d72df493c2590e592b0 Mon Sep 17 00:00:00 2001 From: Praful Makani Date: Wed, 22 Jan 2020 12:49:45 +0530 Subject: [PATCH 0084/1979] chore: remove deprecated method (#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Knut Olav Løite --- .../com/google/cloud/spanner/jdbc/AbortedTest.java | 2 +- .../spanner/jdbc/AbstractConnectionImplTest.java | 2 +- .../spanner/jdbc/AbstractJdbcResultSetTest.java | 2 +- .../spanner/jdbc/AbstractSqlScriptVerifier.java | 2 +- .../jdbc/AutocommitDmlModeConverterTest.java | 2 +- .../cloud/spanner/jdbc/AutocommitDmlModeTest.java | 2 +- .../cloud/spanner/jdbc/BooleanConverterTest.java | 2 +- .../cloud/spanner/jdbc/ConnectionImplTest.java | 2 +- .../jdbc/ConnectionStatementExecutorTest.java | 2 +- .../cloud/spanner/jdbc/CredentialsServiceTest.java | 2 +- .../google/cloud/spanner/jdbc/DdlBatchTest.java | 2 +- .../spanner/jdbc/DirectExecuteResultSetTest.java | 2 +- .../google/cloud/spanner/jdbc/DmlBatchTest.java | 2 +- .../cloud/spanner/jdbc/DurationConverterTest.java | 2 +- .../spanner/jdbc/JdbcAbortedTransactionTest.java | 2 +- .../google/cloud/spanner/jdbc/JdbcBlobTest.java | 2 +- .../google/cloud/spanner/jdbc/JdbcClobTest.java | 2 +- .../cloud/spanner/jdbc/JdbcConnectionTest.java | 2 +- .../spanner/jdbc/JdbcDatabaseMetaDataTest.java | 2 +- .../cloud/spanner/jdbc/JdbcParameterStoreTest.java | 2 +- .../spanner/jdbc/JdbcPreparedStatementTest.java | 2 +- .../cloud/spanner/jdbc/JdbcSqlScriptVerifier.java | 2 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 2 +- .../cloud/spanner/jdbc/JdbcTypeConverterTest.java | 14 +++++++++++++- .../jdbc/ReadOnlyStalenessConverterTest.java | 2 +- .../cloud/spanner/jdbc/ReadOnlyStalenessTest.java | 2 +- .../spanner/jdbc/ReadOnlyStalenessUtilTest.java | 2 +- .../spanner/jdbc/ReadOnlyTransactionTest.java | 2 +- .../spanner/jdbc/ReadWriteTransactionTest.java | 2 +- .../jdbc/ReplaceableForwardingResultSetTest.java | 2 +- .../spanner/jdbc/SingleUseTransactionTest.java | 2 +- .../google/cloud/spanner/jdbc/SpannerPoolTest.java | 2 +- .../cloud/spanner/jdbc/SqlScriptVerifier.java | 2 +- .../cloud/spanner/jdbc/StatementParserTest.java | 5 ++++- .../spanner/jdbc/StatementResultImplTest.java | 2 +- .../cloud/spanner/jdbc/StatementTimeoutTest.java | 2 +- .../spanner/jdbc/TransactionModeConverterTest.java | 2 +- .../spanner/jdbc/it/ITBulkConnectionTest.java | 2 +- .../cloud/spanner/jdbc/it/ITJdbcConnectTest.java | 2 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 2 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 2 +- .../jdbc/it/ITJdbcReadWriteAutocommitTest.java | 2 +- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 2 +- .../cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java | 2 +- .../spanner/jdbc/it/ITReadOnlySpannerTest.java | 2 +- .../jdbc/it/ITReadWriteAutocommitSpannerTest.java | 2 +- .../spanner/jdbc/it/ITSqlMusicScriptTest.java | 2 +- .../spanner/jdbc/it/ITTransactionModeTest.java | 2 +- .../spanner/jdbc/it/ITTransactionRetryTest.java | 2 +- 49 files changed, 64 insertions(+), 49 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java index af5fcdceb7e2..4346bde5c46e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java index 798a4d2b75c9..8b4bdf78dab7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java @@ -22,7 +22,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.Timestamp; import com.google.cloud.spanner.ErrorCode; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java index a267d224fc15..960287ceea6b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java index 71a1865b84ec..3e854d3e16cb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java @@ -21,8 +21,8 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import com.google.cloud.Timestamp; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java index 91b54a961a87..4dcbd410e28e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.AutocommitDmlModeConverter; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java index cf7ba02e33cf..bf350419d241 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.jdbc; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java index 4c9447fb198a..f86295be65ca 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.BooleanConverter; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java index 87190f715d0b..38c978766dad 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java @@ -23,7 +23,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java index 1709ca4080aa..debd02b84f57 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java index fbc35f7286e5..268d4a1a09da 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import com.google.auth.oauth2.GoogleCredentials; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java index 3700f4c71a11..76a5cc5bf33d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java index b138b1e62510..533c417b47b0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.jdbc; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java index e6c54d115b14..b8a96cda9635 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.jdbc; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.anyListOf; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java index 073f33f31d66..77b41e9d04f7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.DurationConverter; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java index f55e383be8f6..7b9c4d050390 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import com.google.cloud.Timestamp; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java index c629eac207cf..46b85fe2dcfb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.rpc.Code; import java.io.IOException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java index 3bb04fc6309a..87011ab4180d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.rpc.Code; import java.io.IOException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 6740782a4aa3..3d9c77caf1a1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 6c3363be3832..4b7fb713ef7f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 336bfc1a5edf..cf93d69d099e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import com.google.cloud.ByteArray; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index bbfded162f67..c72db1ec4108 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java index 878b3a6bb0e9..7a4543089aa4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.jdbc.StatementResult.ResultType; import com.google.rpc.Code; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 648261efdf26..28bb25849ef1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 5978f3ac345c..773fcf94e3c9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -16,7 +16,19 @@ package com.google.cloud.spanner.jdbc; -import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.*; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.convert; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.getAsSqlTimestamp; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.setTimestampInCalendar; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toGoogleBytes; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toGoogleDate; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toGoogleDates; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toGoogleTimestamp; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toJavaByteArrays; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlDate; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlDates; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlTime; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlTimestamp; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlTimestamps; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java index 830c9085156d..12f1094fef86 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.Timestamp; import com.google.cloud.spanner.TimestampBound; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java index 6c0ca2d48b69..bc43e2aa1ed9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.jdbc; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java index 4c96632f371e..3af641f1f799 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java @@ -23,7 +23,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.Timestamp; import com.google.cloud.spanner.ErrorCode; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java index fe7622d934c8..0642b75ae57f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java index f64ff464d487..54a83c628940 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java @@ -21,7 +21,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java index 52c2f2600ba7..4f90773cf657 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java index b9890c5d4d36..720567c2ea8b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java index a4b8e37240ed..fd6e901eb018 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java index c32f39076578..df683b5ffb59 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ResultSet; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java index 9bfef7546ac4..6da65c15af2a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java @@ -19,7 +19,10 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java index a9f06ce57160..ea0b751a61c8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import com.google.cloud.Timestamp; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java index 03eb5a1b63da..5a6fb740c859 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyListOf; import static org.mockito.Mockito.doAnswer; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java index 8e14e608709a..60df4fddaa84 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.TransactionModeConverter; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java index a99b5ada67c5..1349636600c3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.ResultSet; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index cef3148e3111..0abee9000477 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 124664dc7cff..a43f83c48ef5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 40b17452d842..174e76c2b195 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -20,7 +20,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import com.google.api.client.util.Base64; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 315cdc17e199..dba6764fc14f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index 4a71bfd5c358..a1130f2b6e95 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index cc1334662945..f8154dc755df 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java index b3aa8ea751c8..51882c66e064 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java index aa464fd4b756..14834cc69319 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; import com.google.cloud.spanner.ErrorCode; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java index c8a0b897767c..d981a3685077 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; import com.google.cloud.spanner.IntegrationTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java index 19c204a75254..219d2153adac 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTest; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java index 159ca7e6c9ef..e3fc90c4e6f4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java @@ -18,7 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.Timestamp; import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; From aee217f25a1cc34f96bf499c87cd6876d303548d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 22 Jan 2020 15:23:29 +0100 Subject: [PATCH 0085/1979] feat: allow using existing OAuth token for JDBC connection (#37) * feat: allow using existing OAuth token for JDBC connection Allow the user to specify an existing OAuth token to use for a JDBC connection, instead of requiring the user to specify a credentials file or using the default credentials of the environment. Fixes #29 * tests: fix test cases * fix: remove unused method * fix: use default credentials when no file found * fix: fix faulty merge --- .../cloud/spanner/jdbc/ConnectionOptions.java | 45 ++++++++++++- .../google/cloud/spanner/jdbc/JdbcDriver.java | 6 ++ .../spanner/jdbc/ConnectionOptionsTest.java | 63 +++++++++++++++++++ .../cloud/spanner/jdbc/JdbcDriverTest.java | 14 +++++ .../spanner/jdbc/it/ITJdbcConnectTest.java | 49 ++++++++++----- 5 files changed, 161 insertions(+), 16 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java index ca25a5a257e4..f2e4358d6c3d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.auth.Credentials; +import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.NoCredentials; @@ -140,6 +141,7 @@ public String[] getValidValues() { static final boolean DEFAULT_READONLY = false; static final boolean DEFAULT_RETRY_ABORTS_INTERNALLY = true; private static final String DEFAULT_CREDENTIALS = null; + private static final String DEFAULT_OAUTH_TOKEN = null; private static final String DEFAULT_NUM_CHANNELS = null; private static final String DEFAULT_USER_AGENT = null; @@ -156,6 +158,10 @@ public String[] getValidValues() { public static final String RETRY_ABORTS_INTERNALLY_PROPERTY_NAME = "retryAbortsInternally"; /** Name of the 'credentials' connection property. */ public static final String CREDENTIALS_PROPERTY_NAME = "credentials"; + /** + * OAuth token to use for authentication. Cannot be used in combination with a credentials file. + */ + public static final String OAUTH_TOKEN_PROPERTY_NAME = "oauthToken"; /** Name of the 'numChannels' connection property. */ public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels"; /** Custom user agent string is only for other Google libraries. */ @@ -173,6 +179,7 @@ public String[] getValidValues() { ConnectionProperty.createBooleanProperty( RETRY_ABORTS_INTERNALLY_PROPERTY_NAME, "", DEFAULT_RETRY_ABORTS_INTERNALLY), ConnectionProperty.createStringProperty(CREDENTIALS_PROPERTY_NAME, ""), + ConnectionProperty.createStringProperty(OAUTH_TOKEN_PROPERTY_NAME, ""), ConnectionProperty.createStringProperty(NUM_CHANNELS_PROPERTY_NAME, ""), ConnectionProperty.createBooleanProperty( USE_PLAIN_TEXT_PROPERTY_NAME, "", DEFAULT_USE_PLAIN_TEXT), @@ -223,6 +230,7 @@ public static void closeSpanner() { public static class Builder { private String uri; private String credentialsUrl; + private String oauthToken; private Credentials credentials; private List statementExecutionInterceptors = Collections.emptyList(); @@ -308,6 +316,22 @@ public Builder setCredentialsUrl(String credentialsUrl) { return this; } + /** + * Sets the OAuth token to use with this connection. The token must be a valid token with access + * to the resources (project/instance/database) that the connection will be accessing. This + * authentication method cannot be used in combination with a credentials file. If both an OAuth + * token and a credentials file is specified, the {@link #build()} method will throw an + * exception. + * + * @param oauthToken A valid OAuth token for the Google Cloud project that is used by this + * connection. + * @return this builder + */ + public Builder setOAuthToken(String oauthToken) { + this.oauthToken = oauthToken; + return this; + } + @VisibleForTesting Builder setStatementExecutionInterceptors(List interceptors) { this.statementExecutionInterceptors = interceptors; @@ -339,6 +363,7 @@ public static Builder newBuilder() { private final String uri; private final String credentialsUrl; + private final String oauthToken; private final boolean usePlainText; private final String host; @@ -363,6 +388,13 @@ private ConnectionOptions(Builder builder) { this.uri = builder.uri; this.credentialsUrl = builder.credentialsUrl != null ? builder.credentialsUrl : parseCredentials(builder.uri); + this.oauthToken = + builder.oauthToken != null ? builder.oauthToken : parseOAuthToken(builder.uri); + // Check that not both credentials and an OAuth token have been specified. + Preconditions.checkArgument( + (builder.credentials == null && this.credentialsUrl == null) || this.oauthToken == null, + "Cannot specify both credentials and an OAuth token."); + this.usePlainText = parseUsePlainText(this.uri); this.userAgent = parseUserAgent(this.uri); @@ -376,8 +408,13 @@ private ConnectionOptions(Builder builder) { // Using credentials on a plain text connection is not allowed, so if the user has not specified // any credentials and is using a plain text connection, we should not try to get the // credentials from the environment, but default to NoCredentials. - if (builder.credentials == null && this.credentialsUrl == null && this.usePlainText) { + if (builder.credentials == null + && this.credentialsUrl == null + && this.oauthToken == null + && this.usePlainText) { this.credentials = NoCredentials.getInstance(); + } else if (this.oauthToken != null) { + this.credentials = new GoogleCredentials(new AccessToken(oauthToken, null)); } else { this.credentials = builder.credentials == null @@ -446,6 +483,12 @@ static String parseCredentials(String uri) { return value != null ? value : DEFAULT_CREDENTIALS; } + @VisibleForTesting + static String parseOAuthToken(String uri) { + String value = parseUriProperty(uri, OAUTH_TOKEN_PROPERTY_NAME); + return value != null ? value : DEFAULT_OAUTH_TOKEN; + } + @VisibleForTesting static String parseNumChannels(String uri) { String value = parseUriProperty(uri, NUM_CHANNELS_PROPERTY_NAME); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 80ee2cc6d14b..c43f9797ecfe 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -74,6 +74,12 @@ *

  • credentials (String): URL for the credentials file to use for the connection. If you do not * specify any credentials at all, the default credentials of the environment as returned by * {@link GoogleCredentials#getApplicationDefault()} will be used. + *
  • oauthtoken (String): A valid OAuth2 token to use for the JDBC connection. The token must + * have been obtained with one or both of the scopes + * 'https://www.googleapis.com/auth/spanner.admin' and/or + * 'https://www.googleapis.com/auth/spanner.data'. If you specify both a credentials file and + * an OAuth token, the JDBC driver will throw an exception when you try to obtain a + * connection. *
  • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. *
  • readonly (boolean): Sets the initial readonly mode for the connection. Default is false. *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java index 850836d3da82..8eacbbf3a737 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java @@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; +import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.spanner.SpannerOptions; import java.util.Arrays; @@ -323,4 +324,66 @@ public void testParsePropertiesSpecifiedMultipleTimes() { "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" + ";autocommit=false;readonly=false;autocommit=true"); } + + @Test + public void testParseOAuthToken() { + assertThat( + ConnectionOptions.parseUriProperty( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" + + "?oauthtoken=RsT5OjbzRn430zqMLgV3Ia", + "OAuthToken")) + .isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); + // Try to use both credentials and an OAuth token. That should fail. + ConnectionOptions.Builder builder = + ConnectionOptions.newBuilder() + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" + + "?OAuthToken=RsT5OjbzRn430zqMLgV3Ia;credentials=/path/to/credentials.json"); + try { + builder.build(); + fail("missing expected exception"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); + } + + // Now try to use only an OAuth token. + builder = + ConnectionOptions.newBuilder() + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" + + "?OAuthToken=RsT5OjbzRn430zqMLgV3Ia"); + ConnectionOptions options = builder.build(); + assertThat(options.getCredentials()).isInstanceOf(GoogleCredentials.class); + GoogleCredentials credentials = (GoogleCredentials) options.getCredentials(); + assertThat(credentials.getAccessToken().getTokenValue()).isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); + } + + @Test + public void testSetOAuthToken() { + ConnectionOptions options = + ConnectionOptions.newBuilder() + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") + .setOAuthToken("RsT5OjbzRn430zqMLgV3Ia") + .build(); + assertThat(options.getCredentials()).isInstanceOf(GoogleCredentials.class); + GoogleCredentials credentials = (GoogleCredentials) options.getCredentials(); + assertThat(credentials.getAccessToken()).isNotNull(); + assertThat(credentials.getAccessToken().getTokenValue()).isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); + } + + @Test + public void testSetOAuthTokenAndCredentials() { + try { + ConnectionOptions.newBuilder() + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") + .setOAuthToken("RsT5OjbzRn430zqMLgV3Ia") + .setCredentialsUrl(FILE_TEST_PATH) + .build(); + fail("missing expected exception"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 77866dcbb411..1215434c90a6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; import com.google.cloud.spanner.MockSpannerServiceImpl; import io.grpc.Server; @@ -87,4 +88,17 @@ public void testInvalidConnect() throws SQLException { assertThat(connection.isClosed()).isFalse(); } } + + @Test + public void testConnectWithCredentialsAndOAuthToken() throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner://localhost:%d/projects/test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s;OAuthToken=%s", + server.getPort(), TEST_KEY_PATH, "some-token"))) { + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 0abee9000477..580bfff989ac 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -16,14 +16,16 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; +import com.google.auth.oauth2.AccessToken; +import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcDataSource; +import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -57,30 +59,30 @@ private String createBaseUrl() { } private void testDefaultConnection(Connection connection) throws SQLException { - assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class), is(true)); + assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class)).isTrue(); CloudSpannerJdbcConnection cs = connection.unwrap(CloudSpannerJdbcConnection.class); - assertThat(cs.getAutoCommit(), is(true)); - assertThat(cs.isReadOnly(), is(false)); + assertThat(cs.getAutoCommit()).isTrue(); + assertThat(cs.isReadOnly()).isFalse(); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(1))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(1)).isEqualTo(1); } cs.setAutoCommit(false); - assertThat(cs.isRetryAbortsInternally(), is(true)); + assertThat(cs.isRetryAbortsInternally()).isTrue(); } private void testNonDefaultConnection(Connection connection) throws SQLException { - assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class), is(true)); + assertThat(connection.isWrapperFor(CloudSpannerJdbcConnection.class)).isTrue(); CloudSpannerJdbcConnection cs = connection.unwrap(CloudSpannerJdbcConnection.class); - assertThat(cs.getAutoCommit(), is(false)); - assertThat(cs.isReadOnly(), is(true)); + assertThat(cs.getAutoCommit()).isFalse(); + assertThat(cs.isReadOnly()).isTrue(); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(1))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(1)).isEqualTo(1); } connection.commit(); cs.setReadOnly(false); - assertThat(cs.isRetryAbortsInternally(), is(false)); + assertThat(cs.isRetryAbortsInternally()).isFalse(); } @Test @@ -194,4 +196,21 @@ public void testConnectWithDataSourceWithConflictingValues() throws SQLException testNonDefaultConnection(connection); } } + + @Test + public void testConnectWithOAuthToken() throws Exception { + GoogleCredentials credentials; + if (hasValidKeyFile()) { + credentials = GoogleCredentials.fromStream(new FileInputStream(getKeyFile())); + } else { + credentials = GoogleCredentials.getApplicationDefault(); + } + credentials = credentials.createScoped(SpannerOptions.getDefaultInstance().getScopes()); + AccessToken token = credentials.refreshAccessToken(); + String urlWithOAuth = createBaseUrl() + "?OAuthToken=" + token.getTokenValue(); + try (Connection connectionWithOAuth = DriverManager.getConnection(urlWithOAuth)) { + // Try to do a query using the connection created with an OAuth token. + testDefaultConnection(connectionWithOAuth); + } + } } From c82c0e614f80fa0c43ffb0095297d7de5b6767ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 28 Jan 2020 08:30:59 +0100 Subject: [PATCH 0086/1979] fix: add support for WITH clauses (#42) --- .../cloud/spanner/jdbc/StatementParser.java | 2 +- .../spanner/jdbc/StatementParserTest.java | 28 +++++++++++++++++++ .../spanner/jdbc/ITSqlMusicScriptTest.sql | 5 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java index 9ed1ecd23ba1..e43a0974abea 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java @@ -161,7 +161,7 @@ ClientSideStatement getClientSideStatement() { } private final Set ddlStatements = ImmutableSet.of("CREATE", "DROP", "ALTER"); - private final Set selectStatements = ImmutableSet.of("SELECT"); + private final Set selectStatements = ImmutableSet.of("SELECT", "WITH"); private final Set dmlStatements = ImmutableSet.of("INSERT", "UPDATE", "DELETE"); private final Set statements; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java index 6da65c15af2a..1344a0f33346 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java @@ -266,6 +266,27 @@ public void testIsQuery() { assertTrue(parser.isQuery("select * from foo")); assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); + assertTrue( + parser.isQuery( + "WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" + + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + + "SELECT * FROM subQ1\n" + + "UNION ALL\n" + + "SELECT * FROM subQ2")); + assertTrue( + parser.isQuery( + "with subQ1 AS (SELECT SchoolID FROM Roster),\n" + + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + + "select * FROM subQ1\n" + + "UNION ALL\n" + + "SELECT * FROM subQ2")); + assertTrue( + parser + .parse( + Statement.of( + "-- this is a comment\nwith foo as (select * from bar)\nselect * from foo")) + .isQuery()); + assertTrue(parser.parse(Statement.of("-- this is a comment\nselect * from foo")).isQuery()); assertTrue( parser @@ -310,6 +331,13 @@ public void testQueryHints() { assertTrue( parser.isQuery( "@{JOIN_METHOD=HASH_JOIN}\n /* Multi line comment\n with more comments\n */SELECT * FROM PersonsTable")); + assertTrue( + parser.isQuery( + "@{JOIN_METHOD=HASH_JOIN} WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" + + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + + "SELECT * FROM subQ1\n" + + "UNION ALL\n" + + "SELECT * FROM subQ2")); // Invalid query hints. assertFalse(parser.isQuery("@{JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql index 93218da9765d..243cdda32bd0 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql @@ -668,3 +668,8 @@ WHERE SingerId=2; SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED FROM Songs WHERE SingerId=2; + +@EXPECT RESULT_SET +WITH Song2 AS (SELECT * FROM Songs WHERE SingerId=2) +SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED +FROM Song2; From 9138fc5e7d7cd72c4f31aa7311f2072776d0294d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2020 11:37:15 +1100 Subject: [PATCH 0087/1979] chore: release 1.13.0 (#39) * created CHANGELOG.md [ci skip] * updated README.md [ci skip] * updated versions.txt [ci skip] * updated pom.xml [ci skip] --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 8 ++++---- 4 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 java-spanner-jdbc/CHANGELOG.md diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md new file mode 100644 index 000000000000..3fbddecd3657 --- /dev/null +++ b/java-spanner-jdbc/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +## [1.13.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/1.12.0...v1.13.0) (2020-01-28) + + +### Features + +* allow using existing OAuth token for JDBC connection ([#37](https://www.github.com/googleapis/java-spanner-jdbc/issues/37)) ([b368b84](https://www.github.com/googleapis/java-spanner-jdbc/commit/b368b8407b3e2884458d956a9207cb4e12e37848)), closes [#29](https://www.github.com/googleapis/java-spanner-jdbc/issues/29) + + +### Bug Fixes + +* add support for WITH clauses ([#42](https://www.github.com/googleapis/java-spanner-jdbc/issues/42)) ([7f4bea4](https://www.github.com/googleapis/java-spanner-jdbc/commit/7f4bea43c42df68258f776944ea744069a1a218e)) +* allow dots and colons in project id ([#36](https://www.github.com/googleapis/java-spanner-jdbc/issues/36)) ([5957008](https://www.github.com/googleapis/java-spanner-jdbc/commit/59570085403fa7002616dd535df4666a384c3438)), closes [#33](https://www.github.com/googleapis/java-spanner-jdbc/issues/33) + + +### Dependencies + +* update core dependencies ([#25](https://www.github.com/googleapis/java-spanner-jdbc/issues/25)) ([9f4f4ad](https://www.github.com/googleapis/java-spanner-jdbc/commit/9f4f4ad1b076bd3131296c9f7f6558f2bc885d42)) +* update dependency org.threeten:threetenbp to v1.4.1 ([7cc951b](https://www.github.com/googleapis/java-spanner-jdbc/commit/7cc951b340b072e7853df868aaf7c17f854a69f5)) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 666bc7384d72..db50ef106a7c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.12.0 + 1.13.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.12.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.13.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.12.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.13.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fb78d97714ea..05fc700319ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.12.1-SNAPSHOT + 1.13.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index de9c4df19ff4..72036a35b1ac 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ -# Format: -# module:released-version:current-version - -google-cloud-spanner-jdbc:1.12.0:1.12.1-SNAPSHOT +# Format: +# module:released-version:current-version + +google-cloud-spanner-jdbc:1.13.0:1.13.0 From d1b67a9da4257e5aefff1fb619b39c4a185ef8b0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 30 Jan 2020 01:38:18 +0100 Subject: [PATCH 0088/1979] deps: update core transport dependencies to v1.34.1 (#43) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 05fc700319ef..bb962565ec74 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ 1.30.7 1.92.2 1.53.0 - 1.34.0 + 1.34.1 28.2-android 4.13 1.17.0 From e9e4bbb86ac15dad9bc0be8194c0ad22b2134fb3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 30 Jan 2020 03:05:29 +0100 Subject: [PATCH 0089/1979] deps: update dependency com.google.truth:truth to v1.0.1 (#32) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bb962565ec74..de2acbc9c5b7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -247,7 +247,7 @@ com.google.truth truth - 1.0 + 1.0.1 test From 00a8da4364b95110181f5236fe4ba2d234a44911 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 30 Jan 2020 03:41:13 +0100 Subject: [PATCH 0090/1979] deps: update core dependencies (#40) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index de2acbc9c5b7..9e8bbdf4bb42 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,9 +58,9 @@ google-cloud-spanner-jdbc - 1.26.0 + 1.27.0 1.30.7 - 1.92.2 + 1.92.3 1.53.0 1.34.1 28.2-android @@ -72,7 +72,7 @@ 1.47.0 2.2 2.3.4 - 0.19.0 + 0.20.0 From 32789642b0d8c2cf6e8db4efa38fa338e3017122 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 31 Jan 2020 09:17:44 -0800 Subject: [PATCH 0091/1979] chore: group guava with other core dependencies --- java-spanner-jdbc/renovate.json | 3 +- java-spanner-jdbc/synth.metadata | 808 +------------------------------ 2 files changed, 3 insertions(+), 808 deletions(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index a5cdff45c319..268a4669abfd 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -22,7 +22,8 @@ "^com.google.api:gax", "^com.google.auth:", "^com.google.cloud:google-cloud-core", - "^io.grpc:" + "^io.grpc:", + "^com.google.guava:" ], "groupName": "core dependencies" }, diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 50195b614ead..832d4b6758d4 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,5 +1,5 @@ { - "updateTime": "2020-01-16T09:11:16.210833Z", + "updateTime": "2020-01-31T09:14:17.375897Z", "sources": [ { "template": { @@ -8,811 +8,5 @@ "version": "2019.10.17" } } - ], - "newFiles": [ - { - "path": "pom.xml" - }, - { - "path": ".repo-metadata.json" - }, - { - "path": "java.header" - }, - { - "path": "CONTRIBUTING.md" - }, - { - "path": "synth.metadata" - }, - { - "path": "renovate.json" - }, - { - "path": "versions.txt" - }, - { - "path": "synth.py" - }, - { - "path": "license-checks.xml" - }, - { - "path": "CODE_OF_CONDUCT.md" - }, - { - "path": "LICENSE" - }, - { - "path": "codecov.yaml" - }, - { - "path": ".gitignore" - }, - { - "path": "README.md" - }, - { - "path": ".github/release-please.yml" - }, - { - "path": ".github/PULL_REQUEST_TEMPLATE.md" - }, - { - "path": ".github/ISSUE_TEMPLATE/feature_request.md" - }, - { - "path": ".github/ISSUE_TEMPLATE/support_request.md" - }, - { - "path": ".github/ISSUE_TEMPLATE/bug_report.md" - }, - { - "path": ".kokoro/build.sh" - }, - { - "path": ".kokoro/common.cfg" - }, - { - "path": ".kokoro/build.bat" - }, - { - "path": ".kokoro/linkage-monitor.sh" - }, - { - "path": ".kokoro/coerce_logs.sh" - }, - { - "path": ".kokoro/dependencies.sh" - }, - { - "path": ".kokoro/trampoline.sh" - }, - { - "path": ".kokoro/continuous/samples.cfg" - }, - { - "path": ".kokoro/continuous/java8.cfg" - }, - { - "path": ".kokoro/continuous/integration.cfg" - }, - { - "path": ".kokoro/continuous/java11.cfg" - }, - { - "path": ".kokoro/continuous/propose_release.cfg" - }, - { - "path": ".kokoro/continuous/common.cfg" - }, - { - "path": ".kokoro/continuous/propose_release.sh" - }, - { - "path": ".kokoro/continuous/java7.cfg" - }, - { - "path": ".kokoro/continuous/lint.cfg" - }, - { - "path": ".kokoro/continuous/java8-osx.cfg" - }, - { - "path": ".kokoro/continuous/dependencies.cfg" - }, - { - "path": ".kokoro/continuous/java8-win.cfg" - }, - { - "path": ".kokoro/nightly/samples.cfg" - }, - { - "path": ".kokoro/nightly/java8.cfg" - }, - { - "path": ".kokoro/nightly/integration.cfg" - }, - { - "path": ".kokoro/nightly/java11.cfg" - }, - { - "path": ".kokoro/nightly/common.cfg" - }, - { - "path": ".kokoro/nightly/java7.cfg" - }, - { - "path": ".kokoro/nightly/lint.cfg" - }, - { - "path": ".kokoro/nightly/java8-osx.cfg" - }, - { - "path": ".kokoro/nightly/dependencies.cfg" - }, - { - "path": ".kokoro/nightly/java8-win.cfg" - }, - { - "path": ".kokoro/release/publish_javadoc.cfg" - }, - { - "path": ".kokoro/release/common.sh" - }, - { - "path": ".kokoro/release/promote.sh" - }, - { - "path": ".kokoro/release/common.cfg" - }, - { - "path": ".kokoro/release/publish_javadoc.sh" - }, - { - "path": ".kokoro/release/drop.sh" - }, - { - "path": ".kokoro/release/stage.sh" - }, - { - "path": ".kokoro/release/promote.cfg" - }, - { - "path": ".kokoro/release/snapshot.cfg" - }, - { - "path": ".kokoro/release/bump_snapshot.cfg" - }, - { - "path": ".kokoro/release/drop.cfg" - }, - { - "path": ".kokoro/release/bump_snapshot.sh" - }, - { - "path": ".kokoro/release/stage.cfg" - }, - { - "path": ".kokoro/release/snapshot.sh" - }, - { - "path": ".kokoro/presubmit/samples.cfg" - }, - { - "path": ".kokoro/presubmit/java8.cfg" - }, - { - "path": ".kokoro/presubmit/integration.cfg" - }, - { - "path": ".kokoro/presubmit/java11.cfg" - }, - { - "path": ".kokoro/presubmit/linkage-monitor.cfg" - }, - { - "path": ".kokoro/presubmit/common.cfg" - }, - { - "path": ".kokoro/presubmit/java7.cfg" - }, - { - "path": ".kokoro/presubmit/lint.cfg" - }, - { - "path": ".kokoro/presubmit/java8-osx.cfg" - }, - { - "path": ".kokoro/presubmit/dependencies.cfg" - }, - { - "path": ".kokoro/presubmit/clirr.cfg" - }, - { - "path": ".kokoro/presubmit/java8-win.cfg" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java" - }, - { - "path": "src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestSetStatements.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key-cloud-storage.json" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/CommentsTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitReadOnly.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key-app-default.json" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestInvalidStatements.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestReadOnlyStaleness.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/test-key.json" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_InsertTestData.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode_ReadOnly.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITTransactionModeTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/SetStatementTimeoutTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestAutocommitDmlMode.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest_CreateTables.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlMusicScriptTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetReadTimestamp.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestGetCommitTimestamp.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_CreateTables.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTransactionMode.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestTemporaryTransactions.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/ITReadWriteAutocommitSpannerTest.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Songs.txt" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Singers.txt" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Albums.txt" - }, - { - "path": "src/test/resources/com/google/cloud/spanner/jdbc/it/Concerts.txt" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/Connection.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java" - }, - { - "path": "src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql" - }, - { - "path": "src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql" - }, - { - "path": "src/main/resources/META-INF/services/java.sql.Driver" - } ] } \ No newline at end of file From 3cafdbfccd17cb6ae171dda3e18ae952852dbe07 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 3 Feb 2020 10:13:18 -0800 Subject: [PATCH 0092/1979] chore: linkage monitor check should skipp clirr and enforcer --- java-spanner-jdbc/.kokoro/linkage-monitor.sh | 7 ++++++- java-spanner-jdbc/synth.metadata | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/linkage-monitor.sh b/java-spanner-jdbc/.kokoro/linkage-monitor.sh index a3e5ab30e5b3..651c7b5ebd59 100755 --- a/java-spanner-jdbc/.kokoro/linkage-monitor.sh +++ b/java-spanner-jdbc/.kokoro/linkage-monitor.sh @@ -23,7 +23,12 @@ cd github/java-spanner-jdbc/ java -version echo ${JOB_TYPE} -mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgcloud.download.skip=true -B -V +mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dmaven.javadoc.skip=true \ + -Dgcloud.download.skip=true # Kokoro job cloud-opensource-java/ubuntu/linkage-monitor-gcs creates this JAR JAR=linkage-monitor-latest-all-deps.jar diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 832d4b6758d4..a627f8ae9558 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,5 +1,5 @@ { - "updateTime": "2020-01-31T09:14:17.375897Z", + "updateTime": "2020-02-01T09:13:43.890088Z", "sources": [ { "template": { From 473919103476be4fada9ffeeb20aa52fd65e9bc5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 3 Feb 2020 21:26:07 +0100 Subject: [PATCH 0093/1979] deps: update protobuf.version to v3.11.3 (#48) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9e8bbdf4bb42..a3d30a59e4a6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -66,7 +66,7 @@ 28.2-android 4.13 1.17.0 - 3.11.1 + 3.11.3 1.4.1 1.8.1 1.47.0 From 724eb41ac64c7582223ecaae4e455f3cba201dbf Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 3 Feb 2020 21:26:27 +0100 Subject: [PATCH 0094/1979] deps: update dependency com.google.api-client:google-api-client-bom to v1.30.8 (#46) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a3d30a59e4a6..04b12bf5c5ed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -59,7 +59,7 @@ google-cloud-spanner-jdbc 1.27.0 - 1.30.7 + 1.30.8 1.92.3 1.53.0 1.34.1 From dc573ff711ed5dc636695e9a3355a0dbbf2ea12d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 4 Feb 2020 00:59:19 +0100 Subject: [PATCH 0095/1979] deps: update core dependencies --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 04b12bf5c5ed..8e1751e849cb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -60,8 +60,8 @@ google-cloud-spanner-jdbc 1.27.0 1.30.8 - 1.92.3 - 1.53.0 + 1.92.4 + 1.53.1 1.34.1 28.2-android 4.13 From 59cfd73dd15a52134018f5df02ed5bd9f75e69b2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2020 13:59:16 +1100 Subject: [PATCH 0096/1979] chore: release 1.13.1-SNAPSHOT (#51) * updated versions.txt [ci skip] * updated pom.xml [ci skip] --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8e1751e849cb..150ca2696c5a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.13.0 + 1.13.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 72036a35b1ac..72f0ebd53b0a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.13.0:1.13.0 +google-cloud-spanner-jdbc:1.13.0:1.13.1-SNAPSHOT From 571d8199206e9c19e203366161dda8d45e519b76 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Tue, 11 Feb 2020 11:50:48 -0800 Subject: [PATCH 0097/1979] chore: only allow renovate-bot for trusted-contribution auto-labeling --- java-spanner-jdbc/.github/trusted-contribution.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java-spanner-jdbc/.github/trusted-contribution.yml diff --git a/java-spanner-jdbc/.github/trusted-contribution.yml b/java-spanner-jdbc/.github/trusted-contribution.yml new file mode 100644 index 000000000000..f247d5c78934 --- /dev/null +++ b/java-spanner-jdbc/.github/trusted-contribution.yml @@ -0,0 +1,2 @@ +trustedContributors: +- renovate-bot \ No newline at end of file From e8aeae02d3dd9384c4b21a869e996ef8b0861680 Mon Sep 17 00:00:00 2001 From: David Supplee Date: Wed, 12 Feb 2020 14:30:13 -0800 Subject: [PATCH 0098/1979] chore: update github url (#56) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 150ca2696c5a..8b8e5d5ecba8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -7,7 +7,7 @@ 1.13.1-SNAPSHOT jar Google Cloud Spanner JDBC - https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-contrib/google-cloud-spanner-jdbc + https://github.com/googleapis/java-spanner-jdbc JDBC driver for Google Cloud Spanner. From 43b804fe3ef4f1be7fcbb63ca716380d9863d3ec Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 13 Feb 2020 05:01:36 +0100 Subject: [PATCH 0099/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.2.2 (#55) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8b8e5d5ecba8..7b7d6b1ac80e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -371,7 +371,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.2.2 From 469955f6d41d0f5b7f2e6baf6b403b430a48900b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 13 Feb 2020 05:02:13 +0100 Subject: [PATCH 0100/1979] deps: update core dependencies to v1.92.5 (#53) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7b7d6b1ac80e..cfb91d6bf20a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -60,7 +60,7 @@ google-cloud-spanner-jdbc 1.27.0 1.30.8 - 1.92.4 + 1.92.5 1.53.1 1.34.1 28.2-android From edadf0a227744869a8ac8011e02c0b951ddb0bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 19 Feb 2020 01:57:14 +0100 Subject: [PATCH 0101/1979] fix: include Spanner gRPC test dependencies (#63) * fix: include Spanner gRPC test dependencies * fix: add grpc dependencies as ignored dependencies --- java-spanner-jdbc/pom.xml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cfb91d6bf20a..d0ea8f26b7b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ 3.11.3 1.4.1 1.8.1 - 1.47.0 + 1.49.2 2.2 2.3.4 0.20.0 @@ -244,6 +244,24 @@ test-jar test + + com.google.api.grpc + grpc-google-cloud-spanner-v1 + ${spanner.version} + test + + + com.google.api.grpc + grpc-google-cloud-spanner-admin-instance-v1 + ${spanner.version} + test + + + com.google.api.grpc + grpc-google-cloud-spanner-admin-database-v1 + ${spanner.version} + test + com.google.truth truth @@ -321,7 +339,12 @@ org.apache.maven.plugins maven-dependency-plugin - com.google.api:gax-grpc + + com.google.api:gax-grpc + com.google.api.grpc:grpc-google-cloud-spanner-v1 + com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 + com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 + From 19bd94b8c17552ed8b4d8a2c591307e0b384bd36 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 20 Feb 2020 02:52:47 +0100 Subject: [PATCH 0102/1979] deps: update core dependencies to v1.27.1 (#61) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d0ea8f26b7b0..fc8f12e5fe4e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 1.27.0 + 1.27.1 1.30.8 1.92.5 1.53.1 From bf6f1f506205cc04569e6802013da4adf1e9db06 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 20 Feb 2020 02:53:19 +0100 Subject: [PATCH 0103/1979] deps: update core transport dependencies to v1.34.2 (#62) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fc8f12e5fe4e..3552c7b08075 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ 1.30.8 1.92.5 1.53.1 - 1.34.1 + 1.34.2 28.2-android 4.13 1.17.0 From 394b50c6fc22edfbc2a45ef78d3064b629342d65 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 21 Feb 2020 15:47:08 -0800 Subject: [PATCH 0104/1979] chore: update common templates This PR was generated using Autosynth. :rainbow: Commits in this repo since last synth: bf6f1f506205cc04569e6802013da4adf1e9db06 deps: update core transport dependencies to v1.34.2 (#62) 19bd94b8c17552ed8b4d8a2c591307e0b384bd36 deps: update core dependencies to v1.27.1 (#61) edadf0a227744869a8ac8011e02c0b951ddb0bec fix: include Spanner gRPC test dependencies (#63) 469955f6d41d0f5b7f2e6baf6b403b430a48900b deps: update core dependencies to v1.92.5 (#53) 43b804fe3ef4f1be7fcbb63ca716380d9863d3ec build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.2.2 (#55) e8aeae02d3dd9384c4b21a869e996ef8b0861680 chore: update github url (#56) 571d8199206e9c19e203366161dda8d45e519b76 chore: only allow renovate-bot for trusted-contribution auto-labeling 59cfd73dd15a52134018f5df02ed5bd9f75e69b2 chore: release 1.13.1-SNAPSHOT (#51) dc573ff711ed5dc636695e9a3355a0dbbf2ea12d deps: update core dependencies 724eb41ac64c7582223ecaae4e455f3cba201dbf deps: update dependency com.google.api-client:google-api-client-bom to v1.30.8 (#46) 473919103476be4fada9ffeeb20aa52fd65e9bc5 deps: update protobuf.version to v3.11.3 (#48)
    Log from Synthtool ``` synthtool > Executing /tmpfs/src/git/autosynth/working_repo/synth.py. On branch autosynth nothing to commit, working tree clean HEAD detached at FETCH_HEAD nothing to commit, working tree clean .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md .github/ISSUE_TEMPLATE/support_request.md .github/PULL_REQUEST_TEMPLATE.md .github/release-please.yml .kokoro/build.bat .kokoro/build.sh .kokoro/coerce_logs.sh .kokoro/common.cfg .kokoro/continuous/common.cfg .kokoro/continuous/dependencies.cfg .kokoro/continuous/integration.cfg .kokoro/continuous/java11.cfg .kokoro/continuous/java7.cfg .kokoro/continuous/java8-osx.cfg .kokoro/continuous/java8-win.cfg .kokoro/continuous/java8.cfg .kokoro/continuous/lint.cfg .kokoro/continuous/propose_release.cfg .kokoro/continuous/propose_release.sh .kokoro/continuous/samples.cfg .kokoro/dependencies.sh .kokoro/linkage-monitor.sh .kokoro/nightly/common.cfg .kokoro/nightly/dependencies.cfg .kokoro/nightly/integration.cfg .kokoro/nightly/java11.cfg .kokoro/nightly/java7.cfg .kokoro/nightly/java8-osx.cfg .kokoro/nightly/java8-win.cfg .kokoro/nightly/java8.cfg .kokoro/nightly/lint.cfg .kokoro/nightly/samples.cfg .kokoro/presubmit/clirr.cfg .kokoro/presubmit/common.cfg .kokoro/presubmit/dependencies.cfg .kokoro/presubmit/integration.cfg .kokoro/presubmit/java11.cfg .kokoro/presubmit/java7.cfg .kokoro/presubmit/java8-osx.cfg .kokoro/presubmit/java8-win.cfg .kokoro/presubmit/java8.cfg .kokoro/presubmit/linkage-monitor.cfg .kokoro/presubmit/lint.cfg .kokoro/presubmit/samples.cfg .kokoro/release/bump_snapshot.cfg .kokoro/release/bump_snapshot.sh .kokoro/release/common.cfg .kokoro/release/common.sh .kokoro/release/drop.cfg .kokoro/release/drop.sh .kokoro/release/promote.cfg .kokoro/release/promote.sh .kokoro/release/publish_javadoc.cfg .kokoro/release/publish_javadoc.sh .kokoro/release/snapshot.cfg .kokoro/release/snapshot.sh .kokoro/release/stage.cfg .kokoro/release/stage.sh .kokoro/trampoline.sh CODE_OF_CONDUCT.md CONTRIBUTING.md LICENSE README.md codecov.yaml java.header license-checks.xml renovate.json synthtool > Wrote metadata to synth.metadata. ```
    --- java-spanner-jdbc/.kokoro/build.sh | 23 +++++++++++++++-------- java-spanner-jdbc/renovate.json | 7 +++++++ java-spanner-jdbc/synth.metadata | 18 ++++++++++++++++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index f1ae58408da5..d11958c5a67e 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -62,14 +62,21 @@ integration) bash .kokoro/coerce_logs.sh ;; samples) - mvn -B \ - -Penable-samples \ - -DtrimStackTrace=false \ - -Dclirr.skip=true \ - -Denforcer.skip=true \ - -fae \ - verify - bash .kokoro/coerce_logs.sh + if [[ -f samples/pom.xml ]] + then + pushd samples + mvn -B \ + -Penable-samples \ + -DtrimStackTrace=false \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -fae \ + verify + bash .kokoro/coerce_logs.sh + popd + else + echo "no sample pom.xml found - skipping sample tests" + fi ;; clirr) mvn -B -Denforcer.skip=true clirr:check diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 268a4669abfd..fc6412701ada 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -54,6 +54,13 @@ "semanticCommitType": "build", "semanticCommitScope": "deps" }, + { + "packagePatterns": [ + "^com.google.cloud:libraries-bom" + ], + "semanticCommitType": "chore", + "semanticCommitScope": "deps" + }, { "packagePatterns": [ "^com.google.cloud:google-cloud-" diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index a627f8ae9558..2a500865b92a 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,11 +1,25 @@ { - "updateTime": "2020-02-01T09:13:43.890088Z", + "updateTime": "2020-02-21T23:11:00.093008Z", "sources": [ + { + "git": { + "name": ".", + "remote": "https://github.com/googleapis/java-spanner-jdbc.git", + "sha": "8739015f62289adb92fd55b19a5bff8762da20a9" + } + }, + { + "git": { + "name": "synthtool", + "remote": "rpc://devrel/cloud/libraries/tools/autosynth", + "sha": "706a38c26db42299845396cdae55db635c38794a" + } + }, { "template": { "name": "java_library", "origin": "synthtool.gcp", - "version": "2019.10.17" + "version": "2020.2.4" } } ] From 56ec0d595004a62772f7ef21e94d0f1ef89e6fc8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 24 Feb 2020 10:37:56 -0800 Subject: [PATCH 0105/1979] chore: update common templates --- java-spanner-jdbc/.kokoro/build.sh | 24 +++++++++++++++++++++--- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index d11958c5a67e..284a0def7c2b 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -37,19 +37,24 @@ if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTI export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_ROOT}/src/${GOOGLE_APPLICATION_CREDENTIALS}) fi +RETURN_CODE=0 +set +e + case ${JOB_TYPE} in test) mvn test -B -Dclirr.skip=true -Denforcer.skip=true + RETURN_CODE=$? bash ${KOKORO_GFILE_DIR}/codecov.sh - bash .kokoro/coerce_logs.sh ;; lint) mvn \ -Penable-samples \ com.coveo:fmt-maven-plugin:check + RETURN_CODE=$? ;; javadoc) mvn javadoc:javadoc javadoc:test-javadoc + RETURN_CODE=$? ;; integration) mvn -B ${INTEGRATION_TEST_ARGS} \ @@ -59,7 +64,7 @@ integration) -Denforcer.skip=true \ -fae \ verify - bash .kokoro/coerce_logs.sh + RETURN_CODE=$? ;; samples) if [[ -f samples/pom.xml ]] @@ -72,7 +77,7 @@ samples) -Denforcer.skip=true \ -fae \ verify - bash .kokoro/coerce_logs.sh + RETURN_CODE=$? popd else echo "no sample pom.xml found - skipping sample tests" @@ -80,7 +85,20 @@ samples) ;; clirr) mvn -B -Denforcer.skip=true clirr:check + RETURN_CODE=$? ;; *) ;; esac + +# fix output location of logs +bash .kokoro/coerce_logs.sh + +if [[ "${ENABLE_BUILD_COP}" == "true" ]] +then + chmod +x ${KOKORO_GFILE_DIR}/linux_amd64/buildcop + ${KOKORO_GFILE_DIR}/linux_amd64/buildcop -repo=googleapis/java-spanner-jdbc +fi + +echo "exiting with ${RETURN_CODE}" +exit ${RETURN_CODE} \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 2a500865b92a..ce57fd2f8c26 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,11 +1,11 @@ { - "updateTime": "2020-02-21T23:11:00.093008Z", + "updateTime": "2020-02-22T10:16:10.861561Z", "sources": [ { "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "8739015f62289adb92fd55b19a5bff8762da20a9" + "sha": "e6ec261803cbdfd2f82aa8d524de1cbed2fae44e" } }, { From cca88a508c4d36ea30ef465fe689b2dd17f716f3 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 25 Feb 2020 10:21:39 -0800 Subject: [PATCH 0106/1979] chore: update common templates --- java-spanner-jdbc/.kokoro/build.sh | 8 +++++-- .../.kokoro/continuous/java8.cfg | 5 +++++ .../.kokoro/nightly/integration.cfg | 14 +++++++++++++ java-spanner-jdbc/.kokoro/nightly/java8.cfg | 5 +++++ java-spanner-jdbc/.kokoro/nightly/samples.cfg | 21 ++++++++++++------- java-spanner-jdbc/.kokoro/presubmit/java8.cfg | 5 +++++ java-spanner-jdbc/synth.metadata | 16 +------------- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 284a0def7c2b..414656e37b7d 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -44,7 +44,6 @@ case ${JOB_TYPE} in test) mvn test -B -Dclirr.skip=true -Denforcer.skip=true RETURN_CODE=$? - bash ${KOKORO_GFILE_DIR}/codecov.sh ;; lint) mvn \ @@ -91,6 +90,11 @@ clirr) ;; esac +if [ "${REPORT_COVERAGE}" == "true" ] +then + bash ${KOKORO_GFILE_DIR}/codecov.sh +fi + # fix output location of logs bash .kokoro/coerce_logs.sh @@ -101,4 +105,4 @@ then fi echo "exiting with ${RETURN_CODE}" -exit ${RETURN_CODE} \ No newline at end of file +exit ${RETURN_CODE} diff --git a/java-spanner-jdbc/.kokoro/continuous/java8.cfg b/java-spanner-jdbc/.kokoro/continuous/java8.cfg index 3b017fc80f04..495cc7bacd63 100644 --- a/java-spanner-jdbc/.kokoro/continuous/java8.cfg +++ b/java-spanner-jdbc/.kokoro/continuous/java8.cfg @@ -5,3 +5,8 @@ env_vars: { key: "TRAMPOLINE_IMAGE" value: "gcr.io/cloud-devrel-kokoro-resources/java8" } + +env_vars: { + key: "REPORT_COVERAGE" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index 3b017fc80f04..8bf59c02edd6 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -5,3 +5,17 @@ env_vars: { key: "TRAMPOLINE_IMAGE" value: "gcr.io/cloud-devrel-kokoro-resources/java8" } + +env_vars: { + key: "ENABLE_BUILD_COP" + value: "true" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "java_it_service_account" + } + } +} diff --git a/java-spanner-jdbc/.kokoro/nightly/java8.cfg b/java-spanner-jdbc/.kokoro/nightly/java8.cfg index 3b017fc80f04..495cc7bacd63 100644 --- a/java-spanner-jdbc/.kokoro/nightly/java8.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/java8.cfg @@ -5,3 +5,8 @@ env_vars: { key: "TRAMPOLINE_IMAGE" value: "gcr.io/cloud-devrel-kokoro-resources/java8" } + +env_vars: { + key: "REPORT_COVERAGE" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/samples.cfg b/java-spanner-jdbc/.kokoro/nightly/samples.cfg index 9a9102490d54..b4b051cd016f 100644 --- a/java-spanner-jdbc/.kokoro/nightly/samples.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/samples.cfg @@ -2,23 +2,28 @@ # Configure the docker image for kokoro-trampoline. env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" } env_vars: { - key: "JOB_TYPE" - value: "samples" + key: "JOB_TYPE" + value: "samples" } env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" + key: "GCLOUD_PROJECT" + value: "gcloud-devel" } env_vars: { - key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + +env_vars: { + key: "ENABLE_BUILD_COP" + value: "true" } before_action { diff --git a/java-spanner-jdbc/.kokoro/presubmit/java8.cfg b/java-spanner-jdbc/.kokoro/presubmit/java8.cfg index 3b017fc80f04..495cc7bacd63 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/java8.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/java8.cfg @@ -5,3 +5,8 @@ env_vars: { key: "TRAMPOLINE_IMAGE" value: "gcr.io/cloud-devrel-kokoro-resources/java8" } + +env_vars: { + key: "REPORT_COVERAGE" + value: "true" +} diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index ce57fd2f8c26..796dab9779c8 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,20 +1,6 @@ { - "updateTime": "2020-02-22T10:16:10.861561Z", + "updateTime": "2020-02-24T23:15:28.206977Z", "sources": [ - { - "git": { - "name": ".", - "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "e6ec261803cbdfd2f82aa8d524de1cbed2fae44e" - } - }, - { - "git": { - "name": "synthtool", - "remote": "rpc://devrel/cloud/libraries/tools/autosynth", - "sha": "706a38c26db42299845396cdae55db635c38794a" - } - }, { "template": { "name": "java_library", From 9bfd50f57bbcd76dc4aacd9cb2e816d6cd3ed5a2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 27 Feb 2020 05:23:46 +0100 Subject: [PATCH 0107/1979] deps: update protobuf.version to v3.11.4 (#64) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3552c7b08075..56db8f8704fd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -66,7 +66,7 @@ 28.2-android 4.13 1.17.0 - 3.11.3 + 3.11.4 1.4.1 1.8.1 1.49.2 From 925e5d9bb6060721ea317858b5e438c079c6c442 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 27 Feb 2020 05:24:30 +0100 Subject: [PATCH 0108/1979] deps: update core dependencies to v1.27.2 (#71) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 56db8f8704fd..a9559130a9f2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 1.27.1 + 1.27.2 1.30.8 1.92.5 1.53.1 From f3c341aa92d3d5e8ce3dfc68465b55da6837a89a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 27 Feb 2020 21:35:32 +0100 Subject: [PATCH 0109/1979] deps: update core dependencies to v1.54.0 (#72) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a9559130a9f2..ae0613d648f1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ 1.27.2 1.30.8 1.92.5 - 1.53.1 + 1.54.0 1.34.2 28.2-android 4.13 From 7d50f07317754d3a44eb88d56228aebde21686a0 Mon Sep 17 00:00:00 2001 From: skuruppu Date: Thu, 5 Mar 2020 14:41:04 +1100 Subject: [PATCH 0110/1979] deps: update dependency com.google.api-client:google-api-client-bom to v1.30.9 (#74) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ae0613d648f1..9002c7e2d949 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -59,7 +59,7 @@ google-cloud-spanner-jdbc 1.27.2 - 1.30.8 + 1.30.9 1.92.5 1.54.0 1.34.2 From c50d6a98ef183f77a34a43f3cd66669024c5dab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 9 Mar 2020 16:21:28 +0100 Subject: [PATCH 0111/1979] =?UTF-8?q?fix:=20add=20missing=20netty-shaded?= =?UTF-8?q?=20lib=20for=20=C3=BCber-jar=20(#80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- java-spanner-jdbc/pom.xml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9002c7e2d949..6d3ce9547024 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -181,6 +181,11 @@ grpc-api ${grpc.version}
    + + io.grpc + grpc-netty-shaded + ${grpc.version} + com.google.api api-common @@ -286,12 +291,6 @@ ${junit.version} test - - io.grpc - grpc-netty-shaded - ${grpc.version} - test - com.google.api gax-grpc From 3496f75affcaa4904a721fa83c26f0271e175953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 9 Mar 2020 16:25:30 +0100 Subject: [PATCH 0112/1979] feat: add support for foreign keys (#78) Google Cloud Spanner now supports Foreign Key Constraints. These now also show up in the corresponding DatabaseMetaData methods. Fixes #77 --- .../DatabaseMetaData_GetCrossReferences.sql | 50 ++-- .../jdbc/DatabaseMetaData_GetExportedKeys.sql | 53 ++-- .../jdbc/DatabaseMetaData_GetImportedKeys.sql | 53 ++-- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 275 +++++++++++++++++- .../spanner/jdbc/it/CreateMusicTables.sql | 14 +- 5 files changed, 383 insertions(+), 62 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql index 175edc4e14bb..7d362ca58e87 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql @@ -14,21 +14,35 @@ * limitations under the License. */ -SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, - PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, - CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, CHILD.ORDINAL_POSITION AS KEY_SEQ, 3 AS UPDATE_RULE, - CASE WHEN TABLES.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 3 END AS DELETE_RULE, NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, - 7 AS DEFERRABILITY, TABLES.ON_DELETE_ACTION -FROM INFORMATION_SCHEMA.INDEX_COLUMNS PARENT -INNER JOIN INFORMATION_SCHEMA.INDEXES PARENT_INDEX ON PARENT.INDEX_NAME=PARENT_INDEX.INDEX_NAME AND PARENT.TABLE_NAME=PARENT_INDEX.TABLE_NAME AND PARENT.TABLE_SCHEMA=PARENT_INDEX.TABLE_SCHEMA AND PARENT.TABLE_CATALOG=PARENT_INDEX.TABLE_CATALOG AND PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' -INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS CHILD ON NOT PARENT.TABLE_NAME=CHILD.TABLE_NAME AND PARENT.COLUMN_NAME=CHILD.COLUMN_NAME -INNER JOIN INFORMATION_SCHEMA.INDEXES CHILD_INDEX ON CHILD.INDEX_NAME=CHILD_INDEX.INDEX_NAME AND CHILD.TABLE_NAME=CHILD_INDEX.TABLE_NAME AND CHILD.TABLE_SCHEMA=CHILD_INDEX.TABLE_SCHEMA AND CHILD.TABLE_CATALOG=CHILD_INDEX.TABLE_CATALOG AND CHILD_INDEX.INDEX_TYPE='PRIMARY_KEY' -INNER JOIN INFORMATION_SCHEMA.TABLES ON CHILD.TABLE_CATALOG=TABLES.TABLE_CATALOG AND CHILD.TABLE_SCHEMA=TABLES.TABLE_SCHEMA AND CHILD.TABLE_NAME=TABLES.TABLE_NAME AND PARENT.TABLE_NAME=TABLES.PARENT_TABLE_NAME -WHERE PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' AND CHILD.ORDINAL_POSITION IS NOT NULL -AND UPPER(PARENT.TABLE_CATALOG) LIKE ? -AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? -AND UPPER(PARENT.TABLE_NAME) LIKE ? -AND UPPER(CHILD.TABLE_CATALOG) LIKE ? -AND UPPER(CHILD.TABLE_SCHEMA) LIKE ? -AND UPPER(CHILD.TABLE_NAME) LIKE ? -ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, CHILD.ORDINAL_POSITION \ No newline at end of file +SELECT * +FROM ( + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, + PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, CHILD.ORDINAL_POSITION AS KEY_SEQ, 3 AS UPDATE_RULE, + CASE WHEN TABLES.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 3 END AS DELETE_RULE, NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, + 7 AS DEFERRABILITY + FROM INFORMATION_SCHEMA.INDEX_COLUMNS PARENT + INNER JOIN INFORMATION_SCHEMA.INDEXES PARENT_INDEX ON PARENT.INDEX_NAME=PARENT_INDEX.INDEX_NAME AND PARENT.TABLE_NAME=PARENT_INDEX.TABLE_NAME AND PARENT.TABLE_SCHEMA=PARENT_INDEX.TABLE_SCHEMA AND PARENT.TABLE_CATALOG=PARENT_INDEX.TABLE_CATALOG AND PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' + INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS CHILD ON NOT PARENT.TABLE_NAME=CHILD.TABLE_NAME AND PARENT.COLUMN_NAME=CHILD.COLUMN_NAME + INNER JOIN INFORMATION_SCHEMA.INDEXES CHILD_INDEX ON CHILD.INDEX_NAME=CHILD_INDEX.INDEX_NAME AND CHILD.TABLE_NAME=CHILD_INDEX.TABLE_NAME AND CHILD.TABLE_SCHEMA=CHILD_INDEX.TABLE_SCHEMA AND CHILD.TABLE_CATALOG=CHILD_INDEX.TABLE_CATALOG AND CHILD_INDEX.INDEX_TYPE='PRIMARY_KEY' + INNER JOIN INFORMATION_SCHEMA.TABLES ON CHILD.TABLE_CATALOG=TABLES.TABLE_CATALOG AND CHILD.TABLE_SCHEMA=TABLES.TABLE_SCHEMA AND CHILD.TABLE_NAME=TABLES.TABLE_NAME AND PARENT.TABLE_NAME=TABLES.PARENT_TABLE_NAME + WHERE PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' AND CHILD.ORDINAL_POSITION IS NOT NULL + + UNION ALL + + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, + PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, CHILD.ORDINAL_POSITION AS KEY_SEQ, 3 AS UPDATE_RULE, + 3 AS DELETE_RULE, CONSTRAINTS.CONSTRAINT_NAME AS FK_NAME, CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS PK_NAME, + 7 AS DEFERRABILITY + FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +) AS CROSS_REF +WHERE UPPER(PKTABLE_CAT) LIKE ? +AND UPPER(PKTABLE_SCHEM) LIKE ? +AND UPPER(PKTABLE_NAME) LIKE ? +AND UPPER(FKTABLE_CAT) LIKE ? +AND UPPER(FKTABLE_SCHEM) LIKE ? +AND UPPER(FKTABLE_NAME) LIKE ? +ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql index d83bf67daf23..631886d710ed 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql @@ -14,21 +14,38 @@ * limitations under the License. */ -SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, - PARENT.TABLE_NAME AS PKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS PKCOLUMN_NAME, - CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, - CHILD.TABLE_NAME AS FKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS FKCOLUMN_NAME, - PARENT_INDEX_COLUMNS.ORDINAL_POSITION AS KEY_SEQ, - 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict - CASE WHEN CHILD.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 1 END AS DELETE_RULE, -- 0 = cascade - NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, - 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable -FROM INFORMATION_SCHEMA.TABLES PARENT -INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME -INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON - PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME - AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' -WHERE UPPER(PARENT.TABLE_CATALOG) LIKE ? - AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? - AND UPPER(PARENT.TABLE_NAME) LIKE ? -ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, PARENT_INDEX_COLUMNS.ORDINAL_POSITION +SELECT * +FROM ( + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, + PARENT.TABLE_NAME AS PKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS PKCOLUMN_NAME, + CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS FKCOLUMN_NAME, + PARENT_INDEX_COLUMNS.ORDINAL_POSITION AS KEY_SEQ, + 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict + CASE WHEN CHILD.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 1 END AS DELETE_RULE, -- 0 = cascade + NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, + 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable + FROM INFORMATION_SCHEMA.TABLES PARENT + INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME + INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON + PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME + AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' + + UNION ALL + + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, + PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, + CHILD.ORDINAL_POSITION AS KEY_SEQ, + 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict + 1 AS DELETE_RULE, -- 1 = importedKeyRestrict + CONSTRAINTS.CONSTRAINT_NAME AS FK_NAME, CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS PK_NAME, + 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable + FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +) EXPORTED_KEYS +WHERE UPPER(PKTABLE_CAT) LIKE ? + AND UPPER(PKTABLE_SCHEM) LIKE ? + AND UPPER(PKTABLE_NAME) LIKE ? +ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql index 4e7dc7aa416e..50994a55b2a9 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql @@ -14,21 +14,38 @@ * limitations under the License. */ -SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, - PARENT.TABLE_NAME AS PKTABLE_NAME, COL.COLUMN_NAME AS PKCOLUMN_NAME, - CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, - CHILD.TABLE_NAME AS FKTABLE_NAME, COL.COLUMN_NAME FKCOLUMN_NAME, - COL.ORDINAL_POSITION AS KEY_SEQ, - 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict - CASE WHEN CHILD.ON_DELETE_ACTION = 'CASCADE' THEN 0 ELSE 1 END AS DELETE_RULE, -- 0 = cascade - NULL AS FK_NAME, INDEXES.INDEX_NAME AS PK_NAME, - 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable -FROM INFORMATION_SCHEMA.TABLES CHILD -INNER JOIN INFORMATION_SCHEMA.TABLES PARENT ON CHILD.TABLE_CATALOG=PARENT.TABLE_CATALOG AND CHILD.TABLE_SCHEMA=PARENT.TABLE_SCHEMA AND CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME -INNER JOIN INFORMATION_SCHEMA.INDEXES ON PARENT.TABLE_CATALOG=INDEXES.TABLE_CATALOG AND PARENT.TABLE_SCHEMA=INDEXES.TABLE_SCHEMA AND PARENT.TABLE_NAME=INDEXES.TABLE_NAME AND INDEXES.INDEX_TYPE='PRIMARY_KEY' -INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS COL ON INDEXES.TABLE_CATALOG=COL.TABLE_CATALOG AND INDEXES.TABLE_SCHEMA=COL.TABLE_SCHEMA AND INDEXES.TABLE_NAME=COL.TABLE_NAME AND INDEXES.INDEX_NAME=COL.INDEX_NAME -WHERE CHILD.PARENT_TABLE_NAME IS NOT NULL - AND UPPER(CHILD.TABLE_CATALOG) LIKE ? - AND UPPER(CHILD.TABLE_SCHEMA) LIKE ? - AND UPPER(CHILD.TABLE_NAME) LIKE ? -ORDER BY PARENT.TABLE_CATALOG, PARENT.TABLE_SCHEMA, PARENT.TABLE_NAME, COL.ORDINAL_POSITION \ No newline at end of file +SELECT * +FROM ( + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, + PARENT.TABLE_NAME AS PKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS PKCOLUMN_NAME, + CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS FKCOLUMN_NAME, + PARENT_INDEX_COLUMNS.ORDINAL_POSITION AS KEY_SEQ, + 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict + CASE WHEN CHILD.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 1 END AS DELETE_RULE, -- 0 = cascade + NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, + 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable + FROM INFORMATION_SCHEMA.TABLES PARENT + INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME + INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON + PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME + AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' + + UNION ALL + + SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, + PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, + CHILD.ORDINAL_POSITION AS KEY_SEQ, + 1 AS UPDATE_RULE, -- 1 = importedKeyRestrict + 1 AS DELETE_RULE, -- 1 = importedKeyRestrict + CONSTRAINTS.CONSTRAINT_NAME AS FK_NAME, CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS PK_NAME, + 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable + FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +) IMPORTED_KEYS +WHERE UPPER(FKTABLE_CAT) LIKE ? + AND UPPER(FKTABLE_SCHEM) LIKE ? + AND UPPER(FKTABLE_NAME) LIKE ? +ORDER BY PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME, KEY_SEQ diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index a43f83c48ef5..27d7a12f733d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; @@ -44,7 +45,9 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String SINGERS_TABLE = "Singers"; private static final String ALBUMS_TABLE = "Albums"; private static final String SONGS_TABLE = "Songs"; + private static final String CONCERTS_TABLE = "Concerts"; private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; + private static final String TABLE_WITH_REF = "TableWithRef"; @Override protected boolean doCreateMusicTables() { @@ -276,6 +279,109 @@ public void testGetCrossReferences() throws SQLException { rs.getShort("DEFERRABILITY"), is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); } + + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + SINGERS_TABLE, + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + CONCERTS_TABLE)) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Singers"))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Concerts"))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_Concerts_Singer"))); + assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + assertThat(rs.next(), is(false)); + } + + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + TABLE_WITH_ALL_COLS, + DEFAULT_CATALOG, + DEFAULT_SCHEMA, + TABLE_WITH_REF)) { + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColFloat64"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefFloat"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColString"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefString"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColDate"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefDate"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 3))); + assertThat( + rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat( + rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); + assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); + assertThat( + rs.getShort("DEFERRABILITY"), + is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(false)); + } // try getting self-references try (ResultSet rs = connection @@ -292,7 +398,7 @@ public void testGetCrossReferences() throws SQLException { // try getting all cross-references in the database try (ResultSet rs = connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 7; i++) { assertThat(rs.next(), is(true)); } assertThat(rs.next(), is(false)); @@ -334,6 +440,13 @@ private IndexInfo( 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"), + new IndexInfo( + "Concerts", + true, + "FOREIGN_KEY", + 1, + "SingerId", + "A"), // Index automatically added by Cloud Spanner for the referencing column. new IndexInfo("Singers", false, "PRIMARY_KEY", 1, "SingerId", "A"), new IndexInfo("Singers", true, "SingersByFirstLastName", 1, "FirstName", "A"), new IndexInfo("Singers", true, "SingersByFirstLastName", 2, "LastName", "A"), @@ -344,7 +457,20 @@ private IndexInfo( new IndexInfo("Songs", false, "SongsBySingerAlbumSongNameDesc", 2, "AlbumId", "A"), new IndexInfo("Songs", false, "SongsBySingerAlbumSongNameDesc", 3, "SongName", "D"), new IndexInfo("Songs", true, "SongsBySongName", 1, "SongName", "A"), - new IndexInfo("TableWithAllColumnTypes", false, "PRIMARY_KEY", 1, "ColInt64", "A")); + new IndexInfo( + "TableWithAllColumnTypes", + false, + "GENERATED", + 1, + "ColFloat64", + "A"), // Index automatically added by Cloud Spanner for the referencing foreign key. + new IndexInfo("TableWithAllColumnTypes", false, "GENERATED", 2, "ColString", "A"), + new IndexInfo("TableWithAllColumnTypes", false, "GENERATED", 3, "ColDate", "A"), + new IndexInfo("TableWithAllColumnTypes", false, "PRIMARY_KEY", 1, "ColInt64", "A"), + 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")); @Test public void testGetIndexInfo() throws SQLException { @@ -361,7 +487,10 @@ public void testGetIndexInfo() throws SQLException { assertThat(rs.getString("TABLE_NAME"), is(equalTo(index.tableName))); assertThat(rs.getBoolean("NON_UNIQUE"), is(index.nonUnique)); assertThat(rs.getString("INDEX_QUALIFIER"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("INDEX_NAME"), is(equalTo(index.indexName))); + // Foreign key index names are automatically generated. + if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { + assertThat(rs.getString("INDEX_NAME"), is(equalTo(index.indexName))); + } if (index.indexName.equals("PRIMARY_KEY")) { assertThat(rs.getShort("TYPE"), is(equalTo(DatabaseMetaData.tableIndexClustered))); } else { @@ -390,7 +519,7 @@ public void testGetExportedKeys() throws SQLException { connection .getMetaData() .getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertKeysSingersAlbums(rs); + assertExportedKeysSingers(rs); } try (ResultSet rs = connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { @@ -402,18 +531,92 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { try (Connection connection = createConnection()) { + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { + assertImportedKeysSingers(rs); + } try (ResultSet rs = connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertKeysSingersAlbums(rs); + assertImportedKeysAlbums(rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, CONCERTS_TABLE)) { + assertImportedKeysConcerts(rs); } try (ResultSet rs = connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SONGS_TABLE)) { assertKeysAlbumsSongs(rs); } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_REF)) { + assertImportedKeysTableWithRef(rs); + } } } - private void assertKeysSingersAlbums(ResultSet rs) throws SQLException { + private void assertImportedKeysSingers(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(false)); + } + + private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColFloat64"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefFloat"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); + assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColString"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefString"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); + assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColDate"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefDate"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 3))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); + assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(false)); + } + + private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertThat(rs.next(), is(true)); assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); @@ -429,6 +632,63 @@ private void assertKeysSingersAlbums(ResultSet rs) throws SQLException { assertThat(rs.getString("FK_NAME"), is(nullValue())); assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(false)); + } + + private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(CONCERTS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getString("FK_NAME"), is("Fk_Concerts_Singer")); + assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(false)); + } + + private void assertExportedKeysSingers(ResultSet rs) throws SQLException { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); + assertThat(rs.getString("FK_NAME"), is(nullValue())); + assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); + assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); + assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); + assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(CONCERTS_TABLE))); + assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); + assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); + assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); + assertThat(rs.getString("FK_NAME"), is("Fk_Concerts_Singer")); + assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); + assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); + assertThat(rs.next(), is(false)); } @@ -533,7 +793,8 @@ private Table(String name) { new Table("Concerts"), new Table("Singers"), new Table("Songs"), - new Table("TableWithAllColumnTypes")); + new Table("TableWithAllColumnTypes"), + new Table("TableWithRef")); @Test public void testGetTables() throws SQLException { diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 896b8b9cbf2e..5bbb90f6bdf1 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -58,7 +58,8 @@ CREATE TABLE Concerts ( ConcertDate DATE NOT NULL, BeginTime TIMESTAMP, EndTime TIMESTAMP, - TicketPrices ARRAY + TicketPrices ARRAY, + CONSTRAINT Fk_Concerts_Singer FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) ) PRIMARY KEY(VenueId, SingerId, ConcertDate); CREATE TABLE TableWithAllColumnTypes ( @@ -85,4 +86,15 @@ CREATE TABLE TableWithAllColumnTypes ( ) PRIMARY KEY (ColInt64) ; +CREATE TABLE TableWithRef ( + Id INT64 NOT NULL, + RefFloat FLOAT64 NOT NULL, + RefString STRING(100) NOT NULL, + RefDate DATE NOT NULL, + CONSTRAINT Fk_TableWithRef_TableWithAllColumnTypes + FOREIGN KEY (RefFloat, RefString, RefDate) + REFERENCES TableWithAllColumnTypes (ColFloat64, ColString, ColDate) +) PRIMARY KEY (Id) +; + RUN BATCH; \ No newline at end of file From 474a57c803e0108243429a5724e71a8cbea76786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 10 Mar 2020 06:25:24 +0100 Subject: [PATCH 0113/1979] fix: fix deprecation warnings in JDBC (test) files (#81) * fix: fix deprecation warnings in JDBC files * fix: fix typo in test case * fix: remove commented line of code --- .../jdbc/AbstractJdbcPreparedStatement.java | 1 + .../cloud/spanner/jdbc/JdbcResultSet.java | 4 + .../jdbc/JdbcAbortedTransactionTest.java | 103 +++++---- .../spanner/jdbc/JdbcConnectionTest.java | 129 ++++++------ .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 116 ++++++---- .../jdbc/JdbcPreparedStatementTest.java | 5 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 91 +++++--- .../cloud/spanner/jdbc/JdbcStatementTest.java | 198 ++++++++++-------- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 4 - .../it/ITJdbcReadWriteAutocommitTest.java | 4 - .../jdbc/it/ITJdbcSimpleStatementsTest.java | 57 +++-- 11 files changed, 392 insertions(+), 320 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index ef0c5af4b907..52ac32c9cfcd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -169,6 +169,7 @@ public void setAsciiStream(int parameterIndex, InputStream value, int length) } @Override + @Deprecated public void setUnicodeStream(int parameterIndex, InputStream value, int length) throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 00c6361ff47e..e9532554d678 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -215,6 +215,7 @@ public InputStream getAsciiStream(int columnIndex) throws SQLException { } @Override + @Deprecated public InputStream getUnicodeStream(int columnIndex) throws SQLException { checkClosedAndValidRow(); return getInputStream(getString(columnIndex), StandardCharsets.UTF_16LE); @@ -314,6 +315,7 @@ public InputStream getAsciiStream(String columnLabel) throws SQLException { } @Override + @Deprecated public InputStream getUnicodeStream(String columnLabel) throws SQLException { checkClosedAndValidRow(); return getInputStream(getString(columnLabel), StandardCharsets.UTF_16LE); @@ -406,12 +408,14 @@ public BigDecimal getBigDecimal(String columnLabel) throws SQLException { } @Override + @Deprecated public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { checkClosedAndValidRow(); return getBigDecimal(columnIndex, true, scale); } @Override + @Deprecated public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { checkClosedAndValidRow(); return getBigDecimal(spanner.getColumnIndex(columnLabel) + 1, true, scale); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java index 7b9c4d050390..681f60528144 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -16,11 +16,7 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.endsWith; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import com.google.cloud.Timestamp; @@ -53,9 +49,7 @@ import java.util.List; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; @@ -110,8 +104,6 @@ public void retryFinished( @Parameter(0) public boolean retryAbortsInternally; - @Rule public ExpectedException expected = ExpectedException.none(); - @Parameters(name = "retryAbortsInternally = {0}") public static Collection data() { List params = new ArrayList<>(); @@ -175,7 +167,7 @@ public void testAutocommitUpdateAborted() throws SQLException { try (java.sql.Connection connection = createConnection()) { mockSpanner.abortNextStatement(); int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - assertThat(updateCount, is(equalTo(UPDATE_COUNT))); + assertThat(updateCount).isEqualTo(UPDATE_COUNT); } } @@ -183,15 +175,17 @@ public void testAutocommitUpdateAborted() throws SQLException { public void testTransactionalUpdateAborted() throws SQLException { // Updates in transactional mode are automatically retried by default, but this can be switched // off. - if (!retryAbortsInternally) { - expected.expect(JdbcAbortedException.class); - } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); mockSpanner.abortNextStatement(); int updateCount = connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - assertThat(updateCount, is(equalTo(UPDATE_COUNT))); - assertThat(getRetryCount(connection), is(equalTo(1))); + if (!retryAbortsInternally) { + fail("missing expected exception"); + } + assertThat(updateCount).isEqualTo(UPDATE_COUNT); + assertThat(getRetryCount(connection)).isEqualTo(1); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } @@ -203,16 +197,13 @@ public void testAutocommitBatchUpdateAborted() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); int[] updateCounts = statement.executeBatch(); - assertThat(updateCounts, is(equalTo(new int[] {UPDATE_COUNT, UPDATE_COUNT}))); + assertThat(updateCounts).asList().containsExactly(UPDATE_COUNT, UPDATE_COUNT); } } } @Test public void testTransactionalBatchUpdateAborted() throws SQLException { - if (!retryAbortsInternally) { - expected.expect(JdbcAbortedException.class); - } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); mockSpanner.abortNextStatement(); @@ -220,8 +211,13 @@ public void testTransactionalBatchUpdateAborted() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); int[] updateCounts = statement.executeBatch(); - assertThat(updateCounts, is(equalTo(new int[] {UPDATE_COUNT, UPDATE_COUNT}))); - assertThat(getRetryCount(connection), is(equalTo(1))); + if (!retryAbortsInternally) { + fail("missing expected exception"); + } + assertThat(updateCounts).asList().containsExactly(UPDATE_COUNT, UPDATE_COUNT); + assertThat(getRetryCount(connection)).isEqualTo(1); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } } @@ -233,7 +229,7 @@ public void testAutocommitSelectAborted() throws SQLException { mockSpanner.abortNextStatement(); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { - assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs.getLong(1)).isEqualTo(1L); } } } @@ -241,30 +237,27 @@ public void testAutocommitSelectAborted() throws SQLException { @Test public void testTransactionalSelectAborted() throws SQLException { - if (!retryAbortsInternally) { - expected.expect(JdbcAbortedException.class); - } try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); mockSpanner.abortNextStatement(); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { - assertThat(rs.getLong(1), is(equalTo(1L))); + if (!retryAbortsInternally) { + fail("missing expected exception"); + } + assertThat(rs.getLong(1)).isEqualTo(1L); } } - assertThat(getRetryCount(connection), is(equalTo(1))); + assertThat(getRetryCount(connection)).isEqualTo(1); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } @Test public void testTransactionalUpdateWithConcurrentModificationsAborted() throws SQLException { - if (retryAbortsInternally) { - // As the transaction does a random select, the retry will always see different data than the - // original attempt. - expected.expect(JdbcAbortedDueToConcurrentModificationException.class); - } else { - expected.expect(JdbcAbortedException.class); - } + // As the transaction does a random select, the retry will always see different data than the + // original attempt. try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); // Set a random answer. @@ -281,14 +274,15 @@ public void testTransactionalUpdateWithConcurrentModificationsAborted() throws S // This will abort and start an internal retry. connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); fail("missing expected aborted exception"); + } catch (JdbcAbortedDueToConcurrentModificationException e) { + assertThat(retryAbortsInternally).isTrue(); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } @Test public void testTransactionalUpdateWithErrorOnOriginalAndRetry() throws SQLException { - if (!retryAbortsInternally) { - expected.expect(JdbcAbortedException.class); - } final String sql = "UPDATE SOMETHING SET OTHER=1"; mockSpanner.putStatementResult( StatementResult.exception( @@ -298,7 +292,7 @@ public void testTransactionalUpdateWithErrorOnOriginalAndRetry() throws SQLExcep connection.setAutoCommit(false); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { - assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs.getLong(1)).isEqualTo(1L); } } try { @@ -309,16 +303,16 @@ public void testTransactionalUpdateWithErrorOnOriginalAndRetry() throws SQLExcep } mockSpanner.abortNextStatement(); connection.commit(); + if (!retryAbortsInternally) { + fail("missing expected exception"); + } + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } @Test public void testTransactionalUpdateWithErrorOnRetryAndNotOnOriginal() throws SQLException { - if (retryAbortsInternally) { - expected.expect(JdbcAbortedDueToConcurrentModificationException.class); - } else { - expected.expect(JdbcAbortedException.class); - } final String sql = "UPDATE SOMETHING SET OTHER=1"; try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); @@ -335,20 +329,17 @@ public void testTransactionalUpdateWithErrorOnRetryAndNotOnOriginal() throws SQL connection.commit(); fail("missing expected aborted exception"); } catch (JdbcAbortedDueToConcurrentModificationException e) { - assertThat( - e.getDatabaseErrorDuringRetry().getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); - assertThat(e.getDatabaseErrorDuringRetry().getMessage(), endsWith("test")); - throw e; + assertThat(retryAbortsInternally).isTrue(); + assertThat(e.getDatabaseErrorDuringRetry().getErrorCode()) + .isEqualTo(ErrorCode.INVALID_ARGUMENT); + assertThat(e.getDatabaseErrorDuringRetry().getMessage()).endsWith("test"); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } @Test public void testTransactionalUpdateWithErrorOnOriginalAndNotOnRetry() throws SQLException { - if (retryAbortsInternally) { - expected.expect(JdbcAbortedDueToConcurrentModificationException.class); - } else { - expected.expect(JdbcAbortedException.class); - } final String sql = "UPDATE SOMETHING SET OTHER=1"; mockSpanner.putStatementResult( StatementResult.exception( @@ -358,7 +349,7 @@ public void testTransactionalUpdateWithErrorOnOriginalAndNotOnRetry() throws SQL connection.setAutoCommit(false); try (ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { while (rs.next()) { - assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs.getLong(1)).isEqualTo(1L); } } try { @@ -373,8 +364,10 @@ public void testTransactionalUpdateWithErrorOnOriginalAndNotOnRetry() throws SQL connection.commit(); fail("missing expected aborted exception"); } catch (JdbcAbortedDueToConcurrentModificationException e) { - assertThat(e.getDatabaseErrorDuringRetry(), is(nullValue())); - throw e; + assertThat(retryAbortsInternally).isTrue(); + assertThat(e.getDatabaseErrorDuringRetry()).isNull(); + } catch (JdbcAbortedException e) { + assertThat(retryAbortsInternally).isFalse(); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 3d9c77caf1a1..8d49440a5e55 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -16,11 +16,8 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -48,15 +45,12 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JdbcConnectionTest { - @Rule public final ExpectedException exception = ExpectedException.none(); private static final com.google.cloud.spanner.ResultSet SELECT1_RESULTSET = ResultSets.forRows( Type.struct(StructField.of("", Type.int64())), @@ -76,14 +70,14 @@ public void testAutoCommit() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); when(options.isAutocommit()).thenReturn(true); try (Connection connection = createConnection(options)) { - assertThat(connection.getAutoCommit(), is(true)); + assertThat(connection.getAutoCommit()).isTrue(); connection.setAutoCommit(false); - assertThat(connection.getAutoCommit(), is(false)); + assertThat(connection.getAutoCommit()).isFalse(); // execute a query that will start a transaction connection.createStatement().executeQuery(AbstractConnectionImplTest.SELECT); // setting autocommit will automatically commit the transaction connection.setAutoCommit(true); - assertThat(connection.getAutoCommit(), is(true)); + assertThat(connection.getAutoCommit()).isTrue(); } } @@ -93,14 +87,16 @@ public void testReadOnly() throws SQLException { when(options.isAutocommit()).thenReturn(true); when(options.isReadOnly()).thenReturn(true); try (Connection connection = createConnection(options)) { - assertThat(connection.isReadOnly(), is(true)); + assertThat(connection.isReadOnly()).isTrue(); connection.setReadOnly(false); - assertThat(connection.isReadOnly(), is(false)); + assertThat(connection.isReadOnly()).isFalse(); // start a transaction connection.createStatement().execute("begin transaction"); // setting readonly should no longer be allowed - exception.expect(JdbcExceptionMatcher.matchCode(Code.FAILED_PRECONDITION)); connection.setReadOnly(true); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(JdbcExceptionMatcher.matchCode(Code.FAILED_PRECONDITION).matches(e)).isTrue(); } } @@ -109,17 +105,17 @@ public void testCommit() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { // verify that there is no transaction started - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); // start a transaction connection.createStatement().execute(AbstractConnectionImplTest.SELECT); // verify that we did start a transaction - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(true)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isTrue(); // do a commit connection.commit(); // verify that there is no transaction started anymore - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); // verify that there is a commit timestamp - assertThat(connection.getSpannerConnection().getCommitTimestamp(), is(notNullValue())); + assertThat(connection.getSpannerConnection().getCommitTimestamp()).isNotNull(); } } @@ -128,20 +124,20 @@ public void testRollback() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { // verify that there is no transaction started - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); // start a transaction connection.createStatement().execute(AbstractConnectionImplTest.SELECT); // verify that we did start a transaction - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(true)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isTrue(); // do a rollback connection.rollback(); // verify that there is no transaction started anymore - assertThat(connection.getSpannerConnection().isTransactionStarted(), is(false)); + assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); // verify that there is no commit timestamp try (ResultSet rs = connection.createStatement().executeQuery("show variable commit_timestamp")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getTimestamp("COMMIT_TIMESTAMP"), is(nullValue())); + assertThat(rs.next()).isTrue(); + assertThat(rs.getTimestamp("COMMIT_TIMESTAMP")).isNull(); } } } @@ -310,18 +306,17 @@ private void testInvokeMethodOnClosedConnection(Method method, Object... args) valid = true; } } - assertThat( - "Method did not throw exception on closed connection: " + method.getName(), - valid, - is(true)); + assertWithMessage("Method did not throw exception on closed connection: " + method.getName()) + .that(valid) + .isTrue(); } @Test public void testTransactionIsolation() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { - assertThat( - connection.getTransactionIsolation(), is(equalTo(Connection.TRANSACTION_SERIALIZABLE))); + assertThat(connection.getTransactionIsolation()) + .isEqualTo(Connection.TRANSACTION_SERIALIZABLE); // assert that setting it to this value is ok. connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // assert that setting it to something else is not ok. @@ -347,7 +342,7 @@ public void testTransactionIsolation() throws SQLException { && ((JdbcSqlException) e).getCode() == Code.UNIMPLEMENTED); } } - assertThat(exception, is(true)); + assertThat(exception).isTrue(); } } } @@ -356,7 +351,7 @@ public void testTransactionIsolation() throws SQLException { public void testHoldability() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getHoldability(), is(equalTo(ResultSet.CLOSE_CURSORS_AT_COMMIT))); + assertThat(connection.getHoldability()).isEqualTo(ResultSet.CLOSE_CURSORS_AT_COMMIT); // assert that setting it to this value is ok. connection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); // assert that setting it to something else is not ok. @@ -376,7 +371,7 @@ public void testHoldability() throws SQLException { && ((JdbcSqlException) e).getCode() == Code.UNIMPLEMENTED); } } - assertThat(exception, is(true)); + assertThat(exception).isTrue(); } } } @@ -385,24 +380,24 @@ public void testHoldability() throws SQLException { public void testWarnings() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getWarnings(), is(nullValue())); + assertThat((Object) connection.getWarnings()).isNull(); // Push one warning and get it twice. connection.pushWarning(new SQLWarning("test")); - assertThat(connection.getWarnings().getMessage(), is(equalTo("test"))); - assertThat(connection.getWarnings().getMessage(), is(equalTo("test"))); + assertThat(connection.getWarnings().getMessage()).isEqualTo("test"); + assertThat(connection.getWarnings().getMessage()).isEqualTo("test"); // Clear warnings and push two warnings and get them both. connection.clearWarnings(); connection.pushWarning(new SQLWarning("test 1")); connection.pushWarning(new SQLWarning("test 2")); - assertThat(connection.getWarnings().getMessage(), is(equalTo("test 1"))); - assertThat(connection.getWarnings().getMessage(), is(equalTo("test 1"))); - assertThat(connection.getWarnings().getNextWarning().getMessage(), is(equalTo("test 2"))); + assertThat(connection.getWarnings().getMessage()).isEqualTo("test 1"); + assertThat(connection.getWarnings().getMessage()).isEqualTo("test 1"); + assertThat(connection.getWarnings().getNextWarning().getMessage()).isEqualTo("test 2"); // Clear warnings. connection.clearWarnings(); - assertThat(connection.getWarnings(), is(nullValue())); + assertThat((Object) connection.getWarnings()).isNull(); } } @@ -410,23 +405,21 @@ public void testWarnings() throws SQLException { public void testSetClientInfo() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getWarnings(), is(nullValue())); + assertThat((Object) connection.getWarnings()).isNull(); connection.setClientInfo("test", "foo"); - assertThat(connection.getWarnings(), is(notNullValue())); - assertThat( - connection.getWarnings().getMessage(), - is(equalTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED))); + assertThat((Object) connection.getWarnings()).isNotNull(); + assertThat(connection.getWarnings().getMessage()) + .isEqualTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED); connection.clearWarnings(); - assertThat(connection.getWarnings(), is(nullValue())); + assertThat((Object) connection.getWarnings()).isNull(); Properties props = new Properties(); props.setProperty("test", "foo"); connection.setClientInfo(props); - assertThat(connection.getWarnings(), is(notNullValue())); - assertThat( - connection.getWarnings().getMessage(), - is(equalTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED))); + assertThat((Object) connection.getWarnings()).isNotNull(); + assertThat(connection.getWarnings().getMessage()) + .isEqualTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED); } } @@ -442,13 +435,13 @@ public void testIsValid() throws SQLException { // Verify that an opened connection that returns a result set is valid. try (JdbcConnection connection = new JdbcConnection("url", options)) { when(spannerConnection.executeQuery(statement)).thenReturn(SELECT1_RESULTSET); - assertThat(connection.isValid(1), is(true)); + assertThat(connection.isValid(1)).isTrue(); try { // Invalid timeout value. connection.isValid(-1); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT); } // Now let the query return an error. isValid should now return false. @@ -456,7 +449,7 @@ public void testIsValid() throws SQLException { .thenThrow( SpannerExceptionFactory.newSpannerException( ErrorCode.ABORTED, "the current transaction has been aborted")); - assertThat(connection.isValid(1), is(false)); + assertThat(connection.isValid(1)).isFalse(); } } @@ -464,7 +457,7 @@ public void testIsValid() throws SQLException { public void testIsValidOnClosedConnection() throws SQLException { Connection connection = createConnection(mock(ConnectionOptions.class)); connection.close(); - assertThat(connection.isValid(1), is(false)); + assertThat(connection.isValid(1)).isFalse(); } @Test @@ -483,8 +476,8 @@ public void testCreateStatement() throws SQLException { { java.sql.Statement statement = connection.createStatement(resultSetType, resultSetConcurrency); - assertThat(statement.getResultSetType(), is(equalTo(resultSetType))); - assertThat(statement.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + assertThat(statement.getResultSetType()).isEqualTo(resultSetType); + assertThat(statement.getResultSetConcurrency()).isEqualTo(resultSetConcurrency); } else { assertCreateStatementFails(connection, resultSetType, resultSetConcurrency); } @@ -499,9 +492,9 @@ public void testCreateStatement() throws SQLException { java.sql.Statement statement = connection.createStatement( resultSetType, resultSetConcurrency, resultSetHoldability); - assertThat(statement.getResultSetType(), is(equalTo(resultSetType))); - assertThat(statement.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); - assertThat(statement.getResultSetHoldability(), is(equalTo(resultSetHoldability))); + assertThat(statement.getResultSetType()).isEqualTo(resultSetType); + assertThat(statement.getResultSetConcurrency()).isEqualTo(resultSetConcurrency); + assertThat(statement.getResultSetHoldability()).isEqualTo(resultSetHoldability); } else { assertCreateStatementFails( connection, resultSetType, resultSetConcurrency, resultSetHoldability); @@ -557,8 +550,8 @@ public void testPrepareStatement() throws SQLException { { PreparedStatement ps = connection.prepareStatement("SELECT 1", resultSetType, resultSetConcurrency); - assertThat(ps.getResultSetType(), is(equalTo(resultSetType))); - assertThat(ps.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); + assertThat(ps.getResultSetType()).isEqualTo(resultSetType); + assertThat(ps.getResultSetConcurrency()).isEqualTo(resultSetConcurrency); } else { assertPrepareStatementFails(connection, resultSetType, resultSetConcurrency); } @@ -573,9 +566,9 @@ public void testPrepareStatement() throws SQLException { PreparedStatement ps = connection.prepareStatement( "SELECT 1", resultSetType, resultSetConcurrency, resultSetHoldability); - assertThat(ps.getResultSetType(), is(equalTo(resultSetType))); - assertThat(ps.getResultSetConcurrency(), is(equalTo(resultSetConcurrency))); - assertThat(ps.getResultSetHoldability(), is(equalTo(resultSetHoldability))); + assertThat(ps.getResultSetType()).isEqualTo(resultSetType); + assertThat(ps.getResultSetConcurrency()).isEqualTo(resultSetConcurrency); + assertThat(ps.getResultSetHoldability()).isEqualTo(resultSetHoldability); } else { assertPrepareStatementFails( connection, resultSetType, resultSetConcurrency, resultSetHoldability); @@ -623,7 +616,7 @@ public void testPrepareStatementWithAutoGeneratedKeys() throws SQLException { PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.NO_GENERATED_KEYS); ResultSet rs = statement.getGeneratedKeys(); - assertThat(rs.next(), is(false)); + assertThat(rs.next()).isFalse(); try { statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS); fail("missing expected SQLFeatureNotSupportedException"); @@ -638,7 +631,7 @@ public void testCatalog() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); when(options.getDatabaseName()).thenReturn("test"); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getCatalog(), is(equalTo("test"))); + assertThat(connection.getCatalog()).isEqualTo("test"); // This should be allowed. connection.setCatalog(""); try { @@ -646,7 +639,7 @@ public void testCatalog() throws SQLException { connection.setCatalog("other"); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT); } } } @@ -654,7 +647,7 @@ public void testCatalog() throws SQLException { @Test public void testSchema() throws SQLException { try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { - assertThat(connection.getSchema(), is(equalTo(""))); + assertThat(connection.getSchema()).isEqualTo(""); // This should be allowed. connection.setSchema(""); try { @@ -662,7 +655,7 @@ public void testSchema() throws SQLException { connection.setSchema("other"); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertThat(e.getCode()).isEqualTo(Code.INVALID_ARGUMENT); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 06ea2a343afc..a902207b8ad0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -16,6 +16,9 @@ package com.google.cloud.spanner.jdbc; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; @@ -43,9 +46,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -84,7 +85,6 @@ public class JdbcGrpcErrorTest { private static Server server; private static InetSocketAddress address; - @Rule public ExpectedException expected = ExpectedException.none(); // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. private final Exception serverException = Status.FAILED_PRECONDITION.withDescription("test exception").asRuntimeException(); @@ -143,87 +143,100 @@ private Connection createConnection() throws SQLException { @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void autocommitBeginTransaction() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void autocommitBeginPDMLTransaction() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitBeginPDMLTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void transactionalBeginTransaction() throws SQLException { - expected.expect(testExceptionMatcher); + public void transactionalBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void readOnlyBeginTransaction() throws SQLException { - expected.expect(testExceptionMatcher); + public void readOnlyBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); connection.createStatement().executeQuery(SELECT1.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void autocommitExecuteSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitExecuteSql() { mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void autocommitPDMLExecuteSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitPDMLExecuteSql() { mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void transactionalExecuteSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void transactionalExecuteSql() { mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test public void autocommitExecuteBatchDml() throws SQLException { - expected.expect(testExceptionMatcher); mockSpanner.setExecuteBatchDmlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { @@ -231,13 +244,15 @@ public void autocommitExecuteBatchDml() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); statement.executeBatch(); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } } @Test public void transactionalExecuteBatchDml() throws SQLException { - expected.expect(testExceptionMatcher); mockSpanner.setExecuteBatchDmlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { @@ -246,40 +261,51 @@ public void transactionalExecuteBatchDml() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); statement.executeBatch(); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } } @Test - public void autocommitCommit() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitCommit() { mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void transactionalCommit() throws SQLException { - expected.expect(testExceptionMatcher); + public void transactionalCommit() { mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); connection.commit(); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void autocommitRollback() throws SQLException { + public void autocommitRollback() { // The JDBC driver should throw the exception of the SQL statement and ignore any errors from // the rollback() method. - expected.expect( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, Code.NOT_FOUND, "Unknown table name")); mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(INVALID_UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, Code.NOT_FOUND, "Unknown table name") + .matches(e)) + .isTrue(); } } @@ -296,74 +322,86 @@ public void transactionalRollback() throws SQLException { } @Test - public void autocommitExecuteStreamingSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitExecuteStreamingSql() { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeQuery(SELECT1.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void transactionalExecuteStreamingSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void transactionalExecuteStreamingSql() { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeQuery(SELECT1.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Test - public void readOnlyExecuteStreamingSql() throws SQLException { - expected.expect(testExceptionMatcher); + public void readOnlyExecuteStreamingSql() { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); connection.createStatement().executeQuery(SELECT1.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void autocommitCreateSession() throws SQLException { - expected.expect(testExceptionMatcher); + public void autocommitCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void transactionalCreateSession() throws SQLException { - expected.expect(testExceptionMatcher); + public void transactionalCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } @Ignore( "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test - public void readOnlyCreateSession() throws SQLException { - expected.expect(testExceptionMatcher); + public void readOnlyCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); connection.createStatement().executeQuery(SELECT1.getSql()); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(testExceptionMatcher.matches(e)).isTrue(); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index c72db1ec4108..9b829e54e07a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -50,16 +50,12 @@ import java.util.Calendar; import java.util.TimeZone; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JdbcPreparedStatementTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); - private String generateSqlWithParameters(int numberOfParams) { StringBuilder sql = new StringBuilder("INSERT INTO FOO ("); boolean first = true; @@ -100,6 +96,7 @@ private JdbcConnection createMockConnection(Connection spanner) throws SQLExcept return connection; } + @SuppressWarnings("deprecation") @Test public void testParameters() throws SQLException, MalformedURLException { final int numberOfParams = 48; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index d564ad0f2a10..44eefa97010f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -16,12 +16,14 @@ package com.google.cloud.spanner.jdbc; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertArrayEquals; 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.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import com.google.cloud.ByteArray; @@ -33,6 +35,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import io.grpc.Status.Code; import java.io.IOException; import java.io.InputStream; import java.io.Reader; @@ -50,9 +53,7 @@ import java.util.HashMap; import java.util.Map; import java.util.TimeZone; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -111,8 +112,6 @@ public class JdbcResultSetTest { private static final int URL_COLINDEX_NULL = 19; private static final int URL_COLINDEX_NOTNULL = 20; - @Rule public ExpectedException thrown = ExpectedException.none(); - private JdbcResultSet subject; static ResultSet getMockResultSet() { @@ -262,10 +261,19 @@ public void testGetURLIndex() throws SQLException, MalformedURLException { } @Test - public void testGetURLIndexInvalid() throws SQLException, MalformedURLException { - thrown.expect(JdbcSqlExceptionImpl.class); - thrown.expectMessage("Invalid URL"); - assertNotNull(subject.getURL(STRING_COLINDEX_NOTNULL)); + public void testGetURLIndexInvalid() throws SQLException { + try { + subject.getURL(STRING_COLINDEX_NOTNULL); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, + Code.INVALID_ARGUMENT, + "Invalid URL: " + subject.getString(STRING_COLINDEX_NOTNULL)) + .matches(e)) + .isTrue(); + } } @Test @@ -294,6 +302,7 @@ public void testGetDoubleIndex() throws SQLException { assertTrue(subject.wasNull()); } + @SuppressWarnings("deprecation") @Test public void testGetBigDecimalIndexAndScale() throws SQLException { assertNotNull(subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL, 2)); @@ -376,9 +385,18 @@ public void testGetURLLabel() throws SQLException { @Test public void testGetURLLabelInvalid() throws SQLException { - thrown.expect(JdbcSqlExceptionImpl.class); - thrown.expectMessage("Invalid URL"); - assertNotNull(subject.getURL(STRING_COL_NOT_NULL)); + try { + subject.getURL(STRING_COL_NOT_NULL); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, + Code.INVALID_ARGUMENT, + "Invalid URL: " + subject.getString(STRING_COL_NOT_NULL)) + .matches(e)) + .isTrue(); + } } @Test @@ -407,6 +425,7 @@ public void testGetDoubleLabel() throws SQLException { assertTrue(subject.wasNull()); } + @SuppressWarnings("deprecation") @Test public void testGetBigDecimalLabelAndScale() throws SQLException { assertNotNull(subject.getBigDecimal(DOUBLE_COL_NOT_NULL, 2)); @@ -839,6 +858,7 @@ public void testGetAsciiStreamIndex() throws SQLException, IOException { assertTrue(subject.wasNull()); } + @SuppressWarnings("deprecation") @Test public void testGetUnicodeStreamIndex() throws SQLException, IOException { assertNotNull(subject.getUnicodeStream(STRING_COLINDEX_NOTNULL)); @@ -861,7 +881,7 @@ public void testGetBinaryStreamIndex() throws SQLException, IOException { assertArrayEquals(BYTES_VALUE.toByteArray(), cbuf); assertEquals(3, len); assertFalse(subject.wasNull()); - assertNull(subject.getUnicodeStream(BYTES_COLINDEX_NULL)); + assertNull(subject.getBinaryStream(BYTES_COLINDEX_NULL)); assertTrue(subject.wasNull()); } @@ -878,6 +898,7 @@ public void testGetAsciiStreamLabel() throws SQLException, IOException { assertTrue(subject.wasNull()); } + @SuppressWarnings("deprecation") @Test public void testGetUnicodeStreamLabel() throws SQLException, IOException { assertNotNull(subject.getUnicodeStream(STRING_COL_NOT_NULL)); @@ -900,39 +921,59 @@ public void testGetBinaryStreamLabel() throws SQLException, IOException { assertArrayEquals(ByteArray.copyFrom("FOO").toByteArray(), cbuf); assertEquals(3, len); assertFalse(subject.wasNull()); - assertNull(subject.getUnicodeStream(BYTES_COL_NULL)); + assertNull(subject.getBinaryStream(BYTES_COL_NULL)); assertTrue(subject.wasNull()); } @Test - public void testGetBeforeNext() throws SQLException { + public void testGetBeforeNext() { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { - thrown.expect(SQLException.class); - thrown.expectMessage( - "FAILED_PRECONDITION: ResultSet is before first row. Call next() first."); rs.getBigDecimal(LONG_COLINDEX_NOTNULL); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, + Code.FAILED_PRECONDITION, + "ResultSet is before first row. Call next() first.") + .matches(e)) + .isTrue(); } } @Test - public void testGetAfterLast() throws SQLException { + public void testGetAfterLast() { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { while (rs.next()) { // do nothing } - thrown.expect(SQLException.class); - thrown.expectMessage( - "FAILED_PRECONDITION: ResultSet is after last row. There is no more data available."); rs.getBigDecimal(LONG_COLINDEX_NOTNULL); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, + Code.FAILED_PRECONDITION, + "ResultSet is after last row. There is no more data available.") + .matches(e)) + .isTrue(); } } @Test public void testFindIllegalColumnName() throws SQLException { - thrown.expect(SQLException.class); - thrown.expectMessage("INVALID_ARGUMENT: no column with label " + UNKNOWN_COLUMN + " found"); - int index = subject.findColumn(UNKNOWN_COLUMN); - assertEquals(0, index); + try { + subject.findColumn(UNKNOWN_COLUMN); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + SpannerJdbcExceptionMatcher.matchCodeAndMessage( + JdbcSqlExceptionImpl.class, + Code.INVALID_ARGUMENT, + "no column with label " + UNKNOWN_COLUMN + " found") + .matches(e)) + .isTrue(); + } } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 28bb25849ef1..12e0921e36c7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -16,11 +16,7 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -39,9 +35,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Matchers; @@ -50,14 +44,11 @@ @RunWith(JUnit4.class) public class JdbcStatementTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); private static final String SELECT = "SELECT 1"; private static final String UPDATE = "UPDATE FOO SET BAR=1 WHERE BAZ=2"; private static final String LARGE_UPDATE = "UPDATE FOO SET BAR=1 WHERE 1=1"; private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; - @Rule public final ExpectedException expected = ExpectedException.none(); - private JdbcStatement createStatement() { Connection spanner = mock(Connection.class); @@ -140,13 +131,13 @@ public void testQueryTimeout() throws SQLException { when(result.getResultSet()).thenReturn(mock(com.google.cloud.spanner.ResultSet.class)); when(spanner.execute(com.google.cloud.spanner.Statement.of(select))).thenReturn(result); try (Statement statement = new JdbcStatement(connection)) { - assertThat(statement.getQueryTimeout(), is(equalTo(0))); + assertThat(statement.getQueryTimeout()).isEqualTo(0); statement.setQueryTimeout(1); - assertThat(statement.getQueryTimeout(), is(equalTo(1))); + assertThat(statement.getQueryTimeout()).isEqualTo(1); statement.setQueryTimeout(99); - assertThat(statement.getQueryTimeout(), is(equalTo(99))); + assertThat(statement.getQueryTimeout()).isEqualTo(99); statement.setQueryTimeout(0); - assertThat(statement.getQueryTimeout(), is(equalTo(0))); + assertThat(statement.getQueryTimeout()).isEqualTo(0); } when(spanner.getStatementTimeout(TimeUnit.SECONDS)).thenReturn(1L); @@ -155,7 +146,7 @@ public void testQueryTimeout() throws SQLException { when(spanner.getStatementTimeout(TimeUnit.NANOSECONDS)).thenReturn(1000000000L); when(spanner.hasStatementTimeout()).thenReturn(true); try (Statement statement = new JdbcStatement(connection)) { - assertThat(statement.getQueryTimeout(), is(equalTo(0))); + assertThat(statement.getQueryTimeout()).isEqualTo(0); statement.execute(select); // statement has no timeout, so it should also not be set on the connection verify(spanner, never()).setStatementTimeout(1L, TimeUnit.SECONDS); @@ -175,12 +166,12 @@ public void testQueryTimeout() throws SQLException { public void testExecuteWithSelectStatement() throws SQLException { Statement statement = createStatement(); boolean res = statement.execute(SELECT); - assertThat(res, is(true)); - assertThat(statement.getUpdateCount(), is(equalTo(JdbcConstants.STATEMENT_RESULT_SET))); + assertThat(res).isTrue(); + assertThat(statement.getUpdateCount()).isEqualTo(JdbcConstants.STATEMENT_RESULT_SET); try (ResultSet rs = statement.getResultSet()) { - assertThat(rs, is(notNullValue())); - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs).isNotNull(); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); } } @@ -188,16 +179,16 @@ public void testExecuteWithSelectStatement() throws SQLException { public void testExecuteWithUpdateStatement() throws SQLException { Statement statement = createStatement(); boolean res = statement.execute(UPDATE); - assertThat(res, is(false)); - assertThat(statement.getResultSet(), is(nullValue())); - assertThat(statement.getUpdateCount(), is(equalTo(1))); + assertThat(res).isFalse(); + assertThat(statement.getResultSet()).isNull(); + assertThat(statement.getUpdateCount()).isEqualTo(1); try { - assertThat(statement.execute(LARGE_UPDATE), is(false)); - assertThat(statement.getResultSet(), is(nullValue())); + assertThat(statement.execute(LARGE_UPDATE)).isFalse(); + assertThat(statement.getResultSet()).isNull(); statement.getUpdateCount(); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.OUT_OF_RANGE))); + assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE); } } @@ -205,17 +196,17 @@ public void testExecuteWithUpdateStatement() throws SQLException { public void testExecuteWithDdlStatement() throws SQLException { Statement statement = createStatement(); boolean res = statement.execute(DDL); - assertThat(res, is(false)); - assertThat(statement.getResultSet(), is(nullValue())); - assertThat(statement.getUpdateCount(), is(equalTo(JdbcConstants.STATEMENT_NO_RESULT))); + assertThat(res).isFalse(); + assertThat(statement.getResultSet()).isNull(); + assertThat(statement.getUpdateCount()).isEqualTo(JdbcConstants.STATEMENT_NO_RESULT); } @Test public void testExecuteWithGeneratedKeys() throws SQLException { Statement statement = createStatement(); - assertThat(statement.execute(UPDATE, Statement.NO_GENERATED_KEYS), is(false)); + assertThat(statement.execute(UPDATE, Statement.NO_GENERATED_KEYS)).isFalse(); ResultSet keys = statement.getGeneratedKeys(); - assertThat(keys.next(), is(false)); + assertThat(keys.next()).isFalse(); try { statement.execute(UPDATE, Statement.RETURN_GENERATED_KEYS); fail("missing expected exception"); @@ -228,59 +219,79 @@ public void testExecuteWithGeneratedKeys() throws SQLException { public void testExecuteQuery() throws SQLException { Statement statement = createStatement(); try (ResultSet rs = statement.executeQuery(SELECT)) { - assertThat(rs, is(notNullValue())); - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs).isNotNull(); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); } } @Test - public void testExecuteQueryWithUpdateStatement() throws SQLException { + public void testExecuteQueryWithUpdateStatement() { Statement statement = createStatement(); - expected.expect(JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query")); - statement.executeQuery(UPDATE); + try { + statement.executeQuery(UPDATE); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query") + .matches(e)) + .isTrue(); + } } @Test - public void testExecuteQueryWithDdlStatement() throws SQLException { + public void testExecuteQueryWithDdlStatement() { Statement statement = createStatement(); - expected.expect(JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query")); - statement.executeQuery(DDL); + try { + statement.executeQuery(DDL); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query") + .matches(e)) + .isTrue(); + } } @Test public void testExecuteUpdate() throws SQLException { Statement statement = createStatement(); - assertThat(statement.executeUpdate(UPDATE), is(equalTo(1))); + assertThat(statement.executeUpdate(UPDATE)).isEqualTo(1); try { statement.executeUpdate(LARGE_UPDATE); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.OUT_OF_RANGE))); + assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE); } } @Test public void testExecuteUpdateWithSelectStatement() throws SQLException { Statement statement = createStatement(); - expected.expect( - JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, "The statement is not an update or DDL statement")); - statement.executeUpdate(SELECT); + try { + statement.executeUpdate(SELECT); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + JdbcExceptionMatcher.matchCodeAndMessage( + Code.INVALID_ARGUMENT, "The statement is not an update or DDL statement") + .matches(e)) + .isTrue(); + } } @Test public void testExecuteUpdateWithDdlStatement() throws SQLException { Statement statement = createStatement(); - assertThat(statement.executeUpdate(DDL), is(equalTo(0))); + assertThat(statement.executeUpdate(DDL)).isEqualTo(0); } @Test public void testExecuteUpdateWithGeneratedKeys() throws SQLException { Statement statement = createStatement(); - assertThat(statement.executeUpdate(UPDATE, Statement.NO_GENERATED_KEYS), is(equalTo(1))); + assertThat(statement.executeUpdate(UPDATE, Statement.NO_GENERATED_KEYS)).isEqualTo(1); ResultSet keys = statement.getGeneratedKeys(); - assertThat(keys.next(), is(false)); + assertThat(keys.next()).isFalse(); try { statement.executeUpdate(UPDATE, Statement.RETURN_GENERATED_KEYS); fail("missing expected exception"); @@ -292,36 +303,46 @@ public void testExecuteUpdateWithGeneratedKeys() throws SQLException { @Test public void testMoreResults() throws SQLException { Statement statement = createStatement(); - assertThat(statement.execute(SELECT), is(true)); + assertThat(statement.execute(SELECT)).isTrue(); ResultSet rs = statement.getResultSet(); - assertThat(statement.getMoreResults(), is(false)); - assertThat(statement.getResultSet(), is(nullValue())); - assertThat(rs.isClosed(), is(true)); + assertThat(statement.getMoreResults()).isFalse(); + assertThat(statement.getResultSet()).isNull(); + assertThat(rs.isClosed()).isTrue(); - assertThat(statement.execute(SELECT), is(true)); + assertThat(statement.execute(SELECT)).isTrue(); rs = statement.getResultSet(); - assertThat(statement.getMoreResults(Statement.KEEP_CURRENT_RESULT), is(false)); - assertThat(statement.getResultSet(), is(nullValue())); - assertThat(rs.isClosed(), is(false)); + assertThat(statement.getMoreResults(Statement.KEEP_CURRENT_RESULT)).isFalse(); + assertThat(statement.getResultSet()).isNull(); + assertThat(rs.isClosed()).isFalse(); } @Test - public void testNoBatchMixing() throws SQLException { - thrown.expect(SQLException.class); - thrown.expectMessage("Mixing DML and DDL statements in a batch is not allowed."); + public void testNoBatchMixing() { try (Statement statement = createStatement()) { statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'FOO')"); statement.addBatch("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)"); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat( + JdbcExceptionMatcher.matchCodeAndMessage( + Code.INVALID_ARGUMENT, + "Mixing DML and DDL statements in a batch is not allowed.") + .matches(e)) + .isTrue(); } } @Test - public void testNoBatchQuery() throws SQLException { - thrown.expect(SQLException.class); - thrown.expectMessage( - "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching."); + public void testNoBatchQuery() { try (Statement statement = createStatement()) { statement.addBatch("SELECT * FROM FOO"); + } catch (SQLException e) { + assertThat( + JdbcExceptionMatcher.matchCodeAndMessage( + Code.INVALID_ARGUMENT, + "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching.") + .matches(e)) + .isTrue(); } } @@ -333,7 +354,7 @@ public void testDmlBatch() throws SQLException { statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'TEST')"); statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (2, 'TEST')"); statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (3, 'TEST')"); - assertThat(statement.executeBatch(), is(equalTo(new int[] {1, 1, 1}))); + assertThat(statement.executeBatch()).asList().containsExactly(1, 1, 1); } } } @@ -342,12 +363,14 @@ public void testDmlBatch() throws SQLException { public void testConvertUpdateCounts() throws SQLException { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { int[] updateCounts = statement.convertUpdateCounts(new long[] {1L, 2L, 3L}); - assertThat(updateCounts, is(equalTo(new int[] {1, 2, 3}))); + assertThat(updateCounts).asList().containsExactly(1, 2, 3); updateCounts = statement.convertUpdateCounts(new long[] {0L, 0L, 0L}); - assertThat(updateCounts, is(equalTo(new int[] {0, 0, 0}))); + assertThat(updateCounts).asList().containsExactly(0, 0, 0); - expected.expect(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE)); statement.convertUpdateCounts(new long[] {1L, Integer.MAX_VALUE + 1L}); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE).matches(e)).isTrue(); } } @@ -356,35 +379,28 @@ public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { int[] updateCounts = new int[3]; statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 2L, 3L}, updateCounts); - assertThat( - updateCounts, - is( - equalTo( - new int[] { - Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO - }))); + assertThat(updateCounts) + .asList() + .containsExactly( + Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO); statement.convertUpdateCountsToSuccessNoInfo(new long[] {0L, 0L, 0L}, updateCounts); - assertThat( - updateCounts, - is( - equalTo( - new int[] { - Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED - }))); + assertThat(updateCounts) + .asList() + .containsExactly( + Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED); statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 0L, 2L}, updateCounts); - assertThat( - updateCounts, - is( - equalTo( - new int[] { - Statement.SUCCESS_NO_INFO, Statement.EXECUTE_FAILED, Statement.SUCCESS_NO_INFO - }))); - - expected.expect(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE)); + assertThat(updateCounts) + .asList() + .containsExactly( + Statement.SUCCESS_NO_INFO, Statement.EXECUTE_FAILED, Statement.SUCCESS_NO_INFO); + statement.convertUpdateCountsToSuccessNoInfo( new long[] {1L, Integer.MAX_VALUE + 1L}, updateCounts); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE).matches(e)).isTrue(); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 8e083f592ecb..061f2e8de995 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -29,10 +29,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -42,8 +40,6 @@ public class ITJdbcReadOnlyTest extends ITAbstractJdbcTest { private static final long TEST_ROWS_COUNT = 1000L; - @Rule public ExpectedException exception = ExpectedException.none(); - @Override protected void appendConnectionUri(StringBuilder url) { url.append(";readOnly=true"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index dba6764fc14f..fdc8bb890d03 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -27,10 +27,8 @@ import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import org.junit.FixMethodOrder; -import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.junit.runners.MethodSorters; @@ -40,8 +38,6 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcReadWriteAutocommitTest extends ITAbstractJdbcTest { - @Rule public ExpectedException exception = ExpectedException.none(); - @Override protected void appendConnectionUri(StringBuilder uri) { uri.append(";autocommit=true"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index a1130f2b6e95..15f25b919ed7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -16,9 +16,8 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -27,10 +26,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -38,15 +35,13 @@ @RunWith(JUnit4.class) @Category(IntegrationTest.class) public class ITJdbcSimpleStatementsTest extends ITAbstractJdbcTest { - @Rule public final ExpectedException expected = ExpectedException.none(); - @Test public void testSelect1() throws SQLException { try (Connection connection = createConnection()) { try (ResultSet rs = connection.createStatement().executeQuery("select 1")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(1))); - assertThat(rs.next(), is(false)); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(1)).isEqualTo(1); + assertThat(rs.next()).isFalse(); } } } @@ -56,9 +51,9 @@ public void testSelect1PreparedStatement() throws SQLException { try (Connection connection = createConnection()) { try (PreparedStatement ps = connection.prepareStatement("select 1")) { try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(1))); - assertThat(rs.next(), is(false)); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(1)).isEqualTo(1); + assertThat(rs.next()).isFalse(); } } } @@ -73,9 +68,9 @@ public void testPreparedStatement() throws SQLException { for (int i = 1; i <= 3; i++) { ps.setInt(1, i); try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(i))); - assertThat(rs.next(), is(false)); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(1)).isEqualTo(i); + assertThat(rs.next()).isFalse(); } } } @@ -92,17 +87,17 @@ public void testBatchedDdlStatements() throws SQLException { statement.addBatch( "CREATE TABLE FOO2 (ID INT64 NOT NULL, NAME STRING(100)) PRIMARY KEY (ID)"); int[] updateCounts = statement.executeBatch(); - assertThat( - updateCounts, - is(equalTo(new int[] {Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO}))); + assertThat(updateCounts) + .asList() + .containsExactly(Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO); } try (ResultSet rs = connection .createStatement() .executeQuery( "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='' AND TABLE_NAME LIKE 'FOO%'")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(2L))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(2L); } } // Execute a batch of DDL statements that contains a statement that will fail. @@ -121,35 +116,37 @@ public void testBatchedDdlStatements() throws SQLException { } catch (SQLException e) { gotExpectedException = true; } - assertThat(gotExpectedException, is(true)); + assertThat(gotExpectedException).isTrue(); // The table should have been created, the index should not. try (ResultSet rs = connection .createStatement() .executeQuery( "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='' AND TABLE_NAME LIKE 'FOO%'")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(3L))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(3L); } try (ResultSet rs = connection .createStatement() .executeQuery( "SELECT COUNT(*) FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_SCHEMA='' AND INDEX_NAME='IDX_FOO1_UNIQUE'")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(0L))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(0L); } } } @Test - public void testAddBatchWhenAlreadyInBatch() throws SQLException { - expected.expect(SQLException.class); - expected.expectMessage( - "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection."); + public void testAddBatchWhenAlreadyInBatch() { try (Connection connection = createConnection()) { connection.createStatement().execute("START BATCH DML"); connection.createStatement().addBatch("INSERT INTO Singers (SingerId) VALUES (-1)"); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(e.getMessage()) + .contains( + "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection."); } } } From fe18efa56ae34bc4528b8aa84942be411077e5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 13 Mar 2020 06:57:33 +0100 Subject: [PATCH 0114/1979] tests: unflake max staleness read tests (#86) --- .../com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java | 2 ++ .../google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java | 2 ++ .../com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 061f2e8de995..163f555e0fb1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -84,6 +84,8 @@ public void createTestTables() throws Exception { @Test public void testSqlScript() throws Exception { + // Wait 100ms to ensure that staleness tests in the script succeed. + Thread.sleep(100L); JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java index 51882c66e064..599a9cf6595d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java @@ -101,6 +101,8 @@ public void createTestTables() throws Exception { @Test public void testSqlScript() throws Exception { + // Wait 100ms to ensure that staleness tests in the script succeed. + Thread.sleep(100L); SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql index 8f8f6694481d..0dc0410757ae 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql @@ -109,9 +109,9 @@ SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; ---TimestampBound.ofExactStaleness(100, TimeUnit.MILLISECONDS), +--TimestampBound.ofExactStaleness(1, TimeUnit.MILLISECONDS), -SET READ_ONLY_STALENESS = 'EXACT_STALENESS 100ms'; +SET READ_ONLY_STALENESS = 'EXACT_STALENESS 1ms'; @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; From 14c15cb720e25ad1adb603afe52e9c5d89b883a3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 16 Mar 2020 16:12:21 +0100 Subject: [PATCH 0115/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.2.0 (#88) This PR contains the following updates: | Package | Update | Change | |---|---|---| | org.apache.maven.plugins:maven-javadoc-plugin | minor | `3.1.1` -> `3.2.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6d3ce9547024..a78b77df984e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -483,7 +483,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.2.0 html From b453e4e61eb592661f4d8f7815704b6e0eacae2a Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 16 Mar 2020 08:29:06 -0700 Subject: [PATCH 0116/1979] chore: update PR template (#87) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-03-14 02:16:59,517 synthtool > Executing /tmpfs/src/git/autosynth/working_repo/synth.py. .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md .github/ISSUE_TEMPLATE/support_request.md .github/PULL_REQUEST_TEMPLATE.md .github/release-please.yml .github/trusted-contribution.yml .kokoro/build.bat .kokoro/build.sh .kokoro/coerce_logs.sh .kokoro/common.cfg .kokoro/continuous/common.cfg .kokoro/continuous/dependencies.cfg .kokoro/continuous/integration.cfg .kokoro/continuous/java11.cfg .kokoro/continuous/java7.cfg .kokoro/continuous/java8-osx.cfg .kokoro/continuous/java8-win.cfg .kokoro/continuous/java8.cfg .kokoro/continuous/lint.cfg .kokoro/continuous/propose_release.cfg .kokoro/continuous/samples.cfg .kokoro/dependencies.sh .kokoro/linkage-monitor.sh .kokoro/nightly/common.cfg .kokoro/nightly/dependencies.cfg .kokoro/nightly/integration.cfg .kokoro/nightly/java11.cfg .kokoro/nightly/java7.cfg .kokoro/nightly/java8-osx.cfg .kokoro/nightly/java8-win.cfg .kokoro/nightly/java8.cfg .kokoro/nightly/lint.cfg .kokoro/nightly/samples.cfg .kokoro/presubmit/clirr.cfg .kokoro/presubmit/common.cfg .kokoro/presubmit/dependencies.cfg .kokoro/presubmit/integration.cfg .kokoro/presubmit/java11.cfg .kokoro/presubmit/java7.cfg .kokoro/presubmit/java8-osx.cfg .kokoro/presubmit/java8-win.cfg .kokoro/presubmit/java8.cfg .kokoro/presubmit/linkage-monitor.cfg .kokoro/presubmit/lint.cfg .kokoro/presubmit/samples.cfg .kokoro/release/bump_snapshot.cfg .kokoro/release/common.cfg .kokoro/release/common.sh .kokoro/release/drop.cfg .kokoro/release/drop.sh .kokoro/release/promote.cfg .kokoro/release/promote.sh .kokoro/release/publish_javadoc.cfg .kokoro/release/publish_javadoc.sh .kokoro/release/snapshot.cfg .kokoro/release/snapshot.sh .kokoro/release/stage.cfg .kokoro/release/stage.sh .kokoro/trampoline.sh CODE_OF_CONDUCT.md CONTRIBUTING.md LICENSE README.md codecov.yaml java.header license-checks.xml renovate.json 2020-03-14 02:16:59,709 synthtool > Wrote metadata to synth.metadata. ```
    --- java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md | 8 +++++++- java-spanner-jdbc/synth.metadata | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md index 0bd0ee0620f9..52845889399c 100644 --- a/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md +++ b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md @@ -1 +1,7 @@ -Fixes # (it's a good idea to open an issue first for context and/or discussion) \ No newline at end of file +Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: +- [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/java-spanner-jdbc/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea +- [ ] Ensure the tests and linter pass +- [ ] Code coverage does not decrease (if any source code was changed) +- [ ] Appropriate docs were updated (if necessary) + +Fixes # ☕️ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 796dab9779c8..699d0d71ba7c 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,5 +1,5 @@ { - "updateTime": "2020-02-24T23:15:28.206977Z", + "updateTime": "2020-03-14T09:16:59.709595Z", "sources": [ { "template": { From c421b781b034f917c3cba56aca431875d8c890c0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 16 Mar 2020 23:41:34 +0100 Subject: [PATCH 0117/1979] deps: update core dependencies (#73) --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a78b77df984e..4c17942bdfc7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,9 +58,9 @@ google-cloud-spanner-jdbc - 1.27.2 + 1.28.0 1.30.9 - 1.92.5 + 1.93.3 1.54.0 1.34.2 28.2-android From b6df23402d86ed0e5cd7dbba8d2b51af7fd8e7b6 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 17 Mar 2020 00:14:04 +0100 Subject: [PATCH 0118/1979] deps: update spanner.version to v1.51.0 (#75) This PR contains the following updates: | Package | Update | Change | |---|---|---| | com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 | minor | `1.49.2` -> `1.51.0` | | com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 | minor | `1.49.2` -> `1.51.0` | | com.google.api.grpc:grpc-google-cloud-spanner-v1 | minor | `1.49.2` -> `1.51.0` | | [com.google.cloud:google-cloud-spanner](https://togithub.com/googleapis/java-spanner) | minor | `1.49.2` -> `1.51.0` | | com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1 | minor | `1.49.2` -> `1.51.0` | | com.google.api.grpc:proto-google-cloud-spanner-v1 | minor | `1.49.2` -> `1.51.0` | --- ### Release Notes
    googleapis/java-spanner ### [`v1.51.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​1510httpswwwgithubcomgoogleapisjava-spannercomparev1500v1510-2020-03-13) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v1.50.0...v1.51.0) ##### Features - add backend query options ([#​90](https://www.github.com/googleapis/java-spanner/issues/90)) ([e96e172](https://www.github.com/googleapis/java-spanner/commit/e96e17246bee9691171b46857806d03d1f8e19b4)) - add QueryOptions proto ([#​84](https://www.github.com/googleapis/java-spanner/issues/84)) ([eb8fc37](https://www.github.com/googleapis/java-spanner/commit/eb8fc375bbd766f25966aa565e266ed972bbe818)) ##### Bug Fixes - never use credentials in combination with plain text ([#​98](https://www.github.com/googleapis/java-spanner/issues/98)) ([7eb8d49](https://www.github.com/googleapis/java-spanner/commit/7eb8d49cd6c35d7f757cb89009ad16be601b77c3)) ##### Dependencies - update dependency com.google.cloud:google-cloud-core-bom to v1.93.1 ([#​91](https://www.github.com/googleapis/java-spanner/issues/91)) ([29d8db8](https://www.github.com/googleapis/java-spanner/commit/29d8db8cfc9d12824b9264d0fb870049a58a9a03)) - update dependency io.opencensus:opencensus-api to v0.25.0 ([#​95](https://www.github.com/googleapis/java-spanner/issues/95)) ([57f5fd0](https://www.github.com/googleapis/java-spanner/commit/57f5fd0f3bee4b437f48b6a08ab3174f035c8cca)) ### [`v1.50.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​1510httpswwwgithubcomgoogleapisjava-spannercomparev1500v1510-2020-03-13) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v1.49.2...v1.50.0) ##### Features - add backend query options ([#​90](https://www.github.com/googleapis/java-spanner/issues/90)) ([e96e172](https://www.github.com/googleapis/java-spanner/commit/e96e17246bee9691171b46857806d03d1f8e19b4)) - add QueryOptions proto ([#​84](https://www.github.com/googleapis/java-spanner/issues/84)) ([eb8fc37](https://www.github.com/googleapis/java-spanner/commit/eb8fc375bbd766f25966aa565e266ed972bbe818)) ##### Bug Fixes - never use credentials in combination with plain text ([#​98](https://www.github.com/googleapis/java-spanner/issues/98)) ([7eb8d49](https://www.github.com/googleapis/java-spanner/commit/7eb8d49cd6c35d7f757cb89009ad16be601b77c3)) ##### Dependencies - update dependency com.google.cloud:google-cloud-core-bom to v1.93.1 ([#​91](https://www.github.com/googleapis/java-spanner/issues/91)) ([29d8db8](https://www.github.com/googleapis/java-spanner/commit/29d8db8cfc9d12824b9264d0fb870049a58a9a03)) - update dependency io.opencensus:opencensus-api to v0.25.0 ([#​95](https://www.github.com/googleapis/java-spanner/issues/95)) ([57f5fd0](https://www.github.com/googleapis/java-spanner/commit/57f5fd0f3bee4b437f48b6a08ab3174f035c8cca))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4c17942bdfc7..c78553f38975 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ 3.11.4 1.4.1 1.8.1 - 1.49.2 + 1.51.0 2.2 2.3.4 0.20.0 From ccc8e5ab15f5850f5ad98b7bdb5108736245d5c0 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 17 Mar 2020 16:12:40 -0700 Subject: [PATCH 0119/1979] samples: scaffold pom.xml files (#90) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-03-17 12:21:53,248 synthtool > Executing /tmpfs/src/git/autosynth/working_repo/synth.py. .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md .github/ISSUE_TEMPLATE/support_request.md .github/PULL_REQUEST_TEMPLATE.md .github/release-please.yml .github/trusted-contribution.yml .kokoro/build.bat .kokoro/build.sh .kokoro/coerce_logs.sh .kokoro/common.cfg .kokoro/continuous/common.cfg .kokoro/continuous/dependencies.cfg .kokoro/continuous/integration.cfg .kokoro/continuous/java11.cfg .kokoro/continuous/java7.cfg .kokoro/continuous/java8-osx.cfg .kokoro/continuous/java8-win.cfg .kokoro/continuous/java8.cfg .kokoro/continuous/lint.cfg .kokoro/continuous/propose_release.cfg .kokoro/continuous/samples.cfg .kokoro/dependencies.sh .kokoro/linkage-monitor.sh .kokoro/nightly/common.cfg .kokoro/nightly/dependencies.cfg .kokoro/nightly/integration.cfg .kokoro/nightly/java11.cfg .kokoro/nightly/java7.cfg .kokoro/nightly/java8-osx.cfg .kokoro/nightly/java8-win.cfg .kokoro/nightly/java8.cfg .kokoro/nightly/lint.cfg .kokoro/nightly/samples.cfg .kokoro/presubmit/clirr.cfg .kokoro/presubmit/common.cfg .kokoro/presubmit/dependencies.cfg .kokoro/presubmit/integration.cfg .kokoro/presubmit/java11.cfg .kokoro/presubmit/java7.cfg .kokoro/presubmit/java8-osx.cfg .kokoro/presubmit/java8-win.cfg .kokoro/presubmit/java8.cfg .kokoro/presubmit/linkage-monitor.cfg .kokoro/presubmit/lint.cfg .kokoro/presubmit/samples.cfg .kokoro/release/bump_snapshot.cfg .kokoro/release/common.cfg .kokoro/release/common.sh .kokoro/release/drop.cfg .kokoro/release/drop.sh .kokoro/release/promote.cfg .kokoro/release/promote.sh .kokoro/release/publish_javadoc.cfg .kokoro/release/publish_javadoc.sh .kokoro/release/snapshot.cfg .kokoro/release/snapshot.sh .kokoro/release/stage.cfg .kokoro/release/stage.sh .kokoro/trampoline.sh CODE_OF_CONDUCT.md CONTRIBUTING.md LICENSE README.md codecov.yaml java.header license-checks.xml renovate.json samples/install-without-bom/pom.xml samples/pom.xml samples/snapshot/pom.xml samples/snippets/pom.xml 2020-03-17 12:21:53,455 synthtool > Wrote metadata to synth.metadata. ```
    --- .../samples/install-without-bom/pom.xml | 84 +++++++++++++++++++ java-spanner-jdbc/samples/pom.xml | 56 +++++++++++++ java-spanner-jdbc/samples/snapshot/pom.xml | 83 ++++++++++++++++++ java-spanner-jdbc/samples/snippets/pom.xml | 60 +++++++++++++ java-spanner-jdbc/synth.metadata | 2 +- 5 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/samples/install-without-bom/pom.xml create mode 100644 java-spanner-jdbc/samples/pom.xml create mode 100644 java-spanner-jdbc/samples/snapshot/pom.xml create mode 100644 java-spanner-jdbc/samples/snippets/pom.xml diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml new file mode 100644 index 000000000000..952e5f2c6dca --- /dev/null +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + com.google.cloud + spanner-jdbc-install-without-bom + jar + Google Google Cloud Spanner JDBC Install Without Bom + https://github.com/googleapis/java-spanner-jdbc + + + + com.google.cloud.samples + shared-configuration + 1.0.12 + + + + 1.8 + 1.8 + UTF-8 + + + + + + + com.google.cloud + google-cloud-spanner-jdbc + + + + + + junit + junit + 4.13 + test + + + com.google.truth + truth + 1.0.1 + test + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.1.0 + + + add-snippets-source + + add-source + + + + ../snippets/src/main/java + + + + + add-snippets-tests + + add-test-source + + + + ../snippets/src/test/java + + + + + + + + diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml new file mode 100644 index 000000000000..48df32823613 --- /dev/null +++ b/java-spanner-jdbc/samples/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + com.google.cloud + google-cloud-spanner-jdbc-samples + 0.0.1-SNAPSHOT + pom + Google Google Cloud Spanner JDBC Samples Parent + https://github.com/googleapis/java-spanner-jdbc + + Java idiomatic client for Google Cloud Platform services. + + + + + com.google.cloud.samples + shared-configuration + 1.0.12 + + + + 1.8 + 1.8 + UTF-8 + + + + install-without-bom + snapshot + snippets + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + + true + + + + + diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml new file mode 100644 index 000000000000..a1b09607f2fb --- /dev/null +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + com.google.cloud + spanner-jdbc-snapshot + jar + Google Google Cloud Spanner JDBC Snapshot Samples + https://github.com/googleapis/java-spanner-jdbc + + + + com.google.cloud.samples + shared-configuration + 1.0.12 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + google-cloud-spanner-jdbc + + + + + junit + junit + 4.13 + test + + + com.google.truth + truth + 1.0.1 + test + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.1.0 + + + add-snippets-source + + add-source + + + + ../snippets/src/main/java + + + + + add-snippets-tests + + add-test-source + + + + ../snippets/src/test/java + + + + + + + + \ No newline at end of file diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml new file mode 100644 index 000000000000..013fcbeb3753 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + com.google.cloud + spanner-jdbc-snippets + jar + Google Google Cloud Spanner JDBC Snippets + https://github.com/googleapis/java-spanner-jdbc + + + + com.google.cloud.samples + shared-configuration + 1.0.12 + + + + 1.8 + 1.8 + UTF-8 + + + + + + + + com.google.cloud + libraries-bom + + pom + import + + + + + + + com.google.cloud + google-cloud-spanner-jdbc + + + + + junit + junit + 4.13 + test + + + com.google.truth + truth + 1.0.1 + test + + + diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 699d0d71ba7c..ee2cf171cdcd 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,5 +1,5 @@ { - "updateTime": "2020-03-14T09:16:59.709595Z", + "updateTime": "2020-03-17T19:21:53.454785Z", "sources": [ { "template": { From d7e8cc25d0b5993a615ee3b08bdab19da0486ecd Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Wed, 18 Mar 2020 09:22:04 -0700 Subject: [PATCH 0120/1979] samples: fix snippet closing tag (#91) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 952e5f2c6dca..6f6034983db1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -31,7 +31,7 @@ google-cloud-spanner-jdbc
    - + junit From 2f3b7c083689da6b39ccacbd42b739d53828d25f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2020 23:22:08 +0000 Subject: [PATCH 0121/1979] chore: release 1.14.0 (#82) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit :robot: I have created a release \*beep\* \*boop\* --- ## [1.14.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.13.0...v1.14.0) (2020-03-18) ### Features * add support for foreign keys ([#78](https://www.github.com/googleapis/java-spanner-jdbc/issues/78)) ([3496f75](https://www.github.com/googleapis/java-spanner-jdbc/commit/3496f75affcaa4904a721fa83c26f0271e175953)), closes [#77](https://www.github.com/googleapis/java-spanner-jdbc/issues/77) ### Bug Fixes * add missing netty-shaded lib for über-jar ([#80](https://www.github.com/googleapis/java-spanner-jdbc/issues/80)) ([c50d6a9](https://www.github.com/googleapis/java-spanner-jdbc/commit/c50d6a98ef183f77a34a43f3cd66669024c5dab7)) * fix deprecation warnings in JDBC (test) files ([#81](https://www.github.com/googleapis/java-spanner-jdbc/issues/81)) ([474a57c](https://www.github.com/googleapis/java-spanner-jdbc/commit/474a57c803e0108243429a5724e71a8cbea76786)) * include Spanner gRPC test dependencies ([#63](https://www.github.com/googleapis/java-spanner-jdbc/issues/63)) ([edadf0a](https://www.github.com/googleapis/java-spanner-jdbc/commit/edadf0a227744869a8ac8011e02c0b951ddb0bec)) ### Dependencies * update core dependencies ([dc573ff](https://www.github.com/googleapis/java-spanner-jdbc/commit/dc573ff711ed5dc636695e9a3355a0dbbf2ea12d)) * update core dependencies ([#40](https://www.github.com/googleapis/java-spanner-jdbc/issues/40)) ([00a8da4](https://www.github.com/googleapis/java-spanner-jdbc/commit/00a8da4364b95110181f5236fe4ba2d234a44911)) * update core dependencies ([#73](https://www.github.com/googleapis/java-spanner-jdbc/issues/73)) ([c421b78](https://www.github.com/googleapis/java-spanner-jdbc/commit/c421b781b034f917c3cba56aca431875d8c890c0)) * update core dependencies to v1.27.1 ([#61](https://www.github.com/googleapis/java-spanner-jdbc/issues/61)) ([19bd94b](https://www.github.com/googleapis/java-spanner-jdbc/commit/19bd94b8c17552ed8b4d8a2c591307e0b384bd36)) * update core dependencies to v1.27.2 ([#71](https://www.github.com/googleapis/java-spanner-jdbc/issues/71)) ([925e5d9](https://www.github.com/googleapis/java-spanner-jdbc/commit/925e5d9bb6060721ea317858b5e438c079c6c442)) * update core dependencies to v1.54.0 ([#72](https://www.github.com/googleapis/java-spanner-jdbc/issues/72)) ([f3c341a](https://www.github.com/googleapis/java-spanner-jdbc/commit/f3c341aa92d3d5e8ce3dfc68465b55da6837a89a)) * update core dependencies to v1.92.5 ([#53](https://www.github.com/googleapis/java-spanner-jdbc/issues/53)) ([469955f](https://www.github.com/googleapis/java-spanner-jdbc/commit/469955f6d41d0f5b7f2e6baf6b403b430a48900b)) * update core transport dependencies to v1.34.1 ([#43](https://www.github.com/googleapis/java-spanner-jdbc/issues/43)) ([d1b67a9](https://www.github.com/googleapis/java-spanner-jdbc/commit/d1b67a9da4257e5aefff1fb619b39c4a185ef8b0)) * update core transport dependencies to v1.34.2 ([#62](https://www.github.com/googleapis/java-spanner-jdbc/issues/62)) ([bf6f1f5](https://www.github.com/googleapis/java-spanner-jdbc/commit/bf6f1f506205cc04569e6802013da4adf1e9db06)) * update dependency com.google.api-client:google-api-client-bom to v1.30.8 ([#46](https://www.github.com/googleapis/java-spanner-jdbc/issues/46)) ([724eb41](https://www.github.com/googleapis/java-spanner-jdbc/commit/724eb41ac64c7582223ecaae4e455f3cba201dbf)) * update dependency com.google.api-client:google-api-client-bom to v1.30.9 ([#74](https://www.github.com/googleapis/java-spanner-jdbc/issues/74)) ([7d50f07](https://www.github.com/googleapis/java-spanner-jdbc/commit/7d50f07317754d3a44eb88d56228aebde21686a0)) * update dependency com.google.truth:truth to v1.0.1 ([#32](https://www.github.com/googleapis/java-spanner-jdbc/issues/32)) ([e9e4bbb](https://www.github.com/googleapis/java-spanner-jdbc/commit/e9e4bbb86ac15dad9bc0be8194c0ad22b2134fb3)) * update protobuf.version to v3.11.3 ([#48](https://www.github.com/googleapis/java-spanner-jdbc/issues/48)) ([4739191](https://www.github.com/googleapis/java-spanner-jdbc/commit/473919103476be4fada9ffeeb20aa52fd65e9bc5)) * update protobuf.version to v3.11.4 ([#64](https://www.github.com/googleapis/java-spanner-jdbc/issues/64)) ([9bfd50f](https://www.github.com/googleapis/java-spanner-jdbc/commit/9bfd50f57bbcd76dc4aacd9cb2e816d6cd3ed5a2)) * update spanner.version to v1.51.0 ([#75](https://www.github.com/googleapis/java-spanner-jdbc/issues/75)) ([b6df234](https://www.github.com/googleapis/java-spanner-jdbc/commit/b6df23402d86ed0e5cd7dbba8d2b51af7fd8e7b6)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 3fbddecd3657..d3d90e78552c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## [1.14.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.13.0...v1.14.0) (2020-03-18) + + +### Features + +* add support for foreign keys ([#78](https://www.github.com/googleapis/java-spanner-jdbc/issues/78)) ([9e770f2](https://www.github.com/googleapis/java-spanner-jdbc/commit/9e770f281c03a1e9c034e5ff3ddee44fa20a7b30)), closes [#77](https://www.github.com/googleapis/java-spanner-jdbc/issues/77) + + +### Bug Fixes + +* add missing netty-shaded lib for über-jar ([#80](https://www.github.com/googleapis/java-spanner-jdbc/issues/80)) ([3d6f356](https://www.github.com/googleapis/java-spanner-jdbc/commit/3d6f35669671194e6772fe327ce48f27e5bf4643)) +* fix deprecation warnings in JDBC (test) files ([#81](https://www.github.com/googleapis/java-spanner-jdbc/issues/81)) ([a5e031d](https://www.github.com/googleapis/java-spanner-jdbc/commit/a5e031d3183f8fe88a621500f235ca2b0242f50b)) +* include Spanner gRPC test dependencies ([#63](https://www.github.com/googleapis/java-spanner-jdbc/issues/63)) ([a34bfc0](https://www.github.com/googleapis/java-spanner-jdbc/commit/a34bfc0ff1c2ddeef077dbfae4c56bdd53febcb2)) + + +### Dependencies + +* update core dependencies ([1ae098e](https://www.github.com/googleapis/java-spanner-jdbc/commit/1ae098e924c2a488cfddd0a3aee9511274b7a515)) +* update core dependencies ([#40](https://www.github.com/googleapis/java-spanner-jdbc/issues/40)) ([18c3a1b](https://www.github.com/googleapis/java-spanner-jdbc/commit/18c3a1b069cb507a91d0320e64a8bf8ae8efe394)) +* update core dependencies ([#73](https://www.github.com/googleapis/java-spanner-jdbc/issues/73)) ([cfa1539](https://www.github.com/googleapis/java-spanner-jdbc/commit/cfa153997599c36f1243e87f1ea0760694657dfe)) +* update core dependencies to v1.27.1 ([#61](https://www.github.com/googleapis/java-spanner-jdbc/issues/61)) ([181991b](https://www.github.com/googleapis/java-spanner-jdbc/commit/181991bda1f66de707d27dad9658b9177626595a)) +* update core dependencies to v1.27.2 ([#71](https://www.github.com/googleapis/java-spanner-jdbc/issues/71)) ([12425fc](https://www.github.com/googleapis/java-spanner-jdbc/commit/12425fcb4382449e4a7a0edad4c812b7ce15aa71)) +* update core dependencies to v1.54.0 ([#72](https://www.github.com/googleapis/java-spanner-jdbc/issues/72)) ([5676021](https://www.github.com/googleapis/java-spanner-jdbc/commit/567602177e05fa198eaa011fbca05cfe4b72fb13)) +* update core dependencies to v1.92.5 ([#53](https://www.github.com/googleapis/java-spanner-jdbc/issues/53)) ([604ee2b](https://www.github.com/googleapis/java-spanner-jdbc/commit/604ee2b75204ad52eaf724c3fb71e8c13540af7c)) +* update core transport dependencies to v1.34.1 ([#43](https://www.github.com/googleapis/java-spanner-jdbc/issues/43)) ([2b6f04d](https://www.github.com/googleapis/java-spanner-jdbc/commit/2b6f04da3aeebac778fb664c4564fb8b58bf3be4)) +* update core transport dependencies to v1.34.2 ([#62](https://www.github.com/googleapis/java-spanner-jdbc/issues/62)) ([8739015](https://www.github.com/googleapis/java-spanner-jdbc/commit/8739015f62289adb92fd55b19a5bff8762da20a9)) +* update dependency com.google.api-client:google-api-client-bom to v1.30.8 ([#46](https://www.github.com/googleapis/java-spanner-jdbc/issues/46)) ([ef891b0](https://www.github.com/googleapis/java-spanner-jdbc/commit/ef891b000045d1f39f91b6a0ed3abaab19c5f05e)) +* update dependency com.google.api-client:google-api-client-bom to v1.30.9 ([#74](https://www.github.com/googleapis/java-spanner-jdbc/issues/74)) ([3b62299](https://www.github.com/googleapis/java-spanner-jdbc/commit/3b622999b9f9645a6086e5efd3206f4d7b0806bc)) +* update dependency com.google.truth:truth to v1.0.1 ([#32](https://www.github.com/googleapis/java-spanner-jdbc/issues/32)) ([5205863](https://www.github.com/googleapis/java-spanner-jdbc/commit/52058636e10951e883523204f0f161db8a972d62)) +* update protobuf.version to v3.11.3 ([#48](https://www.github.com/googleapis/java-spanner-jdbc/issues/48)) ([0779fcb](https://www.github.com/googleapis/java-spanner-jdbc/commit/0779fcb0bfe935c3c302fa8442f733c7e3629761)) +* update protobuf.version to v3.11.4 ([#64](https://www.github.com/googleapis/java-spanner-jdbc/issues/64)) ([f485cff](https://www.github.com/googleapis/java-spanner-jdbc/commit/f485cfffa0de27ce35f5d16c689c31c6ea22138e)) +* update spanner.version to v1.51.0 ([#75](https://www.github.com/googleapis/java-spanner-jdbc/issues/75)) ([4fff168](https://www.github.com/googleapis/java-spanner-jdbc/commit/4fff168eae61fb55933cf3afd67f24ca65dfde54)) + ## [1.13.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/1.12.0...v1.13.0) (2020-01-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index db50ef106a7c..4a14e5b15545 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.13.0 + 1.14.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.13.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.14.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.13.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.14.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c78553f38975..a57e652a4de2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.13.1-SNAPSHOT + 1.14.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 72f0ebd53b0a..072804d1d1a3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.13.0:1.13.1-SNAPSHOT +google-cloud-spanner-jdbc:1.14.0:1.14.0 From 39e06e4ad252f0e13e53ca97d878756355c8b00c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2020 18:36:14 +0000 Subject: [PATCH 0122/1979] chore: release 1.14.1-SNAPSHOT (#93) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a57e652a4de2..2691043790de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.14.0 + 1.14.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 072804d1d1a3..ce565c7b403c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.14.0:1.14.0 +google-cloud-spanner-jdbc:1.14.0:1.14.1-SNAPSHOT From eefc67761c7889ab3edd86c3db3940b880f1ecf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 23 Mar 2020 20:04:19 +0100 Subject: [PATCH 0123/1979] feat: add support for QueryOptions (#76) * feat: add support for QueryOptions * fix: review comments * deps: temporarily update because of build and test errors * deps: update to released versions * fix: use grpc 1.27.2 * fix: fix invalid query hint in IT Co-authored-by: skuruppu --- java-spanner-jdbc/pom.xml | 2 +- .../ClientSideStatementValueConverters.java | 14 + .../google/cloud/spanner/jdbc/Connection.java | 23 + .../cloud/spanner/jdbc/ConnectionImpl.java | 23 +- .../cloud/spanner/jdbc/ConnectionOptions.java | 23 +- .../jdbc/ConnectionStatementExecutor.java | 4 + .../jdbc/ConnectionStatementExecutorImpl.java | 14 + .../google/cloud/spanner/jdbc/JdbcDriver.java | 1 + .../cloud/spanner/jdbc/StatementParser.java | 63 +- .../cloud/spanner/jdbc/StatementResult.java | 2 + .../spanner/jdbc/ClientSideStatements.json | 22 + .../cloud/spanner/jdbc/AbortedTest.java | 116 +- .../jdbc/AbstractConnectionImplTest.java | 45 + .../spanner/jdbc/AbstractMockServerTest.java | 186 +++ .../spanner/jdbc/ConnectionImplTest.java | 144 ++ .../jdbc/ConnectionStatementExecutorTest.java | 16 + ...nnectionStatementWithNoParametersTest.java | 12 + ...nnectionStatementWithOneParameterTest.java | 15 + .../cloud/spanner/jdbc/ConnectionTest.java | 98 ++ .../spanner/jdbc/JdbcQueryOptionsTest.java | 215 +++ .../spanner/jdbc/JdbcTypeConverterTest.java | 2 + .../jdbc/it/ITJdbcQueryOptionsTest.java | 214 +++ .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 9 + .../spanner/jdbc/ClientSideStatementsTest.sql | 991 ++++++++++++ .../ConnectionImplGeneratedSqlScriptTest.sql | 1392 +++++++++++++++-- .../jdbc/ITSqlScriptTest_TestQueryOptions.sql | 51 + 26 files changed, 3463 insertions(+), 234 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestQueryOptions.sql diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2691043790de..b850ccf1e7b1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 1.28.0 + 1.27.2 1.30.9 1.93.3 1.54.0 diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java index ddeb394268f7..92368fecafa9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java @@ -213,6 +213,20 @@ public AutocommitDmlMode convert(String value) { } } + static class StringValueConverter implements ClientSideStatementValueConverter { + public StringValueConverter(String allowedValues) {} + + @Override + public Class getParameterClass() { + return String.class; + } + + @Override + public String convert(String value) { + return value; + } + } + /** Converter for converting string values to {@link TransactionMode} values. */ static class TransactionModeConverter implements ClientSideStatementValueConverter { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java index 0ae8ed5cd864..c3b32f8e6b26 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java @@ -78,6 +78,11 @@ *
  • * SET READ_ONLY_STALENESS='STRONG' | 'MIN_READ_TIMESTAMP <timestamp>' | 'READ_TIMESTAMP <timestamp>' | 'MAX_STALENESS <int64>s|ms|mus|ns' | 'EXACT_STALENESS (<int64>s|ms|mus|ns)' * : Sets the value of READ_ONLY_STALENESS for this connection. + *
  • SHOW OPTIMIZER_VERSION: Returns the current value of + * OPTIMIZER_VERSION of this connection as a {@link ResultSet} + *
  • + * SET OPTIMIZER_VERSION='<version>' | 'LATEST' + * : Sets the value of OPTIMIZER_VERSION for this connection. *
  • BEGIN [TRANSACTION]: Begins a new transaction. This statement is optional when * the connection is not in autocommit mode, as a new transaction will automatically be * started when a query or update statement is issued. In autocommit mode, this statement will @@ -384,6 +389,24 @@ interface Connection extends AutoCloseable { */ TimestampBound getReadOnlyStaleness(); + /** + * Sets the query optimizer version to use for this connection. + * + * @param optimizerVersion The query optimizer version to use. Must be a valid optimizer version + * number, the string LATEST or an empty string. The empty string will instruct + * the connection to use the optimizer version that is defined in the environment variable + * SPANNER_OPTIMIZER_VERSION. If no value is specified in the environment + * variable, the default query optimizer of Cloud Spanner is used. + */ + void setOptimizerVersion(String optimizerVersion); + + /** + * Gets the current query optimizer version of this connection. + * + * @return The query optimizer version that is currently used by this connection. + */ + String getOptimizerVersion(); + /** * Commits the current transaction of this connection. All mutations that have been buffered * during the current transaction will be written to the database. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java index 8490dfcd5f90..2a83fca42bbf 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java @@ -35,6 +35,7 @@ import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -192,6 +193,7 @@ static UnitOfWorkType of(TransactionMode transactionMode) { private final List transactionRetryListeners = new ArrayList<>(); private AutocommitDmlMode autocommitDmlMode = AutocommitDmlMode.TRANSACTIONAL; private TimestampBound readOnlyStaleness = TimestampBound.strong(); + private QueryOptions queryOptions = QueryOptions.getDefaultInstance(); /** Create a connection and register it in the SpannerPool. */ ConnectionImpl(ConnectionOptions options) { @@ -204,6 +206,7 @@ static UnitOfWorkType of(TransactionMode transactionMode) { this.retryAbortsInternally = options.isRetryAbortsInternally(); this.readOnly = options.isReadOnly(); this.autocommit = options.isAutocommit(); + this.queryOptions = this.queryOptions.toBuilder().mergeFrom(options.getQueryOptions()).build(); this.ddlClient = createDdlClient(); setDefaultTransactionOptions(); } @@ -389,6 +392,19 @@ public TimestampBound getReadOnlyStaleness() { return this.readOnlyStaleness; } + @Override + public void setOptimizerVersion(String optimizerVersion) { + Preconditions.checkNotNull(optimizerVersion); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + this.queryOptions = queryOptions.toBuilder().setOptimizerVersion(optimizerVersion).build(); + } + + @Override + public String getOptimizerVersion() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + return this.queryOptions.getOptimizerVersion(); + } + @Override public void setStatementTimeout(long timeout, TimeUnit unit) { Preconditions.checkArgument(timeout > 0L, "Zero or negative timeout values are not allowed"); @@ -639,7 +655,7 @@ private void endCurrentTransaction(EndTransactionMethod endTransactionMethod) { public StatementResult execute(Statement statement) { Preconditions.checkNotNull(statement); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(statement); + ParsedStatement parsedStatement = parser.parse(statement, this.queryOptions); switch (parsedStatement.getType()) { case CLIENT_SIDE: return parsedStatement @@ -680,7 +696,7 @@ private ResultSet parseAndExecuteQuery( Preconditions.checkNotNull(query); Preconditions.checkNotNull(analyzeMode); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(query); + ParsedStatement parsedStatement = parser.parse(query, this.queryOptions); if (parsedStatement.isQuery()) { switch (parsedStatement.getType()) { case CLIENT_SIDE: @@ -809,7 +825,8 @@ private long[] internalExecuteBatchUpdate(final List updates) { * Returns the current {@link UnitOfWork} of this connection, or creates a new one based on the * current transaction settings of the connection and returns that. */ - private UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { + @VisibleForTesting + UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { if (this.currentUnitOfWork == null || !this.currentUnitOfWork.isActive()) { this.currentUnitOfWork = createNewUnitOfWork(); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java index f2e4358d6c3d..4ec727cd9a76 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java @@ -31,6 +31,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -144,6 +145,7 @@ public String[] getValidValues() { private static final String DEFAULT_OAUTH_TOKEN = null; private static final String DEFAULT_NUM_CHANNELS = null; private static final String DEFAULT_USER_AGENT = null; + private static final String DEFAULT_OPTIMIZER_VERSION = ""; private static final String PLAIN_TEXT_PROTOCOL = "http:"; private static final String HOST_PROTOCOL = "https:"; @@ -166,6 +168,8 @@ public String[] getValidValues() { public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels"; /** Custom user agent string is only for other Google libraries. */ private static final String USER_AGENT_PROPERTY_NAME = "userAgent"; + /** Query optimizer version to use for a connection. */ + private static final String OPTIMIZER_VERSION_PROPERTY_NAME = "optimizerVersion"; /** All valid connection properties. */ public static final Set VALID_PROPERTIES = @@ -183,7 +187,8 @@ public String[] getValidValues() { ConnectionProperty.createStringProperty(NUM_CHANNELS_PROPERTY_NAME, ""), ConnectionProperty.createBooleanProperty( USE_PLAIN_TEXT_PROPERTY_NAME, "", DEFAULT_USE_PLAIN_TEXT), - ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, "")))); + ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, ""), + ConnectionProperty.createStringProperty(OPTIMIZER_VERSION_PROPERTY_NAME, "")))); private static final Set INTERNAL_PROPERTIES = Collections.unmodifiableSet( @@ -281,6 +286,7 @@ private boolean isValidUri(String uri) { * false. *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the * connection. Default is true. + *
  • optimizerVersion (string): Sets the query optimizer version to use for the connection. * * * @param uri The URI of the Spanner database to connect to. @@ -373,6 +379,7 @@ public static Builder newBuilder() { private final Credentials credentials; private final Integer numChannels; private final String userAgent; + private final QueryOptions queryOptions; private final boolean autocommit; private final boolean readOnly; @@ -397,6 +404,9 @@ private ConnectionOptions(Builder builder) { this.usePlainText = parseUsePlainText(this.uri); this.userAgent = parseUserAgent(this.uri); + QueryOptions.Builder queryOptionsBuilder = QueryOptions.newBuilder(); + queryOptionsBuilder.setOptimizerVersion(parseOptimizerVersion(this.uri)); + this.queryOptions = queryOptionsBuilder.build(); this.host = matcher.group(Builder.HOST_GROUP) == null @@ -501,6 +511,12 @@ static String parseUserAgent(String uri) { return value != null ? value : DEFAULT_USER_AGENT; } + @VisibleForTesting + static String parseOptimizerVersion(String uri) { + String value = parseUriProperty(uri, OPTIMIZER_VERSION_PROPERTY_NAME); + return value != null ? value : DEFAULT_OPTIMIZER_VERSION; + } + @VisibleForTesting static String parseUriProperty(String uri, String property) { Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); @@ -633,6 +649,11 @@ String getUserAgent() { return userAgent; } + /** The {@link QueryOptions} to use for the connection. */ + QueryOptions getQueryOptions() { + return queryOptions; + } + /** Interceptors that should be executed after each statement */ List getStatementExecutionInterceptors() { return statementExecutionInterceptors; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java index 4e79f25455a6..4de1f3f0cf43 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java @@ -60,6 +60,10 @@ interface ConnectionStatementExecutor { StatementResult statementShowReadOnlyStaleness(); + StatementResult statementSetOptimizerVersion(String optimizerVersion); + + StatementResult statementShowOptimizerVersion(); + StatementResult statementBeginTransaction(); StatementResult statementCommit(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java index 7f7a5cf3ae74..c8aa40d77a34 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java @@ -23,6 +23,7 @@ import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.RUN_BATCH; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_OPTIMIZER_VERSION; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READONLY; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READ_ONLY_STALENESS; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_RETRY_ABORTS_INTERNALLY; @@ -31,6 +32,7 @@ import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT_DML_MODE; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_COMMIT_TIMESTAMP; +import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_VERSION; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READONLY; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_ONLY_STALENESS; import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_TIMESTAMP; @@ -183,6 +185,18 @@ public StatementResult statementShowReadOnlyStaleness() { SHOW_READ_ONLY_STALENESS); } + @Override + public StatementResult statementSetOptimizerVersion(String optimizerVersion) { + getConnection().setOptimizerVersion(optimizerVersion); + return noResult(SET_OPTIMIZER_VERSION); + } + + @Override + public StatementResult statementShowOptimizerVersion() { + return resultSet( + "OPTIMIZER_VERSION", getConnection().getOptimizerVersion(), SHOW_OPTIMIZER_VERSION); + } + @Override public StatementResult statementBeginTransaction() { getConnection().beginTransaction(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index c43f9797ecfe..229c0a6fb847 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -86,6 +86,7 @@ * connection. Default is true. @see {@link * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} * for more information. + *
  • optimizerVersion (string): The query optimizer version to use for the connection. The value must be either a valid version number or LATEST. If no value is specified, the query optimizer version specified in the environment variable SPANNER_OPTIMIZER_VERSION will be used. If no query optimizer version is specified in the connection URL or in the environment variable, the default query optimizer version of Cloud Spanner will be used. * */ public class JdbcDriver implements Driver { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java index e43a0974abea..e3e998a275f7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java @@ -20,10 +20,13 @@ import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; +import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.util.Collections; +import java.util.Objects; import java.util.Set; /** @@ -66,8 +69,10 @@ private static ParsedStatement ddl(Statement statement, String sqlWithoutComment return new ParsedStatement(StatementType.DDL, statement, sqlWithoutComments); } - private static ParsedStatement query(Statement statement, String sqlWithoutComments) { - return new ParsedStatement(StatementType.QUERY, statement, sqlWithoutComments); + private static ParsedStatement query( + Statement statement, String sqlWithoutComments, QueryOptions defaultQueryOptions) { + return new ParsedStatement( + StatementType.QUERY, statement, sqlWithoutComments, defaultQueryOptions); } private static ParsedStatement update(Statement statement, String sqlWithoutComments) { @@ -91,14 +96,40 @@ private ParsedStatement( } private ParsedStatement(StatementType type, Statement statement, String sqlWithoutComments) { + this(type, statement, sqlWithoutComments, null); + } + + private ParsedStatement( + StatementType type, + Statement statement, + String sqlWithoutComments, + QueryOptions defaultQueryOptions) { Preconditions.checkNotNull(type); Preconditions.checkNotNull(statement); this.type = type; this.clientSideStatement = null; - this.statement = statement; + this.statement = mergeQueryOptions(statement, defaultQueryOptions); this.sqlWithoutComments = sqlWithoutComments; } + @Override + public int hashCode() { + return Objects.hash( + this.type, this.clientSideStatement, this.statement, this.sqlWithoutComments); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ParsedStatement)) { + return false; + } + ParsedStatement o = (ParsedStatement) other; + return Objects.equals(this.type, o.type) + && Objects.equals(this.clientSideStatement, o.clientSideStatement) + && Objects.equals(this.statement, o.statement) + && Objects.equals(this.sqlWithoutComments, o.sqlWithoutComments); + } + StatementType getType() { return type; } @@ -148,6 +179,26 @@ Statement getStatement() { return statement; } + /** + * Merges the {@link QueryOptions} of the {@link Statement} with the current {@link + * QueryOptions} of this connection. The {@link QueryOptions} that are already present on the + * statement take precedence above the connection {@link QueryOptions}. + */ + Statement mergeQueryOptions(Statement statement, QueryOptions defaultQueryOptions) { + if (defaultQueryOptions == null + || defaultQueryOptions.equals(QueryOptions.getDefaultInstance())) { + return statement; + } + if (statement.getQueryOptions() == null) { + return statement.toBuilder().withQueryOptions(defaultQueryOptions).build(); + } + return statement + .toBuilder() + .withQueryOptions( + defaultQueryOptions.toBuilder().mergeFrom(statement.getQueryOptions()).build()) + .build(); + } + String getSqlWithoutComments() { return sqlWithoutComments; } @@ -183,12 +234,16 @@ private StatementParser() { * @return the parsed and categorized statement. */ ParsedStatement parse(Statement statement) { + return parse(statement, null); + } + + ParsedStatement parse(Statement statement, QueryOptions defaultQueryOptions) { String sql = removeCommentsAndTrim(statement.getSql()); ClientSideStatementImpl client = parseClientSideStatement(sql); if (client != null) { return ParsedStatement.clientSideStatement(client, statement, sql); } else if (isQuery(sql)) { - return ParsedStatement.query(statement, sql); + return ParsedStatement.query(statement, sql, defaultQueryOptions); } else if (isUpdateStatement(sql)) { return ParsedStatement.update(statement, sql); } else if (isDdlStatement(sql)) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java index 78cde9aca767..9820716a441f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java @@ -60,6 +60,8 @@ enum ClientSideStatementType { SHOW_COMMIT_TIMESTAMP, SHOW_READ_ONLY_STALENESS, SET_READ_ONLY_STALENESS, + SHOW_OPTIMIZER_VERSION, + SET_OPTIMIZER_VERSION, BEGIN, COMMIT, ROLLBACK, diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json index 28c20a5b419d..8d8cca207dc9 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json @@ -68,6 +68,14 @@ "method": "statementShowReadOnlyStaleness", "exampleStatements": ["show variable read_only_staleness"] }, + { + "name": "SHOW VARIABLE OPTIMIZER_VERSION", + "executorName": "ClientSideStatementNoParamExecutor", + "resultType": "RESULT_SET", + "regex": "(?is)\\A\\s*show\\s+variable\\s+optimizer_version\\s*\\z", + "method": "statementShowOptimizerVersion", + "exampleStatements": ["show variable optimizer_version"] + }, { "name": "BEGIN TRANSACTION", "executorName": "ClientSideStatementNoParamExecutor", @@ -241,6 +249,20 @@ "allowedValues": "'((STRONG)|(MIN_READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(MAX_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns))|(EXACT_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns)))'", "converterName": "ClientSideStatementValueConverters$ReadOnlyStalenessConverter" } + }, + { + "name": "SET OPTIMIZER_VERSION = ''|'LATEST'|''", + "executorName": "ClientSideStatementSetExecutor", + "resultType": "NO_RESULT", + "regex": "(?is)\\A\\s*set\\s+optimizer_version\\s*(?:=)\\s*(.*)\\z", + "method": "statementSetOptimizerVersion", + "exampleStatements": ["set optimizer_version='1'", "set optimizer_version='200'", "set optimizer_version='LATEST'", "set optimizer_version=''"], + "setStatement": { + "propertyName": "OPTIMIZER_VERSION", + "separator": "=", + "allowedValues": "'((\\d{1,20})|(LATEST)|())'", + "converterName": "ClientSideStatementValueConverters$StringValueConverter" + } } ] } \ No newline at end of file diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java index 4346bde5c46e..d10508bba6eb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java @@ -20,128 +20,18 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; -import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.AbortInterceptor; import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.ITConnection; import com.google.cloud.spanner.jdbc.it.ITTransactionRetryTest.CountTransactionRetryListener; -import com.google.protobuf.ListValue; -import com.google.protobuf.Value; -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 io.grpc.Server; -import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.List; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) -public class AbortedTest { - private static final Statement SELECT_COUNT = - Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"); - private static final ResultSetMetadata SELECT_COUNT_METADATA = - ResultSetMetadata.newBuilder() - .setRowType( - StructType.newBuilder() - .addFields( - Field.newBuilder() - .setName("C") - .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) - .build()) - .build()) - .build(); - private static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_BEFORE_INSERT = - com.google.spanner.v1.ResultSet.newBuilder() - .addRows( - ListValue.newBuilder() - .addValues(Value.newBuilder().setStringValue("0").build()) - .build()) - .setMetadata(SELECT_COUNT_METADATA) - .build(); - private static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_AFTER_INSERT = - com.google.spanner.v1.ResultSet.newBuilder() - .addRows( - ListValue.newBuilder() - .addValues(Value.newBuilder().setStringValue("1").build()) - .build()) - .setMetadata(SELECT_COUNT_METADATA) - .build(); - private static final Statement INSERT_STATEMENT = - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"); - private static final int UPDATE_COUNT = 1; - - private static MockSpannerServiceImpl mockSpanner; - private static MockInstanceAdminImpl mockInstanceAdmin; - private static MockDatabaseAdminImpl mockDatabaseAdmin; - private static Server server; - private static InetSocketAddress address; - - @BeforeClass - public static void startStaticServer() throws IOException { - mockSpanner = new MockSpannerServiceImpl(); - mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. - mockInstanceAdmin = new MockInstanceAdminImpl(); - mockDatabaseAdmin = new MockDatabaseAdminImpl(); - address = new InetSocketAddress("localhost", 0); - server = - NettyServerBuilder.forAddress(address) - .addService(mockSpanner) - .addService(mockInstanceAdmin) - .addService(mockDatabaseAdmin) - .build() - .start(); - } - - @AfterClass - public static void stopServer() throws Exception { - SpannerPool.closeSpannerPool(); - server.shutdown(); - server.awaitTermination(); - } - - public ITConnection createConnection( - AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { - return createConnection( - Arrays.asList(interceptor), - Arrays.asList(transactionRetryListener)); - } - - public ITConnection createConnection( - List interceptors, - List transactionRetryListeners) { - StringBuilder url = - new StringBuilder( - String.format( - "cloudspanner://localhost:%d/projects/proj/instances/inst/databases/db?usePlainText=true;autocommit=false;retryAbortsInternally=true", - server.getPort())); - ConnectionOptions.Builder builder = - ConnectionOptions.newBuilder() - .setUri(url.toString()) - .setStatementExecutionInterceptors(interceptors); - ConnectionOptions options = builder.build(); - ITConnection connection = createITConnection(options); - for (TransactionRetryListener listener : transactionRetryListeners) { - connection.addTransactionRetryListener(listener); - } - return connection; - } - - private ITConnection createITConnection(ConnectionOptions options) { - return new ITConnectionImpl(options); - } +public class AbortedTest extends AbstractMockServerTest { @Test public void testCommitAborted() { @@ -149,7 +39,7 @@ public void testCommitAborted() { // transaction is the most recent transaction of that session. for (int i = 0; i < 2; i++) { mockSpanner.putStatementResult( - StatementResult.query(SELECT_COUNT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); mockSpanner.putStatementResult(StatementResult.update(INSERT_STATEMENT, UPDATE_COUNT)); AbortInterceptor interceptor = new AbortInterceptor(0); try (ITConnection connection = @@ -170,7 +60,7 @@ public void testCommitAborted() { // do a commit that will first abort, and then on retry will succeed connection.commit(); mockSpanner.putStatementResult( - StatementResult.query(SELECT_COUNT, SELECT_COUNT_RESULTSET_AFTER_INSERT)); + StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_AFTER_INSERT)); // verify that the insert succeeded try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java index 8b4bdf78dab7..f12f5e889d32 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java @@ -608,6 +608,51 @@ public void testGetReadOnlyStaleness() { } } + boolean isSetOptimizerVersionAllowed() { + return !getConnection().isClosed(); + } + + @Test + public void testSetOptimizerVersion() { + try (Connection connection = getConnection()) { + if (isSetOptimizerVersionAllowed()) { + for (String version : new String[] {"1", "2", "latest", ""}) { + log("SET OPTIMIZER_VERSION='" + version + "';"); + connection.setOptimizerVersion(version); + + log("@EXPECT RESULT_SET 'OPTIMIZER_VERSION','" + version + "'"); + log("SHOW VARIABLE OPTIMIZER_VERSION;"); + assertThat(connection.getOptimizerVersion(), is(equalTo(version))); + } + } else { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log("SET OPTIMIZER_VERSION='1';"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.setOptimizerVersion("1"); + } + } + } + + boolean isGetOptimizerVersionAllowed() { + return !getConnection().isClosed(); + } + + @Test + public void testGetOptimizerVersion() { + try (Connection connection = getConnection()) { + if (isGetOptimizerVersionAllowed()) { + log("@EXPECT RESULT_SET 'OPTIMIZER_VERSION'"); + log("SHOW VARIABLE OPTIMIZER_VERSION;"); + assertThat(connection.getOptimizerVersion(), is(notNullValue())); + } else { + log("@EXPECT EXCEPTION FAILED_PRECONDITION"); + log("SHOW VARIABLE OPTIMIZER_VERSION;"); + exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); + connection.getOptimizerVersion(); + } + } + } + abstract boolean isCommitAllowed(); @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java new file mode 100644 index 000000000000..4117eed29ae7 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java @@ -0,0 +1,186 @@ +/* + * Copyright 2020 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.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; +import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.AbortInterceptor; +import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.ITConnection; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +import com.google.spanner.v1.ExecuteSqlRequest; +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 io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public abstract class AbstractMockServerTest { + static final long COUNT_BEFORE_INSERT = 0L; + static final long COUNT_AFTER_INSERT = 1L; + static final Statement SELECT_COUNT_STATEMENT = + Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"); + private static final ResultSetMetadata SELECT_COUNT_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("C") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .build()) + .build(); + static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_BEFORE_INSERT = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder() + .setStringValue(String.valueOf(COUNT_BEFORE_INSERT)) + .build()) + .build()) + .setMetadata(SELECT_COUNT_METADATA) + .build(); + static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_AFTER_INSERT = + com.google.spanner.v1.ResultSet.newBuilder() + .addRows( + ListValue.newBuilder() + .addValues( + Value.newBuilder().setStringValue(String.valueOf(COUNT_AFTER_INSERT)).build()) + .build()) + .setMetadata(SELECT_COUNT_METADATA) + .build(); + static final Statement INSERT_STATEMENT = + Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"); + static final int UPDATE_COUNT = 1; + + static MockSpannerServiceImpl mockSpanner; + static MockInstanceAdminImpl mockInstanceAdmin; + static MockDatabaseAdminImpl mockDatabaseAdmin; + private static Server server; + private static InetSocketAddress address; + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. + mockInstanceAdmin = new MockInstanceAdminImpl(); + mockDatabaseAdmin = new MockDatabaseAdminImpl(); + address = new InetSocketAddress("localhost", 0); + server = + NettyServerBuilder.forAddress(address) + .addService(mockSpanner) + .addService(mockInstanceAdmin) + .addService(mockDatabaseAdmin) + .build() + .start(); + mockSpanner.putStatementResult( + StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + mockSpanner.putStatementResult(StatementResult.update(INSERT_STATEMENT, UPDATE_COUNT)); + } + + @AfterClass + public static void stopServer() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + @Before + public void setupResults() { + mockSpanner.reset(); + } + + @After + public void closeSpannerPool() { + SpannerPool.closeSpannerPool(); + } + + java.sql.Connection createJdbcConnection() throws SQLException { + return DriverManager.getConnection("jdbc:" + getBaseUrl()); + } + + ITConnection createConnection() { + return createConnection( + Collections.emptyList(), + Collections.emptyList()); + } + + ITConnection createConnection( + AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { + return createConnection( + Arrays.asList(interceptor), + Arrays.asList(transactionRetryListener)); + } + + ITConnection createConnection( + List interceptors, + List transactionRetryListeners) { + StringBuilder url = new StringBuilder(getBaseUrl()); + ConnectionOptions.Builder builder = + ConnectionOptions.newBuilder() + .setUri(url.toString()) + .setStatementExecutionInterceptors(interceptors); + ConnectionOptions options = builder.build(); + ITConnection connection = createITConnection(options); + for (TransactionRetryListener listener : transactionRetryListeners) { + connection.addTransactionRetryListener(listener); + } + return connection; + } + + String getBaseUrl() { + return String.format( + "cloudspanner://localhost:%d/projects/proj/instances/inst/databases/db?usePlainText=true;autocommit=false;retryAbortsInternally=true", + server.getPort()); + } + + ExecuteSqlRequest getLastExecuteSqlRequest() { + List requests = mockSpanner.getRequests(); + for (int i = requests.size() - 1; i >= 0; i--) { + if (requests.get(i) instanceof ExecuteSqlRequest) { + return (ExecuteSqlRequest) requests.get(i); + } + } + throw new IllegalStateException("No ExecuteSqlRequest found in requests"); + } + + private ITConnection createITConnection(ConnectionOptions options) { + return new ITConnectionImpl(options); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java index 38c978766dad..2c2cb964f09b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java @@ -24,10 +24,12 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.api.core.ApiFuture; @@ -38,6 +40,8 @@ import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ForwardingResultSet; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ReadOnlyTransaction; import com.google.cloud.spanner.ResultSet; @@ -57,6 +61,7 @@ import com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.GetExactStaleness; import com.google.cloud.spanner.jdbc.StatementResult.ResultType; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import com.google.spanner.v1.ResultSetStats; import java.util.Arrays; import java.util.HashMap; @@ -523,6 +528,76 @@ public void testExecuteGetAutocommitDmlMode() { } } + @Test + public void testExecuteSetOptimizerVersion() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getOptimizerVersion(), is(equalTo(""))); + + StatementResult res = subject.execute(Statement.of("set optimizer_version='1'")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getOptimizerVersion(), is(equalTo("1"))); + + res = subject.execute(Statement.of("set optimizer_version='1000'")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getOptimizerVersion(), is(equalTo("1000"))); + + res = subject.execute(Statement.of("set optimizer_version='latest'")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getOptimizerVersion(), is(equalTo("latest"))); + + res = subject.execute(Statement.of("set optimizer_version=''")); + assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); + assertThat(subject.getOptimizerVersion(), is(equalTo(""))); + } + } + + @Test + public void testExecuteSetOptimizerVersionInvalidValue() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getOptimizerVersion(), is(equalTo(""))); + + try { + subject.execute(Statement.of("set optimizer_version='NOT_A_VERSION'")); + fail("Missing expected exception"); + } catch (SpannerException e) { + assertThat(e.getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); + } + } + } + + @Test + public void testExecuteGetOptimizerVersion() { + try (ConnectionImpl subject = + createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(URI) + .build())) { + assertThat(subject.getOptimizerVersion(), is(equalTo(""))); + + StatementResult res = subject.execute(Statement.of("show variable optimizer_version")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getString("OPTIMIZER_VERSION"), is(equalTo(""))); + + subject.execute(Statement.of("set optimizer_version='1'")); + res = subject.execute(Statement.of("show variable optimizer_version")); + assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); + assertThat(res.getResultSet().next(), is(true)); + assertThat(res.getResultSet().getString("OPTIMIZER_VERSION"), is(equalTo("1"))); + } + } + @Test public void testExecuteSetStatementTimeout() { try (ConnectionImpl subject = @@ -1114,4 +1189,73 @@ public void testAddRemoveTransactionRetryListener() { assertThat(subject.removeTransactionRetryListener(listener), is(false)); } } + + @Test + public void testMergeQueryOptions() { + ConnectionOptions connectionOptions = mock(ConnectionOptions.class); + SpannerPool spannerPool = mock(SpannerPool.class); + DdlClient ddlClient = mock(DdlClient.class); + DatabaseClient dbClient = mock(DatabaseClient.class); + final UnitOfWork unitOfWork = mock(UnitOfWork.class); + try (ConnectionImpl impl = + new ConnectionImpl(connectionOptions, spannerPool, ddlClient, dbClient) { + @Override + UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { + return unitOfWork; + } + }) { + // Execute query with an optimizer version set on the connection. + impl.setOptimizerVersion("1"); + impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); + verify(unitOfWork) + .executeQuery( + StatementParser.INSTANCE.parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("1").build()) + .build()), + AnalyzeMode.NONE); + + // Execute query with an optimizer version set on the connection. + impl.setOptimizerVersion("2"); + impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); + verify(unitOfWork) + .executeQuery( + StatementParser.INSTANCE.parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("2").build()) + .build()), + AnalyzeMode.NONE); + + // Execute query with an optimizer version set on the connection and PrefetchChunks query + // option specified for the query. + QueryOption prefetchOption = Options.prefetchChunks(100); + impl.setOptimizerVersion("3"); + impl.executeQuery(Statement.of("SELECT FOO FROM BAR"), prefetchOption); + verify(unitOfWork) + .executeQuery( + StatementParser.INSTANCE.parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("3").build()) + .build()), + AnalyzeMode.NONE, + prefetchOption); + + // Execute query with an optimizer version set on the connection, and the same options also + // passed in to the query. The specific options passed in to the query should take precedence. + impl.setOptimizerVersion("4"); + impl.executeQuery( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("5").build()) + .build(), + prefetchOption); + verify(unitOfWork) + .executeQuery( + StatementParser.INSTANCE.parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("5").build()) + .build()), + AnalyzeMode.NONE, + prefetchOption); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java index debd02b84f57..6e524c497235 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java @@ -95,6 +95,12 @@ public void testStatementGetReadOnlyStaleness() { verify(connection).getReadOnlyStaleness(); } + @Test + public void testStatementGetOptimizerVersion() { + subject.statementShowOptimizerVersion(); + verify(connection).getOptimizerVersion(); + } + @Test public void testStatementGetReadTimestamp() { subject.statementShowReadTimestamp(); @@ -167,6 +173,16 @@ public void testStatementSetReadOnlyStaleness() { .setReadOnlyStaleness(TimestampBound.ofMaxStaleness(20L, TimeUnit.MILLISECONDS)); } + @Test + public void testStatementSetOptimizerVersion() { + subject.statementSetOptimizerVersion("1"); + verify(connection).setOptimizerVersion("1"); + subject.statementSetOptimizerVersion(""); + verify(connection).setOptimizerVersion(""); + subject.statementSetOptimizerVersion("LATEST"); + verify(connection).setOptimizerVersion("LATEST"); + } + @Test public void testStatementSetStatementTimeout() { subject.statementSetStatementTimeout(Duration.newBuilder().setNanos(100).build()); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java index e106bcd69467..51aa8abe1c4f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java @@ -114,6 +114,18 @@ public void testExecuteGetReadOnlyStaleness() throws Exception { verify(connection, times(1)).getReadOnlyStaleness(); } + @Test + public void testExecuteGetOptimizerVersion() throws Exception { + ParsedStatement statement = parser.parse(Statement.of("show variable optimizer_version")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementShowOptimizerVersion()).thenCallRealMethod(); + when(connection.getOptimizerVersion()).thenReturn("1"); + statement.getClientSideStatement().execute(executor, "show variable optimizer_version"); + verify(connection, times(1)).getOptimizerVersion(); + } + @Test public void testExecuteBegin() throws Exception { ParsedStatement subject = parser.parse(Statement.of("begin")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java index de5354fc66b3..b9ebf1edae42 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java @@ -148,6 +148,21 @@ private String timestampBoundToString(TimestampBound staleness) { } } + @Test + public void testExecuteSetOptimizerVersion() throws Exception { + ParsedStatement subject = parser.parse(Statement.of("set optimizer_version='foo'")); + ConnectionImpl connection = mock(ConnectionImpl.class); + ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getConnection()).thenReturn(connection); + when(executor.statementSetOptimizerVersion(any(String.class))).thenCallRealMethod(); + for (String version : new String[] {"1", "200", "", "LATEST"}) { + subject + .getClientSideStatement() + .execute(executor, String.format("set optimizer_version='%s'", version)); + verify(connection, times(1)).setOptimizerVersion(version); + } + } + @Test public void testExecuteSetTransaction() throws Exception { ParsedStatement subject = parser.parse(Statement.of("set transaction read_only")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java new file mode 100644 index 000000000000..d99b9a738f49 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2020 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 com.google.common.truth.Truth.assertThat; + +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Statement; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; +import java.sql.SQLException; +import org.junit.Test; + +public class ConnectionTest extends AbstractMockServerTest { + @Test + public void testDefaultOptimizerVersion() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.executeQuery(Statement.of("SHOW VARIABLE OPTIMIZER_VERSION"))) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void testUseOptimizerVersionFromEnvironment() throws SQLException { + try { + SpannerOptions.useEnvironment( + new SpannerOptions.SpannerEnvironment() { + @Override + public String getOptimizerVersion() { + return "20"; + } + }); + try (Connection connection = createConnection()) { + // Do a query and verify that the version from the environment is used. + try (ResultSet rs = connection.executeQuery(SELECT_COUNT_STATEMENT)) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // Verify query options from the environment. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); + } + // Now set one of the query options on the connection. That option should be used in + // combination with the other option from the environment. + connection.execute(Statement.of("SET OPTIMIZER_VERSION='30'")); + try (ResultSet rs = connection.executeQuery(SELECT_COUNT_STATEMENT)) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + // Optimizer version should come from the connection. + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("30"); + } + // Now specify options directly for the query. These should override both the environment + // and what is set on the connection. + try (ResultSet rs = + connection.executeQuery( + Statement.newBuilder(SELECT_COUNT_STATEMENT.getSql()) + .withQueryOptions( + QueryOptions.newBuilder() + .setOptimizerVersion("user-defined-version") + .build()) + .build())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + // Optimizer version should come from the query. + assertThat(request.getQueryOptions().getOptimizerVersion()) + .isEqualTo("user-defined-version"); + } + } + } finally { + SpannerOptions.useDefaultEnvironment(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java new file mode 100644 index 000000000000..460e07f6699e --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -0,0 +1,215 @@ +/* + * Copyright 2020 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 com.google.common.truth.Truth.assertThat; + +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Statement; +import com.google.common.base.MoreObjects; +import com.google.spanner.v1.ExecuteSqlRequest; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcQueryOptionsTest extends AbstractMockServerTest { + @Test + public void testDefaultOptimizerVersion() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void testOptimizerVersionInConnectionUrl() throws SQLException { + try (java.sql.Connection connection = + DriverManager.getConnection( + String.format("jdbc:%s;optimizerVersion=%s", getBaseUrl(), "100"))) { + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo("100"); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void testSetOptimizerVersion() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.createStatement().execute("SET OPTIMIZER_VERSION='20'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo("20"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET OPTIMIZER_VERSION='latest'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo("latest"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET OPTIMIZER_VERSION=''"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void testSetAndUseOptimizerVersion() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.createStatement().execute("SET OPTIMIZER_VERSION='20'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // Verify that the last ExecuteSqlRequest that the server received specified optimizer + // version 20. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); + } + + // Do another query, but now with optimizer version 'latest'. + connection.createStatement().execute("SET OPTIMIZER_VERSION='latest'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // Verify that the last ExecuteSqlRequest that the server received specified optimizer + // version 'latest'. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("latest"); + } + + // Set the optimizer version to ''. This will do a fallback to the default, meaning that it + // will be read from the environment variable SPANNER_OPTIMIZER_VERSION as we have nothing set + // on the connection URL. + connection.createStatement().execute("SET OPTIMIZER_VERSION=''"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // Verify that the last ExecuteSqlRequest that the server received specified an optimizer + // version equal to the environment default. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()) + .isEqualTo(MoreObjects.firstNonNull(System.getenv("SPANNER_OPTIMIZER_VERSION"), "")); + } + } + } + + @Test + public void testUseOptimizerVersionFromConnectionUrl() throws SQLException { + try (java.sql.Connection connection = + DriverManager.getConnection(String.format("jdbc:%s;optimizerVersion=10", getBaseUrl()))) { + // Do a query and verify that the version from the connection URL is used. + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // The optimizer version used should be '10' from the connection URL. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("10"); + } + } + } + + @Test + public void testUseOptimizerVersionFromEnvironment() throws SQLException { + try { + SpannerOptions.useEnvironment( + new SpannerOptions.SpannerEnvironment() { + @Override + public String getOptimizerVersion() { + return "20"; + } + }); + try (java.sql.Connection connection = + DriverManager.getConnection(String.format("jdbc:%s", getBaseUrl()))) { + // Do a query and verify that the version from the environment is used. + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // Verify query options from the environment. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); + } + // Now set one of the query options on the connection. That option should be used in + // combination with the other option from the environment. + connection.createStatement().execute("SET OPTIMIZER_VERSION='30'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + // Optimizer version should come from the connection. + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("30"); + } + } + } finally { + SpannerOptions.useDefaultEnvironment(); + } + } + + @Test + public void testUseQueryHint() throws SQLException { + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of( + String.format("@{optimizer_version=1} %s", SELECT_COUNT_STATEMENT.getSql())), + SELECT_COUNT_RESULTSET_BEFORE_INSERT)); + try (java.sql.Connection connection = + DriverManager.getConnection(String.format("jdbc:%s", getBaseUrl()))) { + try (java.sql.ResultSet rs = + connection + .createStatement() + .executeQuery( + String.format("@{optimizer_version=1} %s", SELECT_COUNT_STATEMENT.getSql()))) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); + assertThat(rs.next()).isFalse(); + // The optimizer version used in the ExecuteSqlRequest should be empty as the query hint is + // parsed by the backend. + ExecuteSqlRequest request = getLastExecuteSqlRequest(); + assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo(""); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 773fcf94e3c9..328c01f1cfbc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -50,6 +50,7 @@ import java.util.Calendar; import java.util.List; import java.util.TimeZone; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -580,6 +581,7 @@ public void testSetTimestampInCalendar() throws SQLException { } } + @Ignore("ignore until java-core 1.93.3 is available") @SuppressWarnings("deprecation") @Test public void testToGoogleTimestamp() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java new file mode 100644 index 000000000000..8e72aa24b7c9 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -0,0 +1,214 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JdbcSqlException; +import com.google.cloud.spanner.jdbc.SpannerPool; +import com.google.rpc.Code; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * {@link QueryOptions} can be used with the JDBC driver on three different levels: + * + *
      + *
    1. Specify {@link QueryOptions} in environment variables. + *
    2. Specify {@link QueryOptions} in the connection URL or by setting these using + * SET <query_option> = '<value>' statements. + *
    3. Specify {@link QueryOptions} in a query hint. + *
    + * + * This class tests all three possibilities. + */ +@Category(IntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcQueryOptionsTest extends ITAbstractJdbcTest { + private String connectionUriSuffix; + + @Before + public void resetConnectionUriSuffix() { + connectionUriSuffix = ""; + } + + @After + public void closeSpannerPool() { + // Close the pool after each test to prevent side effects from one test case to affect following + // test cases. + SpannerPool.closeSpannerPool(); + } + + @Override + protected void appendConnectionUri(StringBuilder uri) { + uri.append(connectionUriSuffix); + } + + private void verifyOptimizerVersion(Connection connection, String expectedVersion) + throws SQLException { + try (ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(expectedVersion); + assertThat(rs.next()).isFalse(); + } + } + + @Test + public void connectionUrl() throws SQLException { + this.connectionUriSuffix = ";optimizerVersion=1"; + try (Connection connection = createConnection()) { + verifyOptimizerVersion(connection, "1"); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { + this.connectionUriSuffix = ";optimizerVersion=9999999"; + try (Connection connection = createConnection()) { + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException je = (JdbcSqlException) e; + assertThat(je.getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + } + + @Test + public void setOptimizerVersion() throws SQLException { + try (Connection connection = createConnection()) { + verifyOptimizerVersion(connection, ""); + connection.createStatement().execute("SET OPTIMIZER_VERSION='1'"); + verifyOptimizerVersion(connection, "1"); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void setLatestOptimizerVersion() throws SQLException { + try (Connection connection = createConnection()) { + verifyOptimizerVersion(connection, ""); + connection.createStatement().execute("SET OPTIMIZER_VERSION='LATEST'"); + verifyOptimizerVersion(connection, "LATEST"); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void setInvalidOptimizerVersion() throws SQLException { + try (Connection connection = createConnection()) { + connection.createStatement().execute("SET OPTIMIZER_VERSION='9999999'"); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException je = (JdbcSqlException) e; + assertThat(je.getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + } + + @Test + public void optimizerVersionInQueryHint() throws SQLException { + try (Connection connection = createConnection()) { + verifyOptimizerVersion(connection, ""); + try (ResultSet rs = + connection.createStatement().executeQuery("@{optimizer_version=1} SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + try (ResultSet rs = + connection.createStatement().executeQuery("@{optimizer_version=latest} SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + } + } + + @Test + public void optimizerVersionInEnvironment() throws SQLException { + try { + SpannerOptions.useEnvironment( + new SpannerOptions.SpannerEnvironment() { + @Override + public String getOptimizerVersion() { + return "1"; + } + }); + try (Connection connection = createConnection()) { + // Environment query options are not visible to the connection. + verifyOptimizerVersion(connection, ""); + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(1)).isEqualTo(1L); + assertThat(rs.next()).isFalse(); + } + } + // Close the pool to force re-initialization of any cached connections. + SpannerPool.closeSpannerPool(); + + // Now set an invalid version on the environment. The query will now fail. + SpannerOptions.useEnvironment( + new SpannerOptions.SpannerEnvironment() { + @Override + public String getOptimizerVersion() { + return "9999999"; + } + }); + try (Connection connection = createConnection()) { + try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException je = (JdbcSqlException) e; + assertThat(je.getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + } finally { + SpannerOptions.useDefaultEnvironment(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index f8154dc755df..87f5abec468d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -61,6 +61,7 @@ public class ITJdbcSqlScriptTest extends ITAbstractJdbcTest { "ITSqlScriptTest_TestAutocommitDmlMode.sql"; private static final String TEST_AUTOCOMMIT_READ_ONLY = "ITSqlScriptTest_TestAutocommitReadOnly.sql"; + private static final String TEST_QUERY_OPTIONS = "ITSqlScriptTest_TestQueryOptions.sql"; private static final String TEST_STATEMENT_TIMEOUT = "ITSqlScriptTest_TestStatementTimeout.sql"; private static final String TEST_SET_STATEMENTS = "ITSqlScriptTest_TestSetStatements.sql"; private static final String TEST_INVALID_STATEMENTS = "ITSqlScriptTest_TestInvalidStatements.sql"; @@ -208,4 +209,12 @@ public void test13_TestInvalidStatements() throws Exception { JdbcGenericConnection.of(connection), TEST_INVALID_STATEMENTS, SqlScriptVerifier.class); } } + + @Test + public void test14_TestQueryOptions() throws Exception { + try (Connection connection = createConnection()) { + verifier.verifyStatementsInFile( + JdbcGenericConnection.of(connection), TEST_QUERY_OPTIONS, SqlScriptVerifier.class); + } + } } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql index fe8afd86e970..56d8041af73e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql @@ -1931,6 +1931,205 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT show variable/-read_only_staleness; NEW_CONNECTION; +show variable optimizer_version; +NEW_CONNECTION; +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +show variable optimizer_version; +NEW_CONNECTION; + show variable optimizer_version; +NEW_CONNECTION; + show variable optimizer_version; +NEW_CONNECTION; + + + +show variable optimizer_version; +NEW_CONNECTION; +show variable optimizer_version ; +NEW_CONNECTION; +show variable optimizer_version ; +NEW_CONNECTION; +show variable optimizer_version + +; +NEW_CONNECTION; +show variable optimizer_version; +NEW_CONNECTION; +show variable optimizer_version; +NEW_CONNECTION; +show +variable +optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable%optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable_optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable&optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable$optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable@optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable!optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable*optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable(optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable)optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable+optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-#optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable\optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable?optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable-/optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/#optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-show variable optimizer_version; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +show variable/-optimizer_version; +NEW_CONNECTION; begin; NEW_CONNECTION; BEGIN; @@ -11076,3 +11275,795 @@ set read_only_staleness='EXACT_STALENESS 9999ns'/-; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT set read_only_staleness='EXACT_STALENESS/-9999ns'; +NEW_CONNECTION; +set optimizer_version='1'; +NEW_CONNECTION; +SET OPTIMIZER_VERSION='1'; +NEW_CONNECTION; +set optimizer_version='1'; +NEW_CONNECTION; + set optimizer_version='1'; +NEW_CONNECTION; + set optimizer_version='1'; +NEW_CONNECTION; + + + +set optimizer_version='1'; +NEW_CONNECTION; +set optimizer_version='1' ; +NEW_CONNECTION; +set optimizer_version='1' ; +NEW_CONNECTION; +set optimizer_version='1' + +; +NEW_CONNECTION; +set optimizer_version='1'; +NEW_CONNECTION; +set optimizer_version='1'; +NEW_CONNECTION; +set +optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set optimizer_version='1'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='1'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-optimizer_version='1'; +NEW_CONNECTION; +set optimizer_version='200'; +NEW_CONNECTION; +SET OPTIMIZER_VERSION='200'; +NEW_CONNECTION; +set optimizer_version='200'; +NEW_CONNECTION; + set optimizer_version='200'; +NEW_CONNECTION; + set optimizer_version='200'; +NEW_CONNECTION; + + + +set optimizer_version='200'; +NEW_CONNECTION; +set optimizer_version='200' ; +NEW_CONNECTION; +set optimizer_version='200' ; +NEW_CONNECTION; +set optimizer_version='200' + +; +NEW_CONNECTION; +set optimizer_version='200'; +NEW_CONNECTION; +set optimizer_version='200'; +NEW_CONNECTION; +set +optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set optimizer_version='200'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='200'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-optimizer_version='200'; +NEW_CONNECTION; +set optimizer_version='LATEST'; +NEW_CONNECTION; +SET OPTIMIZER_VERSION='LATEST'; +NEW_CONNECTION; +set optimizer_version='latest'; +NEW_CONNECTION; + set optimizer_version='LATEST'; +NEW_CONNECTION; + set optimizer_version='LATEST'; +NEW_CONNECTION; + + + +set optimizer_version='LATEST'; +NEW_CONNECTION; +set optimizer_version='LATEST' ; +NEW_CONNECTION; +set optimizer_version='LATEST' ; +NEW_CONNECTION; +set optimizer_version='LATEST' + +; +NEW_CONNECTION; +set optimizer_version='LATEST'; +NEW_CONNECTION; +set optimizer_version='LATEST'; +NEW_CONNECTION; +set +optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set optimizer_version='LATEST'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='LATEST'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-optimizer_version='LATEST'; +NEW_CONNECTION; +set optimizer_version=''; +NEW_CONNECTION; +SET OPTIMIZER_VERSION=''; +NEW_CONNECTION; +set optimizer_version=''; +NEW_CONNECTION; + set optimizer_version=''; +NEW_CONNECTION; + set optimizer_version=''; +NEW_CONNECTION; + + + +set optimizer_version=''; +NEW_CONNECTION; +set optimizer_version='' ; +NEW_CONNECTION; +set optimizer_version='' ; +NEW_CONNECTION; +set optimizer_version='' + +; +NEW_CONNECTION; +set optimizer_version=''; +NEW_CONNECTION; +set optimizer_version=''; +NEW_CONNECTION; +set +optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version='' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set%optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set_optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set&optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set$optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set@optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set!optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set*optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set(optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set)optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set+optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-#optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set\optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set?optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set-/optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/#optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set optimizer_version=''; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set optimizer_version=''/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set/-optimizer_version=''; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql index c76508561647..a4d68cda077a 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql @@ -2,6 +2,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -142,15 +152,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:54.904000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -179,6 +189,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -272,6 +302,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -422,15 +462,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:54.986000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -461,6 +501,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -561,6 +621,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -711,15 +781,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.049000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -750,6 +820,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -850,6 +940,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -1000,15 +1100,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.100000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1039,6 +1139,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -1141,6 +1261,20 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -1345,8 +1479,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1354,8 +1488,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.147000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1396,6 +1530,30 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -1515,6 +1673,14 @@ COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -1638,14 +1804,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.196000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1671,6 +1837,24 @@ SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -1762,6 +1946,18 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -1928,8 +2124,8 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -1937,7 +2133,7 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.237000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -1971,6 +2167,28 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -2074,6 +2292,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -2218,15 +2446,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.284000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -2255,6 +2483,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -2348,6 +2596,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -2512,15 +2770,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.377000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -2551,6 +2809,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -2651,6 +2929,18 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -2842,16 +3132,16 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.430000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -2887,6 +3177,28 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -2996,6 +3308,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -3160,15 +3482,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.491000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -3199,6 +3521,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -3298,6 +3640,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; @@ -3439,13 +3791,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.524000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.797000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.524000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.797000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -3472,6 +3824,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -3567,6 +3939,20 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -3785,8 +4171,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -3794,8 +4180,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.594000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -3836,6 +4222,30 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -3955,6 +4365,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -4119,15 +4539,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.650000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -4158,6 +4578,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -4256,6 +4696,14 @@ UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -4393,14 +4841,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2019-07-31T10:46:55.687000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -4426,6 +4874,24 @@ SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -4515,6 +4981,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -4659,15 +5135,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.716000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4696,6 +5172,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4792,6 +5288,22 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -5031,8 +5543,8 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -5042,7 +5554,7 @@ SET TRANSACTION READ ONLY; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.754000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5086,6 +5598,32 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5214,6 +5752,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -5372,15 +5920,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.806000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5409,6 +5957,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5509,6 +6077,20 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -5721,8 +6303,8 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -5731,7 +6313,7 @@ START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.836000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5770,6 +6352,30 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5891,6 +6497,22 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -6130,8 +6752,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -6141,7 +6763,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.874000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6185,6 +6807,32 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6314,6 +6962,18 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -6487,14 +7147,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.915000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.279000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.915000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.279000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6526,6 +7186,28 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6629,6 +7311,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -6775,13 +7467,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.970000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.328000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.970000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.328000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6808,6 +7500,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6901,6 +7613,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -7059,15 +7781,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:55.995000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7096,6 +7818,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7194,6 +7936,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -7333,15 +8085,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.013000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7370,6 +8122,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7463,6 +8235,16 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; @@ -7604,13 +8386,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.029000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.451000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.029000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.451000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7637,6 +8419,26 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7733,6 +8535,22 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -7972,8 +8790,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -7983,7 +8801,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.066000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8027,6 +8845,32 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8156,6 +9000,18 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; @@ -8324,14 +9180,14 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.104000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.539000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.104000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.539000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8363,6 +9219,28 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8465,6 +9343,14 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -8596,14 +9482,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.132000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8627,6 +9513,24 @@ SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8715,6 +9619,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -8855,15 +9769,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.157000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -8892,6 +9806,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -8985,6 +9919,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -9133,15 +10077,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.175000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9170,6 +10114,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9272,6 +10236,22 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -9501,8 +10481,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -9512,7 +10492,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.203000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9556,6 +10536,32 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9686,6 +10692,18 @@ SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -9854,14 +10872,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.262000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.711000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.262000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.711000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9893,6 +10911,28 @@ SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -9996,6 +11036,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -10137,13 +11187,13 @@ SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.291000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.762000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.291000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.762000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10170,6 +11220,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10263,6 +11333,16 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -10411,15 +11491,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.311000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10448,6 +11528,26 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10550,6 +11650,22 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -10779,8 +11895,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -10790,7 +11906,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.334000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10834,6 +11950,32 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -10962,6 +12104,14 @@ COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; @@ -11083,14 +12233,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2019-07-31T10:46:56.355000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -11114,6 +12264,24 @@ SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +SET OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','2' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','latest' +SHOW VARIABLE OPTIMIZER_VERSION; +SET OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestQueryOptions.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestQueryOptions.sql new file mode 100644 index 000000000000..923cc97167fd --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestQueryOptions.sql @@ -0,0 +1,51 @@ +/* + * Copyright 2020 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. + */ + +/* + * Test setting and getting the optimizer version to use. + */ + +-- Set and get valid values. +@EXPECT NO_RESULT +SET OPTIMIZER_VERSION = '1'; + +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' +SHOW VARIABLE OPTIMIZER_VERSION; + +@EXPECT NO_RESULT +SET OPTIMIZER_VERSION = '555'; + +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','555' +SHOW VARIABLE OPTIMIZER_VERSION; + +@EXPECT NO_RESULT +SET OPTIMIZER_VERSION = 'LATEST'; + +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','LATEST' +SHOW VARIABLE OPTIMIZER_VERSION; + +@EXPECT NO_RESULT +SET OPTIMIZER_VERSION = ''; + +@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' +SHOW VARIABLE OPTIMIZER_VERSION; + +-- Try to set invalid values. +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for OPTIMIZER_VERSION: 'None'' +SET OPTIMIZER_VERSION = 'None'; + +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for OPTIMIZER_VERSION: 'v1'' +SET OPTIMIZER_VERSION = 'v1'; From 8d1abdb829f269add4fb2da8571262bb953f25c0 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Mon, 23 Mar 2020 16:06:55 -0700 Subject: [PATCH 0124/1979] chore: use java helper for templates (#92) --- java-spanner-jdbc/synth.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/synth.py index 259352ead231..a5ea146c6116 100644 --- a/java-spanner-jdbc/synth.py +++ b/java-spanner-jdbc/synth.py @@ -14,12 +14,8 @@ """This script is used to synthesize generated parts of this library.""" -import synthtool as s -import synthtool.gcp as gcp +import synthtool.languages.java as java - -common_templates = gcp.CommonTemplates() -templates = common_templates.java_library() -s.copy(templates, excludes=[ +java.common_templates(excludes=[ 'README.md' -]) \ No newline at end of file +]) From f192676d337e92f76f4aeafa742db0fdfba728d3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 24 Mar 2020 03:10:08 +0100 Subject: [PATCH 0125/1979] deps: update spanner.version to v1.52.0 (#95) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b850ccf1e7b1..26a888bb18b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ 3.11.4 1.4.1 1.8.1 - 1.51.0 + 1.52.0 2.2 2.3.4 0.20.0 From 97847591797d2d376aa6e99d12f679808cdcdf4c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2020 03:26:38 +0000 Subject: [PATCH 0126/1979] chore: release 1.15.0 (#96) :robot: I have created a release \*beep\* \*boop\* --- ## [1.15.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.14.0...v1.15.0) (2020-03-24) ### Features * add support for QueryOptions ([#76](https://www.github.com/googleapis/java-spanner-jdbc/issues/76)) ([eefc677](https://www.github.com/googleapis/java-spanner-jdbc/commit/eefc67761c7889ab3edd86c3db3940b880f1ecf8)) ### Dependencies * update spanner.version to v1.52.0 ([#95](https://www.github.com/googleapis/java-spanner-jdbc/issues/95)) ([f192676](https://www.github.com/googleapis/java-spanner-jdbc/commit/f192676d337e92f76f4aeafa742db0fdfba728d3)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d3d90e78552c..e01abdd37857 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.15.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.14.0...v1.15.0) (2020-03-24) + + +### Features + +* add support for QueryOptions ([#76](https://www.github.com/googleapis/java-spanner-jdbc/issues/76)) ([b3f4cf7](https://www.github.com/googleapis/java-spanner-jdbc/commit/b3f4cf7852a2fd5f22660cc3f25a6253b9a118ab)) + + +### Dependencies + +* update spanner.version to v1.52.0 ([#95](https://www.github.com/googleapis/java-spanner-jdbc/issues/95)) ([cdf9d30](https://www.github.com/googleapis/java-spanner-jdbc/commit/cdf9d30e8ca387d87a6ffe00fa09818d135547f4)) + ## [1.14.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.13.0...v1.14.0) (2020-03-18) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 4a14e5b15545..4940cce2e6b1 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.14.0 + 1.15.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.14.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.15.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.14.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.15.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 26a888bb18b0..302402fce17c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.14.1-SNAPSHOT + 1.15.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ce565c7b403c..6a0536c84334 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.14.0:1.14.1-SNAPSHOT +google-cloud-spanner-jdbc:1.15.0:1.15.0 From 9db9d558bd7e84ae7090734bc94a6470f4f0ed34 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Mon, 23 Mar 2020 21:24:04 -0700 Subject: [PATCH 0127/1979] chore: enable context aware commits (#98) --- java-spanner-jdbc/synth.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/synth.py index a5ea146c6116..ab9fa625d1a9 100644 --- a/java-spanner-jdbc/synth.py +++ b/java-spanner-jdbc/synth.py @@ -16,6 +16,8 @@ import synthtool.languages.java as java +AUTOSYNTH_MULTIPLE_COMMITS = True + java.common_templates(excludes=[ 'README.md' ]) From 3b0077362a68d89716b8f1570d28b9bfb1a17e96 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 26 Mar 2020 00:23:07 +0100 Subject: [PATCH 0128/1979] deps: update dependency com.google.api:api-common to v1.9.0 (#100) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.api:api-common](https://togithub.com/googleapis/api-common-java) | minor | `1.8.1` -> `1.9.0` | --- ### Release Notes
    googleapis/api-common-java ### [`v1.9.0`](https://togithub.com/googleapis/api-common-java/releases/v1.9.0) [Compare Source](https://togithub.com/googleapis/api-common-java/compare/v1.8.1...v1.9.0) 03-25-2020 14:09 PST #### New Features - Add `@BetaApi` `ApiFutres.catchingAsync()` ([#​117](https://togithub.com/googleapis/api-common-java/pull/117)) ##### Dependencies - Update guava to v28.2-android ([#​110](https://togithub.com/googleapis/api-common-java/pull/110)) - Update error_prone_annotations to v2.2.3 ([#​111](https://togithub.com/googleapis/api-common-java/pull/111))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 302402fce17c..e522d9534178 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -68,7 +68,7 @@ 1.17.0 3.11.4 1.4.1 - 1.8.1 + 1.9.0 1.52.0 2.2 2.3.4 From 3b52c95a01bd50c7bcdd2dddcc9c8a820bcebb20 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 25 Mar 2020 22:10:47 -0700 Subject: [PATCH 0129/1979] chore: update common templates (#102) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/f193fffb-af3a-401a-a8ed-2548fbd8844c/targets --- java-spanner-jdbc/.kokoro/build.sh | 19 +++++---- java-spanner-jdbc/.kokoro/common.sh | 44 ++++++++++++++++++++ java-spanner-jdbc/.kokoro/dependencies.sh | 15 +++++-- java-spanner-jdbc/.kokoro/linkage-monitor.sh | 22 ++++++---- java-spanner-jdbc/renovate.json | 6 ++- java-spanner-jdbc/synth.metadata | 10 ++--- 6 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/common.sh diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 414656e37b7d..560e01957f33 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -20,17 +20,22 @@ scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) ## cd to the parent directory, i.e. the root of the git repo cd ${scriptDir}/.. +# include common functions +source ${scriptDir}/common.sh + # Print out Java version java -version echo ${JOB_TYPE} -mvn install -B -V \ - -DskipTests=true \ - -Dclirr.skip=true \ - -Denforcer.skip=true \ - -Dmaven.javadoc.skip=true \ - -Dgcloud.download.skip=true \ - -T 1C +# attempt to install 3 times with exponential backoff (starting with 10 seconds) +retry_with_backoff 3 10 \ + mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dmaven.javadoc.skip=true \ + -Dgcloud.download.skip=true \ + -T 1C # if GOOGLE_APPLICATION_CREDIENTIALS is specified as a relative path prepend Kokoro root directory onto it if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTIALS}" != /* ]]; then diff --git a/java-spanner-jdbc/.kokoro/common.sh b/java-spanner-jdbc/.kokoro/common.sh new file mode 100644 index 000000000000..a3bbc5f67963 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/common.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Copyright 2020 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. + +# set -eo pipefail + +function retry_with_backoff { + attempts_left=$1 + sleep_seconds=$2 + shift 2 + command=$@ + + echo "${command}" + ${command} + exit_code=$? + + if [[ $exit_code == 0 ]] + then + return 0 + fi + + # failure + if [[ ${attempts_left} > 0 ]] + then + echo "failure (${exit_code}), sleeping ${sleep_seconds}..." + sleep ${sleep_seconds} + new_attempts=$((${attempts_left} - 1)) + new_sleep=$((${sleep_seconds} * 2)) + retry_with_backoff ${new_attempts} ${new_sleep} ${command} + fi + + return $exit_code +} diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index d1cb8dc2ca13..0aade871ce10 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -15,7 +15,13 @@ set -eo pipefail -cd github/java-spanner-jdbc/ +## Get the directory of the build script +scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) +## cd to the parent directory, i.e. the root of the git repo +cd ${scriptDir}/.. + +# include common functions +source ${scriptDir}/common.sh # Print out Java java -version @@ -24,8 +30,9 @@ echo $JOB_TYPE export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" # this should run maven enforcer -mvn install -B -V \ - -DskipTests=true \ - -Dclirr.skip=true +retry_with_backoff 3 10 \ + mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true mvn -B dependency:analyze -DfailOnWarning=true diff --git a/java-spanner-jdbc/.kokoro/linkage-monitor.sh b/java-spanner-jdbc/.kokoro/linkage-monitor.sh index 651c7b5ebd59..759ab4e2c220 100755 --- a/java-spanner-jdbc/.kokoro/linkage-monitor.sh +++ b/java-spanner-jdbc/.kokoro/linkage-monitor.sh @@ -17,18 +17,26 @@ set -eo pipefail # Display commands being run. set -x -cd github/java-spanner-jdbc/ +## Get the directory of the build script +scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) +## cd to the parent directory, i.e. the root of the git repo +cd ${scriptDir}/.. + +# include common functions +source ${scriptDir}/common.sh # Print out Java version java -version echo ${JOB_TYPE} -mvn install -B -V \ - -DskipTests=true \ - -Dclirr.skip=true \ - -Denforcer.skip=true \ - -Dmaven.javadoc.skip=true \ - -Dgcloud.download.skip=true +# attempt to install 3 times with exponential backoff (starting with 10 seconds) +retry_with_backoff 3 10 \ + mvn install -B -V \ + -DskipTests=true \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dmaven.javadoc.skip=true \ + -Dgcloud.download.skip=true # Kokoro job cloud-opensource-java/ubuntu/linkage-monitor-gcs creates this JAR JAR=linkage-monitor-latest-all-deps.jar diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index fc6412701ada..2b2b2658b2a2 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -56,7 +56,9 @@ }, { "packagePatterns": [ - "^com.google.cloud:libraries-bom" + "^com.google.cloud:google-cloud-spanner-jdbc", + "^com.google.cloud:libraries-bom", + "^com.google.cloud.samples:shared-configuration" ], "semanticCommitType": "chore", "semanticCommitScope": "deps" @@ -75,4 +77,4 @@ } ], "semanticCommits": true -} +} \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index ee2cf171cdcd..26294534c126 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,11 +1,11 @@ { - "updateTime": "2020-03-17T19:21:53.454785Z", + "updateTime": "2020-03-25T23:36:35.815671Z", "sources": [ { - "template": { - "name": "java_library", - "origin": "synthtool.gcp", - "version": "2020.2.4" + "git": { + "name": "synthtool", + "remote": "https://github.com/googleapis/synthtool.git", + "sha": "e36822bfa0acb355502dab391b8ef9c4f30208d8" } } ] From b7d275b9b92058e3f0e0193839c043853710e5ec Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 26 Mar 2020 16:57:00 +0100 Subject: [PATCH 0130/1979] deps: update dependency com.google.cloud.samples:shared-configuration to v1.0.13 (#99) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6f6034983db1..3f7671cee9f3 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.12 + 1.0.13 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 48df32823613..5cd7fe3b3488 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.12 + 1.0.13 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a1b09607f2fb..2def81f5ff8b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.12 + 1.0.13 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 013fcbeb3753..2fd8e2342ba5 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.12 + 1.0.13 From 298d90ecfbb32d01e1562820ad7863c1cd01c9e8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2020 16:20:05 +0000 Subject: [PATCH 0131/1979] chore: release 1.15.1-SNAPSHOT (#101) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e522d9534178..b649f82e1c9a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.15.0 + 1.15.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6a0536c84334..a36a2be463d9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.15.0:1.15.0 +google-cloud-spanner-jdbc:1.15.0:1.15.1-SNAPSHOT From 598560803a4cfc7d772940816f13542c5526a568 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 30 Mar 2020 20:40:16 +0200 Subject: [PATCH 0132/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.14 (#106) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud.samples:shared-configuration](https://togithub.com/GoogleCloudPlatform/java-repo-tools) | patch | `1.0.13` -> `1.0.14` | --- ### Release Notes
    GoogleCloudPlatform/java-repo-tools ### [`v1.0.14`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/releases/v1.0.14) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.13...v1.0.14) - Update CheckStyle to 8.31 - Add SpotBugs
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3f7671cee9f3..547ca6886f0e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.13 + 1.0.14 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 5cd7fe3b3488..6211b864c76b 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.13 + 1.0.14 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2def81f5ff8b..541e1a976310 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.13 + 1.0.14 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2fd8e2342ba5..73b74a059ec7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.13 + 1.0.14 From f320df41cc4e0ff85520138d59f5c8550209f963 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Mon, 30 Mar 2020 12:37:18 -0700 Subject: [PATCH 0133/1979] samples: fix samples library versions (#107) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 6 +++--- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 547ca6886f0e..a4e95e0da01c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - + 1.15.0 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 541e1a976310..e5a7b5df8384 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -23,13 +23,14 @@ UTF-8 - + com.google.cloud google-cloud-spanner-jdbc - + 1.15.1-SNAPSHOT + junit @@ -44,7 +45,6 @@ test - diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 73b74a059ec7..7f681b559b49 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - + 4.3.0 pom import From 906e688b8777a466bcce77d364a5062ada167e89 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 1 Apr 2020 21:52:34 +0200 Subject: [PATCH 0134/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v4.4.0 (#108) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `4.3.0` -> `4.4.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7f681b559b49..e3292253f133 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 4.3.0 + 4.4.0 pom import From 2cafa6e620c2e448466fcad94d09c56271f72bbf Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 6 Apr 2020 17:50:17 +0200 Subject: [PATCH 0135/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.15 (#109) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud.samples:shared-configuration](https://togithub.com/GoogleCloudPlatform/java-repo-tools) | patch | `1.0.14` -> `1.0.15` | --- ### Release Notes
    GoogleCloudPlatform/java-repo-tools ### [`v1.0.15`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/releases/v1.0.15) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.14...v1.0.15) - Move some stuff around (in prep for a change to release process) pom.xml's - Add an exclude filter for SpotBugs. (disable the Java 11 surprise) - Don't fail on SpotBugs issues for now - add PMD reporting - Don't fail on PMD issues for now.
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a4e95e0da01c..f4f34919ec38 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.14 + 1.0.15 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 6211b864c76b..9eeb40929ac6 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.14 + 1.0.15 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e5a7b5df8384..3d53f099576b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.14 + 1.0.15 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e3292253f133..24b9752f2957 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.14 + 1.0.15 From a4d750b2c2cbe5edfbaa99e9de990b71e825ecd1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 6 Apr 2020 18:36:34 +0200 Subject: [PATCH 0136/1979] deps: update dependency org.threeten:threetenbp to v1.4.3 (#94) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [org.threeten:threetenbp](https://www.threeten.org/threetenbp) ([source](https://togithub.com/ThreeTen/threetenbp)) | patch | `1.4.1` -> `1.4.3` | --- ### Release Notes
    ThreeTen/threetenbp ### [`v1.4.3`](https://togithub.com/ThreeTen/threetenbp/releases/v1.4.3) [Compare Source](https://togithub.com/ThreeTen/threetenbp/compare/v1.4.2...v1.4.3) See the [change notes](https://www.threeten.org/threetenbp/changes-report.html) for more information. ### [`v1.4.2`](https://togithub.com/ThreeTen/threetenbp/releases/v1.4.2) [Compare Source](https://togithub.com/ThreeTen/threetenbp/compare/v1.4.1...v1.4.2) See the [change notes](https://www.threeten.org/threetenbp/changes-report.html) for more information.
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b649f82e1c9a..9064074bd05f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -67,7 +67,7 @@ 4.13 1.17.0 3.11.4 - 1.4.1 + 1.4.3 1.9.0 1.52.0 2.2 From 64f455e6812974ef837fbab092a4d563e831d35b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 6 Apr 2020 22:08:15 +0200 Subject: [PATCH 0137/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v4.4.1 (#110) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | patch | `4.4.0` -> `4.4.1` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 24b9752f2957..82e273fdf17e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 4.4.0 + 4.4.1 pom import From 340424ffc2a49112c78b44397d8748b9120318e9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 7 Apr 2020 00:56:43 +0200 Subject: [PATCH 0138/1979] deps: update core dependencies (#105) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.api:gax-grpc](https://togithub.com/googleapis/gax-java) | minor | `1.54.0` -> `1.56.0` | | [com.google.api:gax](https://togithub.com/googleapis/gax-java) | minor | `1.54.0` -> `1.56.0` | | [com.google.api:gax-bom](https://togithub.com/googleapis/gax-java) | minor | `1.54.0` -> `1.56.0` | | [io.grpc:grpc-netty-shaded](https://togithub.com/grpc/grpc-java) | minor | `1.27.2` -> `1.28.1` | | [io.grpc:grpc-api](https://togithub.com/grpc/grpc-java) | minor | `1.27.2` -> `1.28.1` | | [io.grpc:grpc-bom](https://togithub.com/grpc/grpc-java) | minor | `1.27.2` -> `1.28.1` | --- ### Release Notes
    googleapis/gax-java ### [`v1.56.0`](https://togithub.com/googleapis/gax-java/releases/v1.56.0) [Compare Source](https://togithub.com/googleapis/gax-java/compare/v1.55.0...v1.56.0) 04-06-2020 10:29 PDT ##### New Features - Add ability to partially update retry settings ([#​993](https://togithub.com/googleapis/gax-java/pull/993)) ##### Dependencies - Update grpc to 1.28.1 ([#​1013](https://togithub.com/googleapis/gax-java/pull/1013)) - Update com.google.api:api-common to 1.9.0 ([#​992](https://togithub.com/googleapis/gax-java/pull/992)) - Add javax.annotations dependency in bazel build to gax-grpc ([#​1000](https://togithub.com/googleapis/gax-java/pull/1000)) ##### Internal / Testing Changes - test: make it easier to debug failures in SettingsTest ([#​994](https://togithub.com/googleapis/gax-java/pull/994)) - build: update dependency gradle.plugin.com.dorongold.plugins:task-tree to v1.5 ([#​995](https://togithub.com/googleapis/gax-java/pull/995)) - test: update dependency com.google.api.grpc:grpc-google-cloud-pubsub-v1 to v1.86.0 ([#​1008](https://togithub.com/googleapis/gax-java/pull/1008)) ### [`v1.55.0`](https://togithub.com/googleapis/gax-java/releases/v1.55.0) [Compare Source](https://togithub.com/googleapis/gax-java/compare/v1.54.0...v1.55.0) 03-27-2020 08:33 PDT ##### New Features - Allow client authors to create their own callable chains ([#​891](https://togithub.com/googleapis/gax-java/pull/891)) ##### Dependencies - Update org.threeten:threetenbp to v1.4.1 ([#​890](https://togithub.com/googleapis/gax-java/pull/890)) ##### Internal / Testing Changes - chore(deps): update dependency com.google.api.grpc:grpc-google-cloud-bigtable-v2 to v1 ([#​953](https://togithub.com/googleapis/gax-java/pull/953)) - chore(deps): update dependency com.google.api.grpc:grpc-google-cloud-pubsub-v1 to v1 ([#​970](https://togithub.com/googleapis/gax-java/pull/970)) - remove unused property ([#​887](https://togithub.com/googleapis/gax-java/pull/887))
    grpc/grpc-java ### [`v1.28.1`](https://togithub.com/grpc/grpc-java/releases/v1.28.1) [Compare Source](https://togithub.com/grpc/grpc-java/compare/v1.28.0...v1.28.1) #### Bug Fixes - xds: implement more clear specifications for locality filtering (allow localities with 0 endpoint, ignore localities with 0 weight, check for locality priority continuity). ([#​6875](https://togithub.com/grpc/grpc-java/issues/6875)) ### [`v1.28.0`](https://togithub.com/grpc/grpc-java/releases/v1.28.0) [Compare Source](https://togithub.com/grpc/grpc-java/compare/v1.27.2...v1.28.0) #### gRPC Java 1.28.0 Release Notes #### API Changes - core: service config parsing now validates the final config object via `LoadBalancerProvider#parseLoadBalancingPolicyConfig`. LoadBalancer developers should use parsed config(`loadBalancingPolicyConfig`) in `ResolvedAddresses` instead of deprecated attribute `io.grpc.LoadBalancer.ATTR_LOAD_BALANCING_CONFIG`. - core: remove stickiness from round robin ([#​6698](https://togithub.com/grpc/grpc-java/issues/6698)) #### Behavioral Changes - core, grpclb: change policy selection strategy for Grpclb policy (take one: eliminate special logic for deciding grpclb policy in core) ([#​6637](https://togithub.com/grpc/grpc-java/issues/6637)) - gRPCLB policy selection is being stabilized according to [this gRFC](https://togithub.com/grpc/proposal/blob/master/A26-grpclb-selection.md). gRPCLB policy will not be automatically selected even if there are SRV addresses resolved. You need to explicitly specify the selection by service config (in TXT records, or via `ManagedChannelBuilder#defaultServiceConfig` or `ManagedChannelBuilder#defaultLoadBalancingPolicy`). #### New Features - This release adds an experimental client side implementation of [xDSv2](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api) APIs. This allows a gRPC client written in Java to receive configuration from an xDSv2 API compatible server and use that configuration to load balance RPCs. In this release, only the virtual host matching and cluster route action is supported. More features will be added in future. #### Bug Fixes - netty: fix a deadlock on start gRPC server ([#​6601](https://togithub.com/grpc/grpc-java/issues/6601)) - netty: negotiated application level protocol is now checked against the correct ALPN list in the SslContext settings - okhttp: fix incorrect connection-level flow control handling at beginning of connection. - alts: Fix using the wrong way of checking if Conscrypt is available ([#​6672](https://togithub.com/grpc/grpc-java/issues/6672)) - grpclb: grpclb can handle empty address from LoadBalancer instead of throwing exception - alts: do not exclude opencensus-api from google-oauth2's transitive dependencies ([#​6607](https://togithub.com/grpc/grpc-java/issues/6607)) - grpc-alts was broken since 1.27.0 release for missing opencensus-api used in google-oauth2. This was due to opencensus-api dependency was eliminated from grpc-core. Now it should be included. #### Documentation - stub,examples: Clarify CallStreamObserver's Javadoc ([#​6561](https://togithub.com/grpc/grpc-java/issues/6561)) #### Dependencies - Bump Netty to 4.1.45.Final and tcnative to 2.0.28.Final - Bump okhttp to 2.7.4 - Bump google-auth-library-credentials and google-auth-library-oauth2-http to 0.20.0 #### Acknowledgements [@​chrisschek](https://togithub.com/chrisschek) [@​cushon](https://togithub.com/cushon) Liam Miller-Cushon [@​elharo](https://togithub.com/elharo) Elliotte Rusty Harold [@​gfelbing](https://togithub.com/gfelbing) Georg Welzel [@​hatahet](https://togithub.com/hatahet) Ziad Hatahet [@​leventov](https://togithub.com/leventov) Roman Leventov [@​sourabhsparkala](https://togithub.com/sourabhsparkala) Sourabh Sarvotham Parkala [@​ZhenLian](https://togithub.com/ZhenLian) Zhen Lian
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :ghost: **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/config-help/issues) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9064074bd05f..c11866277b91 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,10 +58,10 @@ google-cloud-spanner-jdbc - 1.27.2 + 1.28.1 1.30.9 1.93.3 - 1.54.0 + 1.56.0 1.34.2 28.2-android 4.13 From d7cc813bf768b6a2d036df69c7300a4e15e0e757 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 7 Apr 2020 01:44:12 +0200 Subject: [PATCH 0139/1979] deps: update core dependencies to v1.93.4 (#111) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-core](https://togithub.com/googleapis/java-core) | patch | `1.93.3` -> `1.93.4` | | [com.google.cloud:google-cloud-core-bom](https://togithub.com/googleapis/java-core) | patch | `1.93.3` -> `1.93.4` | --- ### Release Notes
    googleapis/java-core ### [`v1.93.4`](https://togithub.com/googleapis/java-core/blob/master/CHANGELOG.md#​1934-httpswwwgithubcomgoogleapisjava-corecomparev1933v1934-2020-04-06) [Compare Source](https://togithub.com/googleapis/java-core/compare/v1.93.3...v1.93.4)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c11866277b91..3be621bae547 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -60,7 +60,7 @@ google-cloud-spanner-jdbc 1.28.1 1.30.9 - 1.93.3 + 1.93.4 1.56.0 1.34.2 28.2-android From 74b3408355a6f3918e711339a0c03a1a9e458d35 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 8 Apr 2020 06:48:39 +0200 Subject: [PATCH 0140/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.5.0 (#112) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | minor | `0.4.0` -> `0.5.0` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.5.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​050-httpswwwgithubcomgoogleapisjava-shared-configcomparev040v050-2020-04-07) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.4.0...v0.5.0) ##### Features - add ban duplicate classes rule ([#​126](https://www.github.com/googleapis/java-shared-config/issues/126)) ([e38a7cc](https://www.github.com/googleapis/java-shared-config/commit/e38a7cc949396f8f5696e62cd060e0c076047b8d)) - add devsite javadoc profile ([#​121](https://www.github.com/googleapis/java-shared-config/issues/121)) ([7f452fb](https://www.github.com/googleapis/java-shared-config/commit/7f452fb6c5704f6ce0f731085479a28fb99ebcb9)) - add maven flatten plugin ([#​127](https://www.github.com/googleapis/java-shared-config/issues/127)) ([fb00799](https://www.github.com/googleapis/java-shared-config/commit/fb00799c416d324d68da5b660a26f7ef595c26d9)) ##### Bug Fixes - declare com.coveo:fmt-maven-plugin version/configuration ([#​90](https://www.github.com/googleapis/java-shared-config/issues/90)) ([5cf71a6](https://www.github.com/googleapis/java-shared-config/commit/5cf71a6ed699907082756e70c2fdee6ad3632f38)) ##### Dependencies - update dependency com.google.cloud.samples:shared-configuration to v1.0.13 ([#​118](https://www.github.com/googleapis/java-shared-config/issues/118)) ([58ae69e](https://www.github.com/googleapis/java-shared-config/commit/58ae69eb5ba037963cdaed0c2b0e30663bc873eb)) - update dependency com.puppycrawl.tools:checkstyle to v8.29 ([f62292d](https://www.github.com/googleapis/java-shared-config/commit/f62292dab75699a75f8a7d499fe2ccfb7ee93783)) - update dependency org.apache.maven.plugins:maven-antrun-plugin to v1.8 ([#​124](https://www.github.com/googleapis/java-shared-config/issues/124)) ([a681536](https://www.github.com/googleapis/java-shared-config/commit/a68153643400c3f3b5c5959cda4dc3b552336427)) - update dependency org.apache.maven.plugins:maven-dependency-plugin to v3.1.2 ([#​107](https://www.github.com/googleapis/java-shared-config/issues/107)) ([c9b096b](https://www.github.com/googleapis/java-shared-config/commit/c9b096b81b1f4f8dc2d1302f259f0321722e1ca5)) - update dependency org.apache.maven.plugins:maven-site-plugin to v3.9.0 ([#​103](https://www.github.com/googleapis/java-shared-config/issues/103)) ([abe7140](https://www.github.com/googleapis/java-shared-config/commit/abe714060e858c70a83888fb34438c45d97b1168)) - update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.1.0 ([#​101](https://www.github.com/googleapis/java-shared-config/issues/101)) ([ac69572](https://www.github.com/googleapis/java-shared-config/commit/ac69572be76e4462fdf65fa6e7f0935c3d51d827))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3be621bae547..1efa2d91a92e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.4.0 + 0.5.0 From 07b8002a048a7a09049789570ead34f32edf927b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 14 Apr 2020 20:28:41 +0200 Subject: [PATCH 0141/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v5 (#116) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `4.4.1` -> `5.1.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 82e273fdf17e..1616d36b4415 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 4.4.1 + 5.1.0 pom import From cf535573956c209b389a018913c068bdb827f5c3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 16 Apr 2020 17:52:20 +0200 Subject: [PATCH 0142/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.16 (#118) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud.samples:shared-configuration](https://togithub.com/GoogleCloudPlatform/java-repo-tools) | patch | `1.0.15` -> `1.0.16` | --- ### Release Notes
    GoogleCloudPlatform/java-repo-tools ### [`v1.0.16`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/releases/v1.0.16) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.15...v1.0.16) Add a few SpotBugs exclusions: - `RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE` - existing - codegen bug - `UPM_UNCALLED_PRIVATE_METHOD` - probably SpotBug issue - `NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE` - likely SpotBug issue - `CLI_CONSTANT_LIST_INDEX` - style issue particular to our samples - `OBL_UNSATISFIED_OBLIGATION` - issue for SQL clients
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f4f34919ec38..53a9f8f36b5c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.15 + 1.0.16 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 9eeb40929ac6..1cc1b52b3c71 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.15 + 1.0.16 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3d53f099576b..edd188ea794d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.15 + 1.0.16 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 1616d36b4415..943372639841 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.15 + 1.0.16 From 52a6d2e1a115508d212d1b5890f8af022ee103df Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 17 Apr 2020 08:50:00 +0200 Subject: [PATCH 0143/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.17 (#120) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud.samples:shared-configuration](https://togithub.com/GoogleCloudPlatform/java-repo-tools) | patch | `1.0.16` -> `1.0.17` | --- ### Release Notes
    GoogleCloudPlatform/java-repo-tools ### [`v1.0.17`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/releases/v1.0.17) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.16...v1.0.17) - require -P lint Lets not burden customers with our development rules. - Move Checkstyle, ErrorProne, PMD, and SpotBugs to only run w/ -P lint - Update the Readme - spotbugs-annotations 4.0.2
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 53a9f8f36b5c..26df0156453c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.16 + 1.0.17 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 1cc1b52b3c71..db021acdaa70 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.16 + 1.0.17 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index edd188ea794d..79a9a78fcdd1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.16 + 1.0.17 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 943372639841..e7a558398af3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.16 + 1.0.17 From f65beae21ff1341063d35b339b739a10e665ac63 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 24 Apr 2020 21:10:17 +0200 Subject: [PATCH 0144/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v5.2.0 (#123) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `5.1.0` -> `5.2.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e7a558398af3..f6cc6f431106 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 5.1.0 + 5.2.0 pom import From 68d6221522ab3e0e1b0c0b6f4313b3b127273bc3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 29 Apr 2020 01:08:32 +0200 Subject: [PATCH 0145/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v5.3.0 (#126) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `5.2.0` -> `5.3.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f6cc6f431106..3c022fd47183 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 5.2.0 + 5.3.0 pom import From dc6545c93ca1773aac77a694146d14c8076dd536 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 5 May 2020 05:38:04 +0200 Subject: [PATCH 0146/1979] deps: update dependency com.google.api.grpc:proto-google-common-protos to v1.18.0 (#128) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.api.grpc:proto-google-common-protos](https://togithub.com/googleapis/java-iam) | minor | `1.17.0` -> `1.18.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1efa2d91a92e..8759681ee3ec 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -65,7 +65,7 @@ 1.34.2 28.2-android 4.13 - 1.17.0 + 1.18.0 3.11.4 1.4.3 1.9.0 From 680279f8c695be7ecb22ae004f2abf219cf543a4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 May 2020 12:08:04 +0200 Subject: [PATCH 0147/1979] deps: update core dependencies to v29 (major) (#114) This PR contains the following updates: | Package | Update | Change | |---|---|---| | com.google.guava:guava | major | `28.2-android` -> `29.0-android` | | [com.google.guava:guava-bom](https://togithub.com/google/guava) | major | `28.2-android` -> `29.0-android` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8759681ee3ec..2e394a26afff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -63,7 +63,7 @@ 1.93.4 1.56.0 1.34.2 - 28.2-android + 29.0-android 4.13 1.18.0 3.11.4 From 4b83981714ee86939136f90c1410ff8d8a0e11b0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 May 2020 12:12:29 +0200 Subject: [PATCH 0148/1979] deps: update core dependencies to v1.29.0 (#121) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2e394a26afff..d99ce5e8c5f3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 1.28.1 + 1.29.0 1.30.9 1.93.4 1.56.0 From edf4e7a77dfcd90f3978cafe49110c0dea75ae89 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 May 2020 12:38:05 +0200 Subject: [PATCH 0149/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.2.3 (#115) This PR contains the following updates: | Package | Update | Change | |---|---|---| | org.apache.maven.plugins:maven-shade-plugin | patch | `3.2.2` -> `3.2.3` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d99ce5e8c5f3..e821fb0793ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.2 + 3.2.3 From f59804d4ab355f4fc8749154f0266a4ac9373ad7 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 12 May 2020 10:09:38 -0700 Subject: [PATCH 0150/1979] chore: update common templates (#119) * build(java): fix retry_with_backoff when -e option set (#475) Source-Author: Jeff Ching Source-Date: Wed Apr 8 14:01:08 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: bd69a2aa7b70875f3c988e269706b22fefbef40e Source-Link: https://github.com/googleapis/synthtool/commit/bd69a2aa7b70875f3c988e269706b22fefbef40e * build(java): fix nightly integration test config to run integrations (#465) This was only running the units. Source-Author: Jeff Ching Source-Date: Wed Apr 8 14:06:04 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: c7e0e517d7f46f77bebd27da2e5afcaa6eee7e25 Source-Link: https://github.com/googleapis/synthtool/commit/c7e0e517d7f46f77bebd27da2e5afcaa6eee7e25 * ci: add dependency list completeness check (#490) Source-Author: Stephanie Wang Source-Date: Mon Apr 13 18:30:27 2020 -0400 Source-Repo: googleapis/synthtool Source-Sha: 3df869dd6eb546ef13beeb7a9efa6ee0226afafd Source-Link: https://github.com/googleapis/synthtool/commit/3df869dd6eb546ef13beeb7a9efa6ee0226afafd * build(java): set GOOGLE_CLOUD_PROJECT env for samples/integration tests (#484) * build(java): set GOOGLE_CLOUD_PROJECT env variable for samples/integration tests * ci: use java-docs-samples-testing for sample tests Source-Author: Jeff Ching Source-Date: Mon Apr 13 16:24:21 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: 52638600f387deb98efb5f9c85fec39e82aa9052 Source-Link: https://github.com/googleapis/synthtool/commit/52638600f387deb98efb5f9c85fec39e82aa9052 --- java-spanner-jdbc/.kokoro/common.sh | 19 +++++++- java-spanner-jdbc/.kokoro/dependencies.sh | 48 +++++++++++++++++++ .../.kokoro/nightly/integration.cfg | 20 ++++++++ java-spanner-jdbc/.kokoro/nightly/samples.cfg | 8 +++- .../.kokoro/presubmit/integration.cfg | 14 ++++-- .../.kokoro/presubmit/samples.cfg | 14 ++++-- java-spanner-jdbc/synth.metadata | 10 +++- 7 files changed, 120 insertions(+), 13 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/common.sh b/java-spanner-jdbc/.kokoro/common.sh index a3bbc5f67963..a8d0ea04d37d 100644 --- a/java-spanner-jdbc/.kokoro/common.sh +++ b/java-spanner-jdbc/.kokoro/common.sh @@ -13,18 +13,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -# set -eo pipefail - function retry_with_backoff { attempts_left=$1 sleep_seconds=$2 shift 2 command=$@ + + # store current flag state + flags=$- + + # allow a failures to continue + set +e echo "${command}" ${command} exit_code=$? + # restore "e" flag + if [[ ${flags} =~ e ]] + then set -e + else set +e + fi + if [[ $exit_code == 0 ]] then return 0 @@ -42,3 +52,8 @@ function retry_with_backoff { return $exit_code } + +## Helper functionss +function now() { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n'; } +function msg() { println "$*" >&2; } +function println() { printf '%s\n' "$(now) $*"; } \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 0aade871ce10..cf3bb4347e01 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -36,3 +36,51 @@ retry_with_backoff 3 10 \ -Dclirr.skip=true mvn -B dependency:analyze -DfailOnWarning=true + +echo "****************** DEPENDENCY LIST COMPLETENESS CHECK *******************" +## Run dependency list completeness check +function completenessCheck() { + # Output dep list with compile scope generated using the original pom + msg "Generating dependency list using original pom..." + mvn dependency:list -f pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | grep -v ':test$' >.org-list.txt + + # Output dep list generated using the flattened pom (test scope deps are ommitted) + msg "Generating dependency list using flattened pom..." + mvn dependency:list -f .flattened-pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' >.new-list.txt + + # Compare two dependency lists + msg "Comparing dependency lists..." + diff .org-list.txt .new-list.txt >.diff.txt + if [[ $? == 0 ]] + then + msg "Success. No diff!" + else + msg "Diff found. See below: " + msg "You can also check .diff.txt file located in $1." + cat .diff.txt + return 1 + fi +} + +# Allow failures to continue running the script +set +e + +error_count=0 +for path in $(find -name ".flattened-pom.xml") +do + # Check flattened pom in each dir that contains it for completeness + dir=$(dirname "$path") + pushd "$dir" + completenessCheck "$dir" + error_count=$(($error_count + $?)) + popd +done + +if [[ $error_count == 0 ]] +then + msg "All checks passed." + exit 0 +else + msg "Errors found. See log statements above." + exit 1 +fi diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index 8bf59c02edd6..40c4abb7bf08 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -6,11 +6,31 @@ env_vars: { value: "gcr.io/cloud-devrel-kokoro-resources/java8" } +env_vars: { + key: "JOB_TYPE" + value: "integration" +} +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + env_vars: { key: "ENABLE_BUILD_COP" value: "true" } +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" +} + before_action { fetch_keystore { keystore_resource { diff --git a/java-spanner-jdbc/.kokoro/nightly/samples.cfg b/java-spanner-jdbc/.kokoro/nightly/samples.cfg index b4b051cd016f..20aabd55de11 100644 --- a/java-spanner-jdbc/.kokoro/nightly/samples.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/samples.cfg @@ -11,9 +11,15 @@ env_vars: { value: "samples" } +# TODO: remove this after we've migrated all tests and scripts env_vars: { key: "GCLOUD_PROJECT" - value: "gcloud-devel" + value: "java-docs-samples-testing" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "java-docs-samples-testing" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg index 141f90c13c56..522e5b10101c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -11,14 +11,20 @@ env_vars: { value: "integration" } +# TODO: remove this after we've migrated all tests and scripts env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" + key: "GCLOUD_PROJECT" + value: "gcloud-devel" } env_vars: { - key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" } before_action { diff --git a/java-spanner-jdbc/.kokoro/presubmit/samples.cfg b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg index fa7b493d0b5c..1171aead01f0 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/samples.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg @@ -11,14 +11,20 @@ env_vars: { value: "samples" } +# TODO: remove this after we've migrated all tests and scripts env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" + key: "GCLOUD_PROJECT" + value: "java-docs-samples-testing" } env_vars: { - key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + key: "GOOGLE_CLOUD_PROJECT" + value: "java-docs-samples-testing" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "keystore/73713_java_it_service_account" } before_action { diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 26294534c126..5afed4c25367 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -1,11 +1,17 @@ { - "updateTime": "2020-03-25T23:36:35.815671Z", "sources": [ + { + "git": { + "name": ".", + "remote": "https://github.com/googleapis/java-spanner-jdbc.git", + "sha": "a8caef202d88e497c474a69eb7abe0b4096a1b0e" + } + }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "e36822bfa0acb355502dab391b8ef9c4f30208d8" + "sha": "52638600f387deb98efb5f9c85fec39e82aa9052" } } ] From 85ca66a4b0ad61f64a0633f604a606de960a57ed Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 13 May 2020 16:22:41 -0700 Subject: [PATCH 0151/1979] chore: regenerate common templates (#129) * ci(java): switch to GitHub Actions (#533) * ci: switch to GitHub Actions * update based on comment Source-Author: Stephanie Wang Source-Date: Mon May 11 12:54:00 2020 -0400 Source-Repo: googleapis/synthtool Source-Sha: 55cdc844877d97139f25004229842624a6a86a02 Source-Link: https://github.com/googleapis/synthtool/commit/55cdc844877d97139f25004229842624a6a86a02 * chore: move ci.yaml to workflows dir (#535) Source-Author: Stephanie Wang Source-Date: Mon May 11 16:24:04 2020 -0400 Source-Repo: googleapis/synthtool Source-Sha: 98c50772ec23295c64cf0d2ddf199ea52961fd4c Source-Link: https://github.com/googleapis/synthtool/commit/98c50772ec23295c64cf0d2ddf199ea52961fd4c * docs: update CONTRIBUTING.md to include code formatting (#534) Co-authored-by: Jeff Ching Co-authored-by: Jeffrey Rennie Source-Author: Brian Chen Source-Date: Tue May 12 10:24:59 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: 5b48b0716a36ca069db3038da7e205c87a22ed19 Source-Link: https://github.com/googleapis/synthtool/commit/5b48b0716a36ca069db3038da7e205c87a22ed19 --- java-spanner-jdbc/.github/workflows/ci.yaml | 76 +++++++++++++++++++++ java-spanner-jdbc/.kokoro/build.bat | 2 +- java-spanner-jdbc/CONTRIBUTING.md | 11 ++- java-spanner-jdbc/synth.metadata | 4 +- 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/ci.yaml diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml new file mode 100644 index 000000000000..445b4bf82ffd --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -0,0 +1,76 @@ +on: + push: + branches: + - master + pull_request: +name: ci +jobs: + units: + runs-on: ubuntu-latest + strategy: + matrix: + java: [7, 8, 11] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: ${{matrix.java}} + - run: java -version + - run: .kokoro/build.sh + env: + JOB_TYPE: test + - name: coverage + uses: codecov/codecov-action@v1 + with: + name: actions ${{matrix.java}} + windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/build.bat + env: + JOB_TYPE: test + dependencies: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/dependencies.sh + linkage-monitor: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/linkage-monitor.sh + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/build.sh + env: + JOB_TYPE: lint + clirr: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/build.sh + env: + JOB_TYPE: clirr \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/build.bat b/java-spanner-jdbc/.kokoro/build.bat index 680ad2804149..05826ad93fe8 100644 --- a/java-spanner-jdbc/.kokoro/build.bat +++ b/java-spanner-jdbc/.kokoro/build.bat @@ -1,3 +1,3 @@ :: See documentation in type-shell-output.bat -"C:\Program Files\Git\bin\bash.exe" github/java-spanner-jdbc/.kokoro/build.sh +"C:\Program Files\Git\bin\bash.exe" %~dp0build.sh diff --git a/java-spanner-jdbc/CONTRIBUTING.md b/java-spanner-jdbc/CONTRIBUTING.md index 085021ddec26..f2dbdee06bc3 100644 --- a/java-spanner-jdbc/CONTRIBUTING.md +++ b/java-spanner-jdbc/CONTRIBUTING.md @@ -99,7 +99,16 @@ mvn -Penable-samples clean verify ``` 2. [Activate](#profile-activation) the profile. -3. Define your samples in a normal Maven project in the `samples/` directory +3. Define your samples in a normal Maven project in the `samples/` directory. + +### Code Formatting + +Code in this repo is formatted with +[google-java-format](https://github.com/google/google-java-format). +To run formatting on your project, you can run: +``` +mvn com.coveo:fmt-maven-plugin:format +``` ### Profile Activation diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 5afed4c25367..0faa79cc2fdb 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a8caef202d88e497c474a69eb7abe0b4096a1b0e" + "sha": "839e4dcc0ab9b1044cd0534195a44c37c2e37f14" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "52638600f387deb98efb5f9c85fec39e82aa9052" + "sha": "5b48b0716a36ca069db3038da7e205c87a22ed19" } } ] From 5b49c2d48005f05dcb3ee6f57ddb173cddaf12e9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 16 May 2020 18:01:38 +0200 Subject: [PATCH 0152/1979] deps: update dependency org.threeten:threetenbp to v1.4.4 (#124) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e821fb0793ab..1757871a9a21 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -67,7 +67,7 @@ 4.13 1.18.0 3.11.4 - 1.4.3 + 1.4.4 1.9.0 1.52.0 2.2 From d7b35e82e5714cb3593b92cd94cbdaad100a72f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 19 May 2020 04:52:41 +0200 Subject: [PATCH 0153/1979] fix: test allowed a too old staleness (#131) --- .../spanner/jdbc/ITReadOnlySpannerTest.sql | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql index 0dc0410757ae..6a8df6a58b9f 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITReadOnlySpannerTest.sql @@ -20,9 +20,11 @@ NEW_CONNECTION; @EXPECT RESULT_SET 'READONLY',true SHOW VARIABLE READONLY; +-- Check initial contents. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; +-- Check initial contents. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -72,12 +74,14 @@ SELECT CURRENT_TIMESTAMP(); SET READ_ONLY_STALENESS = 'READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; +-- Check SELECT with READ_TIMESTAMP @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @PUT 'READ_TIMESTAMP1' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with READ_TIMESTAMP @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -95,12 +99,14 @@ SELECT CURRENT_TIMESTAMP(); SET READ_ONLY_STALENESS = 'MIN_READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; +-- Check SELECT with MIN_READ_TIMESTAMP @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with MIN_READ_TIMESTAMP @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -113,12 +119,14 @@ NEW_CONNECTION; SET READ_ONLY_STALENESS = 'EXACT_STALENESS 1ms'; +-- Check SELECT with EXACT_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with EXACT_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -127,16 +135,18 @@ SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; ---TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS) +--TimestampBound.ofMaxStaleness(100, TimeUnit.MILLISECONDS) -SET READ_ONLY_STALENESS = 'MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; +-- Check SELECT with MAX_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with MAX_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -149,12 +159,14 @@ NEW_CONNECTION; SET READ_ONLY_STALENESS = 'STRONG'; +-- Check SELECT with STRONG @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with STRONG @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -178,12 +190,14 @@ SET AUTOCOMMIT = FALSE; SET READ_ONLY_STALENESS = 'READ_TIMESTAMP %%CURRENT_TIMESTAMP%%'; +-- Check SELECT with READ_TIMESTAMP in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @PUT 'READ_TIMESTAMP1' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with READ_TIMESTAMP in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -213,12 +227,14 @@ SET AUTOCOMMIT = FALSE; SET READ_ONLY_STALENESS = 'EXACT_STALENESS 100ms'; +-- Check SELECT with EXACT_STALENESS in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @PUT 'READ_TIMESTAMP1' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with EXACT_STALENESS in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; @@ -231,11 +247,11 @@ COMMIT; NEW_CONNECTION; ---TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS) +--TimestampBound.ofMaxStaleness(100, TimeUnit.MILLISECONDS) SET AUTOCOMMIT = FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS = 'MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; NEW_CONNECTION; @@ -244,12 +260,14 @@ SET AUTOCOMMIT = FALSE; SET READ_ONLY_STALENESS = 'STRONG'; +-- Check SELECT with STRONG in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 1000 AS EXPECTED FROM NUMBERS; @PUT 'READ_TIMESTAMP1' SHOW VARIABLE READ_TIMESTAMP; +-- Check SELECT with STRONG in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS ACTUAL, 168 AS EXPECTED FROM PRIME_NUMBERS; From 643840daf6fa1a818eb7dfc90c2474a0dfbe825d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 19 May 2020 23:46:17 +0200 Subject: [PATCH 0154/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v5.4.0 (#134) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `5.3.0` -> `5.4.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 3c022fd47183..27c094d84d91 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 5.3.0 + 5.4.0 pom import From 5ecf353870483df0124448e1864a22bb4e1de47c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 May 2020 01:06:19 +0200 Subject: [PATCH 0155/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.6.0 (#135) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | minor | `0.5.0` -> `0.6.0` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.6.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​060-httpswwwgithubcomgoogleapisjava-shared-configcomparev050v060-2020-05-19) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.5.0...v0.6.0) ##### Features - add new configuration necessary to support auto-value ([#​136](https://www.github.com/googleapis/java-shared-config/issues/136)) ([c14689b](https://www.github.com/googleapis/java-shared-config/commit/c14689b8791c173687f719d73156a989aedd7ba6))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1757871a9a21..0f6bf42537a2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.5.0 + 0.6.0 From d50ca424954bd590fc2eb8c0ce83169954ef02ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 27 May 2020 16:36:51 +0200 Subject: [PATCH 0156/1979] refactor: use Connection API in client lib (#133) * refactor: use Connection API in client lib The generic Connection API has been moved to the client library. The JDBC driver still contained its own copy of this API. This change removes this own API and instead uses the one in the client library. * deps: remove unused dependencies * deps: revert to libraries-bom 5.2.0 * deps: exclude grpc-api to prevent version conflicts * deps: more exclusions * fix: exclude dependency to prevent conflicts --- .../clirr-ignored-differences.xml | 45 + java-spanner-jdbc/pom.xml | 179 +- .../spanner/jdbc/AbstractBaseUnitOfWork.java | 162 -- .../spanner/jdbc/AbstractJdbcConnection.java | 7 +- .../spanner/jdbc/AbstractJdbcStatement.java | 3 +- .../jdbc/AbstractMultiUseTransaction.java | 96 - .../cloud/spanner/jdbc/AnalyzeMode.java | 52 - .../cloud/spanner/jdbc/AutocommitDmlMode.java | 42 - .../cloud/spanner/jdbc/ChecksumResultSet.java | 355 --- .../spanner/jdbc/ClientSideStatement.java | 63 - .../jdbc/ClientSideStatementExecutor.java | 54 - .../spanner/jdbc/ClientSideStatementImpl.java | 217 -- .../ClientSideStatementNoParamExecutor.java | 45 - .../jdbc/ClientSideStatementSetExecutor.java | 101 - .../ClientSideStatementValueConverter.java | 35 - .../ClientSideStatementValueConverters.java | 257 --- .../spanner/jdbc/ClientSideStatements.java | 51 - .../jdbc/CloudSpannerJdbcConnection.java | 36 +- .../google/cloud/spanner/jdbc/Connection.java | 727 ------ .../cloud/spanner/jdbc/ConnectionImpl.java | 1018 --------- .../cloud/spanner/jdbc/ConnectionOptions.java | 666 ------ .../spanner/jdbc/ConnectionPreconditions.java | 45 - .../jdbc/ConnectionStatementExecutor.java | 82 - .../jdbc/ConnectionStatementExecutorImpl.java | 247 --- .../spanner/jdbc/CredentialsService.java | 89 - .../google/cloud/spanner/jdbc/DdlBatch.java | 303 --- .../google/cloud/spanner/jdbc/DdlClient.java | 91 - .../spanner/jdbc/DirectExecuteResultSet.java | 365 ---- .../google/cloud/spanner/jdbc/DmlBatch.java | 193 -- .../cloud/spanner/jdbc/FailedBatchUpdate.java | 83 - .../cloud/spanner/jdbc/FailedQuery.java | 82 - .../cloud/spanner/jdbc/FailedUpdate.java | 67 - .../cloud/spanner/jdbc/JdbcConnection.java | 87 + .../cloud/spanner/jdbc/JdbcConstants.java | 1 - .../cloud/spanner/jdbc/JdbcDataSource.java | 1 + .../spanner/jdbc/JdbcDatabaseMetaData.java | 2 +- .../google/cloud/spanner/jdbc/JdbcDriver.java | 3 +- .../spanner/jdbc/JdbcPreparedStatement.java | 1 + .../cloud/spanner/jdbc/JdbcStatement.java | 2 + .../spanner/jdbc/ReadOnlyStalenessUtil.java | 261 --- .../spanner/jdbc/ReadOnlyTransaction.java | 178 -- .../spanner/jdbc/ReadWriteTransaction.java | 762 ------- .../jdbc/ReplaceableForwardingResultSet.java | 352 --- .../spanner/jdbc/RetriableBatchUpdate.java | 69 - .../cloud/spanner/jdbc/RetriableUpdate.java | 64 - .../spanner/jdbc/SingleUseTransaction.java | 505 ----- .../cloud/spanner/jdbc/SpannerPool.java | 413 +--- .../jdbc/StatementExecutionInterceptor.java | 40 - .../cloud/spanner/jdbc/StatementExecutor.java | 188 -- .../cloud/spanner/jdbc/StatementParser.java | 458 ---- .../cloud/spanner/jdbc/StatementResult.java | 103 - .../spanner/jdbc/StatementResultImpl.java | 187 -- .../cloud/spanner/jdbc/TransactionMode.java | 46 - .../jdbc/TransactionRetryListener.java | 22 +- .../google/cloud/spanner/jdbc/UnitOfWork.java | 182 -- .../cloud/spanner/jdbc/AbortedTest.java | 74 - .../jdbc/AbstractConnectionImplTest.java | 963 -------- .../spanner/jdbc/AbstractMockServerTest.java | 186 -- .../jdbc/AbstractSqlScriptVerifier.java | 453 ---- .../jdbc/AutocommitDmlModeConverterTest.java | 58 - .../spanner/jdbc/AutocommitDmlModeTest.java | 115 - .../spanner/jdbc/BooleanConverterTest.java | 51 - .../jdbc/ClientSideStatementsTest.java | 241 -- .../ConnectionImplAutocommitReadOnlyTest.java | 914 -------- ...ConnectionImplAutocommitReadWriteTest.java | 1325 ----------- .../ConnectionImplGeneratedSqlScriptTest.java | 124 -- .../spanner/jdbc/ConnectionImplTest.java | 1261 ----------- ...nnectionImplTransactionalReadOnlyTest.java | 1204 ---------- ...nectionImplTransactionalReadWriteTest.java | 1945 ----------------- .../spanner/jdbc/ConnectionOptionsTest.java | 389 ---- .../jdbc/ConnectionStatementExecutorTest.java | 199 -- ...nnectionStatementWithNoParametersTest.java | 167 -- ...nnectionStatementWithOneParameterTest.java | 180 -- .../cloud/spanner/jdbc/ConnectionTest.java | 98 - .../spanner/jdbc/CredentialsServiceTest.java | 85 - .../cloud/spanner/jdbc/DdlBatchTest.java | 544 ----- .../cloud/spanner/jdbc/DdlClientTest.java | 69 - .../jdbc/DirectExecuteResultSetTest.java | 255 --- .../cloud/spanner/jdbc/DmlBatchTest.java | 163 -- .../spanner/jdbc/DurationConverterTest.java | 86 - .../spanner/jdbc/ITAbstractJdbcTest.java | 7 +- .../spanner/jdbc/ITAbstractSpannerTest.java | 320 --- .../cloud/spanner/jdbc/ITConnectionImpl.java | 25 - .../jdbc/JdbcAbortedTransactionTest.java | 5 +- .../JdbcConnectionGeneratedSqlScriptTest.java | 9 +- .../spanner/jdbc/JdbcConnectionTest.java | 9 +- .../jdbc/JdbcDatabaseMetaDataTest.java | 2 + ...cDatabaseMetaDataWithMockedServerTest.java | 2 + .../cloud/spanner/jdbc/JdbcDriverTest.java | 62 +- .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 1 + .../spanner/jdbc/JdbcParameterStoreTest.java | 17 +- .../jdbc/JdbcPreparedStatementTest.java | 1 + .../spanner/jdbc/JdbcQueryOptionsTest.java | 1 + .../spanner/jdbc/JdbcSqlScriptVerifier.java | 21 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 5 +- .../spanner/jdbc/JdbcTypeConverterTest.java | 1 + .../jdbc/RandomResultSetGenerator.java | 166 -- .../jdbc/ReadOnlyStalenessConverterTest.java | 166 -- .../spanner/jdbc/ReadOnlyStalenessTest.java | 199 -- .../jdbc/ReadOnlyStalenessUtilTest.java | 170 -- .../spanner/jdbc/ReadOnlyTransactionTest.java | 403 ---- .../jdbc/ReadWriteTransactionTest.java | 581 ----- .../ReplaceableForwardingResultSetTest.java | 310 --- .../SetReadOnlyStalenessSqlScriptTest.java | 47 - .../SetStatementTimeoutSqlScriptTest.java | 47 - .../jdbc/SingleUseTransactionTest.java | 740 ------- .../spanner/jdbc/SpannerExceptionMatcher.java | 65 - .../cloud/spanner/jdbc/SpannerPoolTest.java | 400 ---- .../cloud/spanner/jdbc/SqlScriptVerifier.java | 185 -- .../spanner/jdbc/SqlTestScriptsGenerator.java | 27 - .../spanner/jdbc/StatementParserTest.java | 723 ------ .../spanner/jdbc/StatementResultImplTest.java | 177 -- .../spanner/jdbc/StatementTimeoutTest.java | 1192 ---------- .../jdbc/TransactionModeConverterTest.java | 71 - .../spanner/jdbc/it/ITBulkConnectionTest.java | 88 - .../cloud/spanner/jdbc/it/ITDdlTest.java | 37 - .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 2 +- .../jdbc/it/ITJdbcQueryOptionsTest.java | 2 +- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 2 +- .../it/ITJdbcReadWriteAutocommitTest.java | 2 +- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 2 +- .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 2 +- .../jdbc/it/ITReadOnlySpannerTest.java | 227 -- .../it/ITReadWriteAutocommitSpannerTest.java | 179 -- .../spanner/jdbc/it/ITSqlMusicScriptTest.java | 205 -- .../spanner/jdbc/it/ITSqlScriptTest.java | 182 -- .../jdbc/it/ITTransactionModeTest.java | 187 -- .../jdbc/it/ITTransactionRetryTest.java | 1567 ------------- 128 files changed, 353 insertions(+), 29422 deletions(-) create mode 100644 java-spanner-jdbc/clirr-ignored-differences.xml delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml new file mode 100644 index 000000000000..cfa113659dca --- /dev/null +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -0,0 +1,45 @@ + + + + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean removeTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + java.util.Iterator getTransactionRetryListenersFromConnection() + + + 8001 + com/google/cloud/spanner/jdbc/ConnectionOptions$Builder + + + 8001 + com/google/cloud/spanner/jdbc/ConnectionOptions$ConnectionProperty + + + 8001 + com/google/cloud/spanner/jdbc/StatementResult$ClientSideStatementType + + + 8001 + com/google/cloud/spanner/jdbc/StatementResult$ResultType + + + 8001 + com/google/cloud/spanner/jdbc/UnitOfWork$Type + + + 8001 + com/google/cloud/spanner/jdbc/UnitOfWork$UnitOfWorkState + + diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0f6bf42537a2..262795eaaa00 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,225 +58,128 @@ google-cloud-spanner-jdbc - 1.29.0 - 1.30.9 - 1.93.4 - 1.56.0 - 1.34.2 - 29.0-android 4.13 - 1.18.0 - 3.11.4 + 1.53.0 + 3.0.2 1.4.4 - 1.9.0 - 1.52.0 + 1.0.1 + 1.10.19 2.2 - 2.3.4 - 0.20.0 - - io.grpc - grpc-bom - ${grpc.version} - pom - import - - - com.google.api-client - google-api-client-bom - ${api-client.version} - pom - import - com.google.cloud - google-cloud-core-bom - ${google.core.version} + libraries-bom + 5.3.0 pom import - - com.google.api - gax-bom - ${gax.version} - pom - import - - - com.google.http-client - google-http-client-bom - ${http-client-bom.version} - pom - import - - - com.google.guava - guava-bom - ${guava.version} - pom - import - - - com.google.auth - google-auth-library-bom - ${google.auth.version} - pom - import - - - com.google.errorprone - error_prone_annotations - ${error-prone.version} - - - com.google.protobuf - protobuf-java - ${protobuf.version} - - - org.hamcrest - hamcrest-core - ${hamcrest.version} - test - - + + io.grpc + grpc-api + + + com.google.cloud + google-cloud-core-grpc + com.google.api.grpc proto-google-common-protos - ${google.common-protos.version} com.google.cloud google-cloud-spanner - ${spanner.version} + + + + io.grpc + grpc-api + + + com.google.cloud + google-cloud-core-grpc + + + + + com.google.api.grpc + proto-google-cloud-spanner-v1 com.google.protobuf protobuf-java - ${protobuf.version} com.google.guava guava - ${guava.version} - - - com.google.api - gax - ${gax.version} org.threeten threetenbp ${threeten.version} - - io.grpc - grpc-api - ${grpc.version} - io.grpc grpc-netty-shaded - ${grpc.version} com.google.api api-common - ${google.api-common.version} com.google.code.findbugs jsr305 - 3.0.2 + ${findbugs.version} com.google.http-client google-http-client - ${http-client-bom.version} com.google.auth google-auth-library-oauth2-http - ${google.auth.version} com.google.cloud google-cloud-core - ${google.core.version} - - - com.google.code.gson - gson - 2.8.6 com.google.auth google-auth-library-credentials - ${google.auth.version} - - - org.apache.commons - commons-lang3 - 3.5 - - - com.google.api.grpc - proto-google-cloud-spanner-v1 - ${spanner.version} - - - com.google.api.grpc - proto-google-cloud-spanner-admin-database-v1 - ${spanner.version} - - - com.google.protobuf - protobuf-java-util - ${protobuf.version} + com.google.cloud google-cloud-spanner - ${spanner.version} + ${spanner.test.version} test-jar test com.google.api.grpc grpc-google-cloud-spanner-v1 - ${spanner.version} test com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - ${spanner.version} test com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - ${spanner.version} test com.google.truth truth - 1.0.1 - test - - - org.mockito - mockito-core - 1.10.19 + ${truth.version} test @@ -285,6 +188,18 @@ ${hamcrest.version} test + + org.mockito + mockito-core + ${mockito.version} + test + + + org.hamcrest + hamcrest-core + + + junit junit @@ -294,7 +209,6 @@ com.google.api gax-grpc - ${gax.version} testlib test @@ -304,7 +218,6 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 com.google.cloud.spanner.IntegrationTest sponge_log @@ -313,7 +226,6 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M4 com.google.cloud.spanner.GceTestEnvConfig @@ -340,6 +252,7 @@ com.google.api:gax-grpc + com.google.cloud:google-cloud-core-grpc com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java deleted file mode 100644 index 099fd36e3579..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractBaseUnitOfWork.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.StatementExecutor.StatementTimeout; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import javax.annotation.concurrent.GuardedBy; - -/** Base for all {@link Connection}-based transactions and batches. */ -abstract class AbstractBaseUnitOfWork implements UnitOfWork { - private final StatementExecutor statementExecutor; - private final StatementTimeout statementTimeout; - - /** - * The {@link Future} that monitors the result of the statement currently being executed for this - * unit of work. - */ - @GuardedBy("this") - private Future currentlyRunningStatementFuture = null; - - enum InterceptorsUsage { - INVOKE_INTERCEPTORS, - IGNORE_INTERCEPTORS; - } - - abstract static class Builder, T extends AbstractBaseUnitOfWork> { - private StatementExecutor statementExecutor; - private StatementTimeout statementTimeout = new StatementTimeout(); - - Builder() {} - - @SuppressWarnings("unchecked") - B self() { - return (B) this; - } - - B withStatementExecutor(StatementExecutor executor) { - Preconditions.checkNotNull(executor); - this.statementExecutor = executor; - return self(); - } - - B setStatementTimeout(StatementTimeout timeout) { - Preconditions.checkNotNull(timeout); - this.statementTimeout = timeout; - return self(); - } - - abstract T build(); - } - - AbstractBaseUnitOfWork(Builder builder) { - Preconditions.checkState(builder.statementExecutor != null, "No statement executor specified"); - this.statementExecutor = builder.statementExecutor; - this.statementTimeout = builder.statementTimeout; - } - - StatementExecutor getStatementExecutor() { - return statementExecutor; - } - - StatementTimeout getStatementTimeout() { - return statementTimeout; - } - - @Override - public void cancel() { - synchronized (this) { - if (currentlyRunningStatementFuture != null - && !currentlyRunningStatementFuture.isDone() - && !currentlyRunningStatementFuture.isCancelled()) { - currentlyRunningStatementFuture.cancel(true); - } - } - } - - T asyncExecuteStatement(ParsedStatement statement, Callable callable) { - return asyncExecuteStatement(statement, callable, InterceptorsUsage.INVOKE_INTERCEPTORS); - } - - T asyncExecuteStatement( - ParsedStatement statement, Callable callable, InterceptorsUsage interceptorUsage) { - Preconditions.checkNotNull(statement); - Preconditions.checkNotNull(callable); - - if (interceptorUsage == InterceptorsUsage.INVOKE_INTERCEPTORS) { - statementExecutor.invokeInterceptors( - statement, StatementExecutionStep.EXECUTE_STATEMENT, this); - } - Future future = statementExecutor.submit(callable); - synchronized (this) { - this.currentlyRunningStatementFuture = future; - } - T res; - try { - if (statementTimeout.hasTimeout()) { - TimeUnit unit = statementTimeout.getAppropriateTimeUnit(); - res = future.get(statementTimeout.getTimeoutValue(unit), unit); - } else { - res = future.get(); - } - } catch (TimeoutException e) { - // statement timed out, cancel the execution - future.cancel(true); - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.DEADLINE_EXCEEDED, - "Statement execution timeout occurred for " + statement.getSqlWithoutComments(), - e); - } catch (ExecutionException e) { - Throwable cause = e.getCause(); - Set causes = new HashSet<>(); - while (cause != null && !causes.contains(cause)) { - if (cause instanceof SpannerException) { - throw (SpannerException) cause; - } - causes.add(cause); - cause = cause.getCause(); - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.UNKNOWN, - "Statement execution failed for " + statement.getSqlWithoutComments(), - e); - } catch (InterruptedException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.CANCELLED, "Statement execution was interrupted", e); - } catch (CancellationException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.CANCELLED, "Statement execution was cancelled", e); - } finally { - synchronized (this) { - this.currentlyRunningStatementFuture = null; - } - } - return res; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 71a1c20a62e2..aad5ad82c7ec 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; import java.sql.CallableStatement; @@ -48,7 +49,7 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper private final String connectionUrl; private final ConnectionOptions options; - private final com.google.cloud.spanner.jdbc.Connection spanner; + private final com.google.cloud.spanner.connection.Connection spanner; private SQLWarning firstWarning = null; private SQLWarning lastWarning = null; @@ -59,8 +60,8 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper this.spanner = options.getConnection(); } - /** Return the corresponding {@link com.google.cloud.spanner.jdbc.Connection} */ - com.google.cloud.spanner.jdbc.Connection getSpannerConnection() { + /** Return the corresponding {@link com.google.cloud.spanner.connection.Connection} */ + com.google.cloud.spanner.connection.Connection getSpannerConnection() { return spanner; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 94ddaf17d695..48a002d57b57 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -19,7 +19,8 @@ import com.google.cloud.spanner.Options; import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType; +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; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java deleted file mode 100644 index 6468c0042da3..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractMultiUseTransaction.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadContext; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; -import java.util.concurrent.Callable; - -/** - * Base class for {@link Connection}-based transactions that can be used for multiple read and - * read/write statements. - */ -abstract class AbstractMultiUseTransaction extends AbstractBaseUnitOfWork { - - AbstractMultiUseTransaction(Builder builder) { - super(builder); - } - - @Override - public Type getType() { - return Type.TRANSACTION; - } - - @Override - public boolean isActive() { - return getState().isActive(); - } - - /** - * Check that the current transaction actually has a valid underlying transaction. If not, the - * method will throw a {@link SpannerException}. - */ - abstract void checkValidTransaction(); - - /** Returns the {@link ReadContext} that can be used for queries on this transaction. */ - abstract ReadContext getReadContext(); - - @Override - public ResultSet executeQuery( - final ParsedStatement statement, - final AnalyzeMode analyzeMode, - final QueryOption... options) { - Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); - checkValidTransaction(); - return asyncExecuteStatement( - statement, - new Callable() { - @Override - public ResultSet call() throws Exception { - return DirectExecuteResultSet.ofResultSet( - internalExecuteQuery(statement, analyzeMode, options)); - } - }); - } - - ResultSet internalExecuteQuery( - final ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { - if (analyzeMode == AnalyzeMode.NONE) { - return getReadContext().executeQuery(statement.getStatement(), options); - } - return getReadContext() - .analyzeQuery(statement.getStatement(), analyzeMode.getQueryAnalyzeMode()); - } - - @Override - public long[] runBatch() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for transactions"); - } - - @Override - public void abortBatch() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for transactions"); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java deleted file mode 100644 index 457ceec2a128..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AnalyzeMode.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 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.ReadContext.QueryAnalyzeMode; - -/** - * {@link AnalyzeMode} indicates whether a query should be executed as a normal query (NONE), - * whether only a query plan should be returned, or whether the query should be profiled while - * executed. - */ -enum AnalyzeMode { - NONE(null), - PLAN(QueryAnalyzeMode.PLAN), - PROFILE(QueryAnalyzeMode.PROFILE); - - private final QueryAnalyzeMode mode; - - private AnalyzeMode(QueryAnalyzeMode mode) { - this.mode = mode; - } - - QueryAnalyzeMode getQueryAnalyzeMode() { - return mode; - } - - /** Translates from the Spanner client library QueryAnalyzeMode to {@link AnalyzeMode}. */ - static AnalyzeMode of(QueryAnalyzeMode mode) { - switch (mode) { - case PLAN: - return AnalyzeMode.PLAN; - case PROFILE: - return AnalyzeMode.PROFILE; - default: - throw new IllegalArgumentException(mode + " is unknown"); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java deleted file mode 100644 index c390edd1b459..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AutocommitDmlMode.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 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; - -/** Enum used to define the behavior of DML statements in autocommit mode */ -enum AutocommitDmlMode { - TRANSACTIONAL, - PARTITIONED_NON_ATOMIC; - - private final String statementString; - - private AutocommitDmlMode() { - this.statementString = name(); - } - - /** - * Use this method to get the correct format for use in a SQL statement. Autocommit dml mode must - * be wrapped between single quotes in SQL statements: - * SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL' This method returns the value - * without the single quotes. - * - * @return a string representation of this {@link AutocommitDmlMode} that can be used in a SQL - * statement. - */ - public String getStatementString() { - return statementString; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java deleted file mode 100644 index 0e0d7b433c34..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ChecksumResultSet.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2019 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.ByteArray; -import com.google.cloud.Date; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type.Code; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.hash.Funnel; -import com.google.common.hash.HashCode; -import com.google.common.hash.HashFunction; -import com.google.common.hash.Hasher; -import com.google.common.hash.Hashing; -import com.google.common.hash.PrimitiveSink; -import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -/** - * {@link ResultSet} implementation that keeps a running checksum that can be used to determine - * whether a transaction retry is possible or not. The checksum is based on all the rows that have - * actually been consumed by the user. If the user has not yet consumed any part of the result set - * (i.e. never called next()), the checksum will be null and retry will always be - * allowed. - * - *

    If all the rows in the result set have been consumed, the checksum will be based on the values - * of all those rows, and a retry will only be possible if the query returns the exact same results - * during the retry as during the original transaction. - * - *

    If some of the rows in the result set have been consumed, the checksum will be based on the - * values of the rows that have been consumed. A retry will succeed if the query returns the same - * results for the already consumed rows. - * - *

    The checksum of a {@link ResultSet} is the SHA256 checksum of the current row together with - * the previous checksum value of the result set. The calculation of the checksum is executed in a - * separate {@link Thread} to allow the checksum calculation to lag behind the actual consumption of - * rows, and catch up again if the client slows down the consumption of rows, for example while - * waiting for more data from Cloud Spanner. If the checksum calculation queue contains more than - * {@link ChecksumExecutor#MAX_IN_CHECKSUM_QUEUE} items that have not yet been calculated, calls to - * {@link ResultSet#next()} will slow down in order to allow the calculation to catch up. - */ -@VisibleForTesting -class ChecksumResultSet extends ReplaceableForwardingResultSet implements RetriableStatement { - private final ReadWriteTransaction transaction; - private long numberOfNextCalls; - private final ParsedStatement statement; - private final AnalyzeMode analyzeMode; - private final QueryOption[] options; - private final ChecksumResultSet.ChecksumCalculator checksumCalculator = new ChecksumCalculator(); - - ChecksumResultSet( - ReadWriteTransaction transaction, - ResultSet delegate, - ParsedStatement statement, - AnalyzeMode analyzeMode, - QueryOption... options) { - super(delegate); - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(delegate); - Preconditions.checkNotNull(statement); - Preconditions.checkNotNull(statement.getStatement()); - Preconditions.checkNotNull(statement.getStatement().getSql()); - this.transaction = transaction; - this.statement = statement; - this.analyzeMode = analyzeMode; - this.options = options; - } - - /** Simple {@link Callable} for calling {@link ResultSet#next()} */ - private final class NextCallable implements Callable { - @Override - public Boolean call() throws Exception { - transaction - .getStatementExecutor() - .invokeInterceptors( - statement, StatementExecutionStep.CALL_NEXT_ON_RESULT_SET, transaction); - return ChecksumResultSet.super.next(); - } - } - - private final NextCallable nextCallable = new NextCallable(); - - @Override - public boolean next() { - // Call next() with retry. - boolean res = transaction.runWithRetry(nextCallable); - // Only update the checksum if there was another row to be consumed. - if (res) { - checksumCalculator.calculateNextChecksum(getCurrentRowAsStruct()); - } - numberOfNextCalls++; - return res; - } - - @VisibleForTesting - HashCode getChecksum() throws InterruptedException, ExecutionException { - // HashCode is immutable and can be safely returned. - return checksumCalculator.getChecksum(); - } - - /** - * Execute the same query as in the original transaction and consume the {@link ResultSet} to the - * same point as the original {@link ResultSet}. The {@link HashCode} of the new {@link ResultSet} - * is compared with the {@link HashCode} of the original {@link ResultSet} at the point where the - * consumption of the {@link ResultSet} stopped. - */ - @Override - public void retry(AbortedException aborted) throws AbortedException { - // Execute the same query and consume the result set to the same point as the original. - ChecksumResultSet.ChecksumCalculator newChecksumCalculator = new ChecksumCalculator(); - ResultSet resultSet = null; - long counter = 0L; - try { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - resultSet = - DirectExecuteResultSet.ofResultSet( - transaction.internalExecuteQuery(statement, analyzeMode, options)); - boolean next = true; - while (counter < numberOfNextCalls && next) { - transaction - .getStatementExecutor() - .invokeInterceptors( - statement, StatementExecutionStep.RETRY_NEXT_ON_RESULT_SET, transaction); - next = resultSet.next(); - if (next) { - newChecksumCalculator.calculateNextChecksum(resultSet.getCurrentRowAsStruct()); - } - counter++; - } - } catch (Throwable e) { - if (resultSet != null) { - resultSet.close(); - } - // If it was a SpannerException other than an AbortedException, the retry should fail - // because of different results from the database. - if (e instanceof SpannerException && !(e instanceof AbortedException)) { - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException( - aborted, (SpannerException) e); - } - // For other types of exceptions we should just re-throw the exception. - throw e; - } - // Check that we have the same number of rows and the same checksum. - HashCode newChecksum = newChecksumCalculator.getChecksum(); - HashCode currentChecksum = checksumCalculator.getChecksum(); - if (counter == numberOfNextCalls && Objects.equals(newChecksum, currentChecksum)) { - // Checksum is ok, we only need to replace the delegate result set if it's still open. - if (isClosed()) { - resultSet.close(); - } else { - replaceDelegate(resultSet); - } - } else { - // The results are not equal, there is an actual concurrent modification, so we cannot - // continue the transaction. - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } - } - - /** Calculates and keeps the current checksum of a {@link ChecksumResultSet} */ - private static final class ChecksumCalculator { - private static final HashFunction SHA256_FUNCTION = Hashing.sha256(); - private HashCode currentChecksum; - - private void calculateNextChecksum(Struct row) { - Hasher hasher = SHA256_FUNCTION.newHasher(); - if (currentChecksum != null) { - hasher.putBytes(currentChecksum.asBytes()); - } - hasher.putObject(row, StructFunnel.INSTANCE); - currentChecksum = hasher.hash(); - } - - private HashCode getChecksum() { - return currentChecksum; - } - } - - /** - * A {@link Funnel} implementation for calculating a {@link HashCode} for each row in a {@link - * ResultSet}. - */ - private enum StructFunnel implements Funnel { - INSTANCE; - private static final String NULL = "null"; - - @Override - public void funnel(Struct row, PrimitiveSink into) { - for (int i = 0; i < row.getColumnCount(); i++) { - if (row.isNull(i)) { - funnelValue(Code.STRING, null, into); - } else { - Code type = row.getColumnType(i).getCode(); - switch (type) { - case ARRAY: - funnelArray(row.getColumnType(i).getArrayElementType().getCode(), row, i, into); - break; - case BOOL: - funnelValue(type, row.getBoolean(i), into); - break; - case BYTES: - funnelValue(type, row.getBytes(i), into); - break; - case DATE: - funnelValue(type, row.getDate(i), into); - break; - case FLOAT64: - funnelValue(type, row.getDouble(i), into); - break; - case INT64: - funnelValue(type, row.getLong(i), into); - break; - case STRING: - funnelValue(type, row.getString(i), into); - break; - case TIMESTAMP: - funnelValue(type, row.getTimestamp(i), into); - break; - - case STRUCT: - default: - throw new IllegalArgumentException("unsupported row type"); - } - } - } - } - - private void funnelArray( - Code arrayElementType, Struct row, int columnIndex, PrimitiveSink into) { - funnelValue(Code.STRING, "BeginArray", into); - switch (arrayElementType) { - case BOOL: - into.putInt(row.getBooleanList(columnIndex).size()); - for (Boolean value : row.getBooleanList(columnIndex)) { - funnelValue(Code.BOOL, value, into); - } - break; - case BYTES: - into.putInt(row.getBytesList(columnIndex).size()); - for (ByteArray value : row.getBytesList(columnIndex)) { - funnelValue(Code.BYTES, value, into); - } - break; - case DATE: - into.putInt(row.getDateList(columnIndex).size()); - for (Date value : row.getDateList(columnIndex)) { - funnelValue(Code.DATE, value, into); - } - break; - case FLOAT64: - into.putInt(row.getDoubleList(columnIndex).size()); - for (Double value : row.getDoubleList(columnIndex)) { - funnelValue(Code.FLOAT64, value, into); - } - break; - case INT64: - into.putInt(row.getLongList(columnIndex).size()); - for (Long value : row.getLongList(columnIndex)) { - funnelValue(Code.INT64, value, into); - } - break; - case STRING: - into.putInt(row.getStringList(columnIndex).size()); - for (String value : row.getStringList(columnIndex)) { - funnelValue(Code.STRING, value, into); - } - break; - case TIMESTAMP: - into.putInt(row.getTimestampList(columnIndex).size()); - for (Timestamp value : row.getTimestampList(columnIndex)) { - funnelValue(Code.TIMESTAMP, value, into); - } - break; - - case ARRAY: - case STRUCT: - default: - throw new IllegalArgumentException("unsupported array element type"); - } - funnelValue(Code.STRING, "EndArray", into); - } - - private void funnelValue(Code type, T value, PrimitiveSink into) { - // Include the type name in case the type of a column has changed. - into.putUnencodedChars(type.name()); - if (value == null) { - if (type == Code.BYTES || type == Code.STRING) { - // Put length -1 to distinguish from the string value 'null'. - into.putInt(-1); - } - into.putUnencodedChars(NULL); - } else { - switch (type) { - case BOOL: - into.putBoolean((Boolean) value); - break; - case BYTES: - ByteArray byteArray = (ByteArray) value; - into.putInt(byteArray.length()); - into.putBytes(byteArray.toByteArray()); - break; - case DATE: - Date date = (Date) value; - into.putInt(date.getYear()).putInt(date.getMonth()).putInt(date.getDayOfMonth()); - break; - case FLOAT64: - into.putDouble((Double) value); - break; - case INT64: - into.putLong((Long) value); - break; - case STRING: - String stringValue = (String) value; - into.putInt(stringValue.length()); - into.putUnencodedChars(stringValue); - break; - case TIMESTAMP: - Timestamp timestamp = (Timestamp) value; - into.putLong(timestamp.getSeconds()).putInt(timestamp.getNanos()); - break; - case ARRAY: - case STRUCT: - default: - throw new IllegalArgumentException("invalid type for single value"); - } - } - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java deleted file mode 100644 index 7bd31407a348..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatement.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019 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.ResultSet; -import java.util.List; - -/** - * A {@link ClientSideStatement} is a statement that is not sent to Google Cloud Spanner, but that - * is executed locally to for example set a certain state of a {@link Connection} or get a property - * of a {@link Connection}. - */ -interface ClientSideStatement { - - /** - * @return a list of example statements for this {@link ClientSideStatement}. If these statements - * are parsed, they will all result this in this {@link ClientSideStatement}. - */ - List getExampleStatements(); - - /** - * @return a list of statements that need to be executed on a new connection before the example - * statements may be executed on a connection. For GET READ_TIMESTAMP this would for example - * be a couple of statements that generate a read-only transaction. - */ - List getExamplePrerequisiteStatements(); - - /** - * @return true if this {@link ClientSideStatement} will return a {@link ResultSet}. - */ - boolean isQuery(); - - /** @return true if this {@link ClientSideStatement} will return an update count. */ - boolean isUpdate(); - - /** - * Execute this {@link ClientSideStatement} on the given {@link ConnectionStatementExecutor}. The - * executor calls the appropriate method(s) on the {@link Connection}. The statement argument is - * used to parse any additional properties that might be needed for the execution. - * - * @param executor The {@link ConnectionStatementExecutor} that will be used to call a method on - * the {@link Connection}. - * @param statement The original sql statement that has been parsed to this {@link - * ClientSideStatement}. This statement is used to get any additional arguments that are - * needed for the execution of the {@link ClientSideStatement}. - * @return the result of the execution of the statement. - */ - StatementResult execute(ConnectionStatementExecutor executor, String statement); -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java deleted file mode 100644 index d758286d16c5..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementExecutor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; - -/** - * A {@link ClientSideStatementExecutor} is used to compile {@link ClientSideStatement}s from the - * json source file, and to execute these against a {@link Connection} (through a {@link - * ConnectionStatementExecutor}). - */ -interface ClientSideStatementExecutor { - - /** - * Compiles the given {@link ClientSideStatementImpl} and registers this statement with this - * executor. A statement must be compiled before it can be executed. The parser automatically - * compiles all available statements during initialization. - * - * @param statement The statement to compile. - * @throws CompileException If the statement could not be compiled. This should never happen, as - * it would indicate that an invalid statement has been defined in the source file. - */ - void compile(ClientSideStatementImpl statement) throws CompileException; - - /** - * Executes the {@link ClientSideStatementImpl} that has been compiled and registered with this - * executor on the specified connection. - * - * @param connectionExecutor The {@link ConnectionStatementExecutor} to use to execute the - * statement on a {@link Connection}. - * @param sql The sql statement that is executed. This can be used to parse any additional - * arguments that might be needed for the execution of the {@link ClientSideStatementImpl}. - * @return the result of the execution. - * @throws Exception If an error occurs while executing the statement, for example if an invalid - * argument has been specified in the sql statement, or if the statement is invalid for the - * current state of the {@link Connection}. - */ - StatementResult execute(ConnectionStatementExecutor connectionExecutor, String sql) - throws Exception; -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java deleted file mode 100644 index 551ab5aa3a87..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementImpl.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2019 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.SpannerException; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; -import com.google.common.base.Preconditions; -import java.lang.reflect.InvocationTargetException; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -/** - * Implementation of the {@link ClientSideStatement} interface. The instances of this class are - * imported from the file 'ClientSideStatements.json' in the resources folder. - */ -class ClientSideStatementImpl implements ClientSideStatement { - - /** - * Statements that set a value, such as SET AUTOCOMMIT ON|OFF, must specify a {@link - * ClientSideSetStatementImpl} that defines how the value is set. - */ - static class ClientSideSetStatementImpl { - /** The property name that is to be set, e.g. AUTOCOMMIT. */ - private String propertyName; - /** The separator between the property and the value (i.e. '=' or '\s+'). */ - private String separator; - /** Regex specifying the range of allowed values for the property. */ - private String allowedValues; - /** The class name of the {@link ClientSideStatementValueConverter} to use. */ - private String converterName; - - String getPropertyName() { - return propertyName; - } - - String getSeparator() { - return separator; - } - - String getAllowedValues() { - return allowedValues; - } - - String getConverterName() { - return converterName; - } - } - - static class CompileException extends Exception { - private static final long serialVersionUID = 1L; - private final ClientSideStatementImpl statement; - - CompileException(Throwable cause, ClientSideStatementImpl statement) { - super(cause); - this.statement = statement; - } - - @Override - public String getMessage() { - return "Could not compile statement " + this.statement.name; - } - } - - static class ExecuteException extends RuntimeException { - private static final long serialVersionUID = 1L; - private final ClientSideStatementImpl statement; - private final String sql; - - private ExecuteException(Throwable cause, ClientSideStatementImpl statement, String sql) { - super(cause); - this.statement = statement; - this.sql = sql; - } - - @Override - public String getMessage() { - return "Could not execute statement " + this.statement.name + " (" + sql + ")"; - } - } - - /** The name of this statement. Used in error and info messages. */ - private String name; - - /** - * The class name of the {@link ClientSideStatementExecutor} that should be used for this - * statement. - */ - private String executorName; - - /** The result type of this statement. */ - private ResultType resultType; - - /** The regular expression that should be used to recognize this class of statements. */ - private String regex; - - /** - * The method name of the {@link ConnectionStatementExecutor} that should be called when this - * statement is executed, for example 'statementSetAutocommit'. - */ - private String method; - - /** A list of example statements that is used for testing. */ - private List exampleStatements; - - /** - * A list of statements that need to be executed before the example statements may be executed. - */ - private List examplePrerequisiteStatements; - - /** - * If this statement sets a value, the statement definition should also contain a {@link - * ClientSideSetStatementImpl} definition that defines how the value that is to be set should be - * parsed. - */ - private ClientSideSetStatementImpl setStatement; - - /** The compiled regex pattern for recognizing this statement. */ - private Pattern pattern; - - /** A reference to the executor that should be used. */ - private ClientSideStatementExecutor executor; - - /** - * Compiles this {@link ClientSideStatementImpl}. Throws a {@link CompileException} if the - * compilation fails. This should never happen, and if it does, it is a sign of a invalid - * statement definition in the ClientSideStatements.json file. - */ - ClientSideStatementImpl compile() throws CompileException { - try { - this.pattern = Pattern.compile(regex); - this.executor = - (ClientSideStatementExecutor) - Class.forName(getClass().getPackage().getName() + "." + executorName).newInstance(); - this.executor.compile(this); - return this; - } catch (Exception e) { - throw new CompileException(e, this); - } - } - - @Override - public StatementResult execute(ConnectionStatementExecutor connection, String statement) { - Preconditions.checkState(executor != null, "This statement has not been compiled"); - try { - return executor.execute(connection, statement); - } catch (SpannerException e) { - throw e; - } catch (InvocationTargetException e) { - if (e.getCause() instanceof SpannerException) { - throw (SpannerException) e.getCause(); - } - throw new ExecuteException(e.getCause(), this, statement); - } catch (Exception e) { - throw new ExecuteException(e, this, statement); - } - } - - @Override - public boolean isQuery() { - return resultType == ResultType.RESULT_SET; - } - - @Override - public boolean isUpdate() { - return resultType == ResultType.UPDATE_COUNT; - } - - boolean matches(String statement) { - Preconditions.checkState(pattern != null, "This statement has not been compiled"); - return pattern.matcher(statement).matches(); - } - - @Override - public String toString() { - return name; - } - - Pattern getPattern() { - return pattern; - } - - String getMethodName() { - return method; - } - - @Override - public List getExampleStatements() { - return Collections.unmodifiableList(exampleStatements); - } - - @Override - public List getExamplePrerequisiteStatements() { - if (examplePrerequisiteStatements == null) { - return Collections.emptyList(); - } - return Collections.unmodifiableList(examplePrerequisiteStatements); - } - - ClientSideSetStatementImpl getSetStatement() { - return setStatement; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java deleted file mode 100644 index d2ca7fde9d0f..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementNoParamExecutor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; -import java.lang.reflect.Method; - -/** - * Executor to use for statements that do not set a value and do not have any parameters, such as - * SHOW AUTOCOMMIT. The executor just calls a method with no parameters. - */ -class ClientSideStatementNoParamExecutor implements ClientSideStatementExecutor { - private Method method; - - ClientSideStatementNoParamExecutor() {} - - @Override - public void compile(ClientSideStatementImpl statement) throws CompileException { - try { - this.method = ConnectionStatementExecutor.class.getDeclaredMethod(statement.getMethodName()); - } catch (NoSuchMethodException | SecurityException e) { - throw new CompileException(e, statement); - } - } - - @Override - public StatementResult execute(ConnectionStatementExecutor connection, String statement) - throws Exception { - return (StatementResult) method.invoke(connection); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java deleted file mode 100644 index aaf01eaaa859..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementSetExecutor.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.common.base.Preconditions; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Executor for {@link ClientSideStatement}s that sets a value for a property, such as SET - * AUTOCOMMIT=TRUE. - */ -class ClientSideStatementSetExecutor implements ClientSideStatementExecutor { - private ClientSideStatementImpl statement; - private Method method; - private ClientSideStatementValueConverter converter; - private Pattern allowedValuesPattern; - - @SuppressWarnings("unchecked") - @Override - public void compile(ClientSideStatementImpl statement) throws CompileException { - Preconditions.checkNotNull(statement.getSetStatement()); - try { - this.statement = statement; - this.allowedValuesPattern = - Pattern.compile( - String.format( - "(?is)\\A\\s*set\\s+%s\\s*%s\\s*%s\\s*\\z", - statement.getSetStatement().getPropertyName(), - statement.getSetStatement().getSeparator(), - statement.getSetStatement().getAllowedValues())); - Class> converterClass = - (Class>) - Class.forName( - getClass().getPackage().getName() - + "." - + statement.getSetStatement().getConverterName()); - Constructor> constructor = - converterClass.getConstructor(String.class); - this.converter = constructor.newInstance(statement.getSetStatement().getAllowedValues()); - this.method = - ConnectionStatementExecutor.class.getDeclaredMethod( - statement.getMethodName(), converter.getParameterClass()); - } catch (Exception e) { - throw new CompileException(e, statement); - } - } - - @Override - public StatementResult execute(ConnectionStatementExecutor connection, String sql) - throws Exception { - return (StatementResult) method.invoke(connection, getParameterValue(sql)); - } - - T getParameterValue(String sql) { - Matcher matcher = allowedValuesPattern.matcher(sql); - if (matcher.find() && matcher.groupCount() >= 1) { - String value = matcher.group(1); - T res = converter.convert(value); - if (res != null) { - return res; - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - String.format( - "Unknown value for %s: %s", - this.statement.getSetStatement().getPropertyName(), value)); - } else { - Matcher invalidMatcher = this.statement.getPattern().matcher(sql); - if (invalidMatcher.find() && invalidMatcher.groupCount() == 1) { - String invalidValue = invalidMatcher.group(1); - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - String.format( - "Unknown value for %s: %s", - this.statement.getSetStatement().getPropertyName(), invalidValue)); - } - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, String.format("Unknown statement: %s", sql)); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java deleted file mode 100644 index 13b404cfe598..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 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; - -/** - * Interface for converters that are used by {@link ClientSideStatement} that sets a value that need - * to be converted from a string to a specific type. Implementing classes must have a public - * constructor that takes a String parameter. The String parameter will contain a regular expression - * for the allowed values for the property. - */ -interface ClientSideStatementValueConverter { - - /** The type to convert to. */ - Class getParameterClass(); - - /** - * The actual convert method. Should return null for values that could not be - * converted. - */ - T convert(String value); -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java deleted file mode 100644 index 92368fecafa9..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatementValueConverters.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.protobuf.Duration; -import com.google.protobuf.util.Durations; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** Contains all {@link ClientSideStatementValueConverter} implementations. */ -class ClientSideStatementValueConverters { - /** Map for mapping case-insensitive strings to enums. */ - private static final class CaseInsensitiveEnumMap> { - private final Map map = new HashMap<>(); - - /** Create an map using the name of the enum elements as keys. */ - private CaseInsensitiveEnumMap(Class elementType) { - this( - elementType, - new Function() { - @Override - public String apply(E input) { - return input.name(); - } - }); - } - - /** Create a map using the specific function to get the key per enum value. */ - private CaseInsensitiveEnumMap(Class elementType, Function keyFunction) { - Preconditions.checkNotNull(elementType); - Preconditions.checkNotNull(keyFunction); - EnumSet set = EnumSet.allOf(elementType); - for (E e : set) { - if (map.put(keyFunction.apply(e).toUpperCase(), e) != null) { - throw new IllegalArgumentException( - "Enum contains multiple elements with the same case-insensitive key"); - } - } - } - - private E get(String value) { - Preconditions.checkNotNull(value); - return map.get(value.toUpperCase()); - } - } - - /** Converter from string to {@link Boolean} */ - static class BooleanConverter implements ClientSideStatementValueConverter { - - public BooleanConverter(String allowedValues) {} - - @Override - public Class getParameterClass() { - return Boolean.class; - } - - @Override - public Boolean convert(String value) { - if ("true".equalsIgnoreCase(value)) { - return Boolean.TRUE; - } - if ("false".equalsIgnoreCase(value)) { - return Boolean.FALSE; - } - return null; - } - } - - /** Converter from string to {@link Duration}. */ - static class DurationConverter implements ClientSideStatementValueConverter { - private final Pattern allowedValues; - - public DurationConverter(String allowedValues) { - // Remove the parentheses from the beginning and end. - this.allowedValues = - Pattern.compile( - "(?is)\\A" + allowedValues.substring(1, allowedValues.length() - 1) + "\\z"); - } - - @Override - public Class getParameterClass() { - return Duration.class; - } - - @Override - public Duration convert(String value) { - Matcher matcher = allowedValues.matcher(value); - if (matcher.find()) { - if (matcher.group(0).equalsIgnoreCase("null")) { - return Durations.fromNanos(0L); - } else { - Duration duration = - ReadOnlyStalenessUtil.createDuration( - Long.valueOf(matcher.group(1)), - ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(2))); - if (duration.getSeconds() == 0L && duration.getNanos() == 0) { - return null; - } - return duration; - } - } - return null; - } - } - - /** Converter from string to possible values for read only staleness ({@link TimestampBound}). */ - static class ReadOnlyStalenessConverter - implements ClientSideStatementValueConverter { - private final Pattern allowedValues; - private final CaseInsensitiveEnumMap values = new CaseInsensitiveEnumMap<>(Mode.class); - - public ReadOnlyStalenessConverter(String allowedValues) { - // Remove the single quotes at the beginning and end. - this.allowedValues = - Pattern.compile( - "(?is)\\A" + allowedValues.substring(1, allowedValues.length() - 1) + "\\z"); - } - - @Override - public Class getParameterClass() { - return TimestampBound.class; - } - - @Override - public TimestampBound convert(String value) { - Matcher matcher = allowedValues.matcher(value); - if (matcher.find() && matcher.groupCount() >= 1) { - Mode mode = null; - int groupIndex = 0; - for (int group = 1; group <= matcher.groupCount(); group++) { - if (matcher.group(group) != null) { - mode = values.get(matcher.group(group)); - if (mode != null) { - groupIndex = group; - break; - } - } - } - switch (mode) { - case STRONG: - return TimestampBound.strong(); - case READ_TIMESTAMP: - return TimestampBound.ofReadTimestamp( - ReadOnlyStalenessUtil.parseRfc3339(matcher.group(groupIndex + 1))); - case MIN_READ_TIMESTAMP: - return TimestampBound.ofMinReadTimestamp( - ReadOnlyStalenessUtil.parseRfc3339(matcher.group(groupIndex + 1))); - case EXACT_STALENESS: - try { - return TimestampBound.ofExactStaleness( - Long.valueOf(matcher.group(groupIndex + 2)), - ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3))); - } catch (IllegalArgumentException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, e.getMessage()); - } - case MAX_STALENESS: - try { - return TimestampBound.ofMaxStaleness( - Long.valueOf(matcher.group(groupIndex + 2)), - ReadOnlyStalenessUtil.parseTimeUnit(matcher.group(groupIndex + 3))); - } catch (IllegalArgumentException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, e.getMessage()); - } - default: - // fall through to allow the calling method to handle this - } - } - return null; - } - } - - /** Converter for converting strings to {@link AutocommitDmlMode} values. */ - static class AutocommitDmlModeConverter - implements ClientSideStatementValueConverter { - private final CaseInsensitiveEnumMap values = - new CaseInsensitiveEnumMap<>(AutocommitDmlMode.class); - - public AutocommitDmlModeConverter(String allowedValues) {} - - @Override - public Class getParameterClass() { - return AutocommitDmlMode.class; - } - - @Override - public AutocommitDmlMode convert(String value) { - return values.get(value); - } - } - - static class StringValueConverter implements ClientSideStatementValueConverter { - public StringValueConverter(String allowedValues) {} - - @Override - public Class getParameterClass() { - return String.class; - } - - @Override - public String convert(String value) { - return value; - } - } - - /** Converter for converting string values to {@link TransactionMode} values. */ - static class TransactionModeConverter - implements ClientSideStatementValueConverter { - private final CaseInsensitiveEnumMap values = - new CaseInsensitiveEnumMap<>( - TransactionMode.class, - new Function() { - @Override - public String apply(TransactionMode input) { - return input.getStatementString(); - } - }); - - public TransactionModeConverter(String allowedValues) {} - - @Override - public Class getParameterClass() { - return TransactionMode.class; - } - - @Override - public TransactionMode convert(String value) { - // Transaction mode may contain multiple spaces. - String valueWithSingleSpaces = value.replaceAll("\\s+", " "); - return values.get(valueWithSingleSpaces); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java deleted file mode 100644 index 3f3d872fc669..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ClientSideStatements.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 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.jdbc.ClientSideStatementImpl.CompileException; -import com.google.gson.Gson; -import java.io.InputStreamReader; -import java.util.Set; - -/** This class reads and parses the {@link ClientSideStatement}s from the json file. */ -class ClientSideStatements { - private static final String STATEMENTS_DEFINITION_FILE = "ClientSideStatements.json"; - static final ClientSideStatements INSTANCE = importStatements(); - - /** - * Reads statement definitions from ClientSideStatements.json and parses these as Java objects. - */ - private static ClientSideStatements importStatements() { - Gson gson = new Gson(); - return gson.fromJson( - new InputStreamReader( - ClientSideStatements.class.getResourceAsStream(STATEMENTS_DEFINITION_FILE)), - ClientSideStatements.class); - } - - private Set statements; - - private ClientSideStatements() {} - - /** Compiles and returns all statements from the resource file. */ - Set getCompiledStatements() throws CompileException { - for (ClientSideStatementImpl statement : statements) { - statement.compile(); - } - return statements; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index d4c6629b7e82..dc52ca355d95 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -152,21 +152,45 @@ public interface CloudSpannerJdbcConnection extends Connection { /** * @see - * com.google.cloud.spanner.jdbc.Connection#addTransactionRetryListener(TransactionRetryListener) + * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(TransactionRetryListener) * @throws SQLException if the {@link Connection} is closed. */ - void addTransactionRetryListener(TransactionRetryListener listener) throws SQLException; + void addTransactionRetryListener( + com.google.cloud.spanner.connection.TransactionRetryListener listener) throws SQLException; + + /** + * Use {@link + * #addTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener)} + */ + @Deprecated + void addTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener listener) + throws SQLException; /** * @see - * com.google.cloud.spanner.jdbc.Connection#removeTransactionRetryListener(TransactionRetryListener) + * com.google.cloud.spanner.connection.Connection#removeTransactionRetryListener(TransactionRetryListener) * @throws SQLException if the {@link Connection} is closed. */ - boolean removeTransactionRetryListener(TransactionRetryListener listener) throws SQLException; + boolean removeTransactionRetryListener( + com.google.cloud.spanner.connection.TransactionRetryListener listener) throws SQLException; + + /** + * Use {@link + * #removeTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener)} + */ + @Deprecated + boolean removeTransactionRetryListener( + com.google.cloud.spanner.jdbc.TransactionRetryListener listener) throws SQLException; + + /** Use {@link #getTransactionRetryListenersFromConnection()} */ + @Deprecated + Iterator getTransactionRetryListeners() + throws SQLException; /** - * @see com.google.cloud.spanner.jdbc.Connection#getTransactionRetryListeners() + * @see com.google.cloud.spanner.connection.Connection#getTransactionRetryListeners() * @throws SQLException if the {@link Connection} is closed. */ - Iterator getTransactionRetryListeners() throws SQLException; + Iterator + getTransactionRetryListenersFromConnection() throws SQLException; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java deleted file mode 100644 index c3b32f8e6b26..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Connection.java +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Copyright 2019 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.Timestamp; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerBatchUpdateException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; -import java.util.Iterator; -import java.util.concurrent.TimeUnit; - -/** - * A connection to a Cloud Spanner database. Connections are not designed to be thread-safe. The - * only exception is the {@link Connection#cancel()} method that may be called by any other thread - * to stop the execution of the current statement on the connection. - * - *

    Connections accept a number of additional SQL statements for setting or changing the state of - * a {@link Connection}. These statements can only be executed using the {@link - * Connection#execute(Statement)} method: - * - *

      - *
    • SHOW AUTOCOMMIT: Returns the current value of AUTOCOMMIT of this - * connection as a {@link ResultSet} - *
    • SET AUTOCOMMIT=TRUE|FALSE: Sets the value of AUTOCOMMIT for this - * connection - *
    • SHOW READONLY: Returns the current value of READONLY of this - * connection as a {@link ResultSet} - *
    • SET READONLY=TRUE|FALSE: Sets the value of READONLY for this - * connection - *
    • SHOW RETRY_ABORTS_INTERNALLY: Returns the current value of - * RETRY_ABORTS_INTERNALLY of this connection as a {@link ResultSet} - *
    • SET RETRY_ABORTS_INTERNALLY=TRUE|FALSE: Sets the value of - * RETRY_ABORTS_INTERNALLY for this connection - *
    • SHOW AUTOCOMMIT_DML_MODE: Returns the current value of - * AUTOCOMMIT_DML_MODE of this connection as a {@link ResultSet} - *
    • SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL' | 'PARTITIONED_NON_ATOMIC': Sets the - * value of AUTOCOMMIT_DML_MODE for this connection - *
    • SHOW STATEMENT_TIMEOUT: Returns the current value of STATEMENT_TIMEOUT - * of this connection as a {@link ResultSet} - *
    • SET STATEMENT_TIMEOUT='<int64>s|ms|us|ns' | NULL: Sets the value of - * STATEMENT_TIMEOUT for this connection. The supported {@link TimeUnit}s are: - *
        - *
      • s - Seconds - *
      • ms - Milliseconds - *
      • us - Microseconds - *
      • ns - Nanoseconds - *
      - * Setting the STATEMENT_TIMEOUT to NULL will clear the value for the STATEMENT_TIMEOUT on the - * connection. - *
    • SHOW READ_TIMESTAMP: Returns the last READ_TIMESTAMP of this - * connection as a {@link ResultSet} - *
    • SHOW COMMIT_TIMESTAMP: Returns the last COMMIT_TIMESTAMP of this - * connection as a {@link ResultSet} - *
    • SHOW READ_ONLY_STALENESS: Returns the current value of - * READ_ONLY_STALENESS of this connection as a {@link ResultSet} - *
    • - * SET READ_ONLY_STALENESS='STRONG' | 'MIN_READ_TIMESTAMP <timestamp>' | 'READ_TIMESTAMP <timestamp>' | 'MAX_STALENESS <int64>s|ms|mus|ns' | 'EXACT_STALENESS (<int64>s|ms|mus|ns)' - * : Sets the value of READ_ONLY_STALENESS for this connection. - *
    • SHOW OPTIMIZER_VERSION: Returns the current value of - * OPTIMIZER_VERSION of this connection as a {@link ResultSet} - *
    • - * SET OPTIMIZER_VERSION='<version>' | 'LATEST' - * : Sets the value of OPTIMIZER_VERSION for this connection. - *
    • BEGIN [TRANSACTION]: Begins a new transaction. This statement is optional when - * the connection is not in autocommit mode, as a new transaction will automatically be - * started when a query or update statement is issued. In autocommit mode, this statement will - * temporarily put the connection in transactional mode, and return the connection to - * autocommit mode when COMMIT [TRANSACTION] or ROLLBACK [TRANSACTION] - * is executed - *
    • COMMIT [TRANSACTION]: Commits the current transaction - *
    • ROLLBACK [TRANSACTION]: Rollbacks the current transaction - *
    • SET TRANSACTION READ ONLY|READ WRITE: Sets the type for the current - * transaction. May only be executed before a transaction is actually running (i.e. before any - * statements have been executed in the transaction) - *
    • START BATCH DDL: Starts a batch of DDL statements. May only be executed when - * no transaction has been started and the connection is in read/write mode. The connection - * will only accept DDL statements while a DDL batch is active. - *
    • START BATCH DML: Starts a batch of DML statements. May only be executed when - * the connection is in read/write mode. The connection will only accept DML statements while - * a DML batch is active. - *
    • RUN BATCH: Ends the current batch, sends the batched DML or DDL statements to - * Spanner and blocks until all statements have been executed or an error occurs. May only be - * executed when a (possibly empty) batch is active. The statement will return the update - * counts of the batched statements as {@link ResultSet} with an ARRAY<INT64> column. In - * case of a DDL batch, this array will always be empty. - *
    • ABORT BATCH: Ends the current batch and removes any DML or DDL statements from - * the buffer without sending any statements to Spanner. May only be executed when a (possibly - * empty) batch is active. - *
    - * - * Note that Cloud Spanner could abort read/write transactions in the background, and that - * any database call during a read/write transaction could fail with an {@link - * AbortedException}. This also includes calls to {@link ResultSet#next()}. - * - *

    If {@link Connection#isRetryAbortsInternally()} is true, then the connection will - * silently handle any {@link AbortedException}s by internally re-acquiring all transactional locks - * and verifying (via the use of cryptographic checksums) that no underlying data has changed. If a - * change to the underlying data is detected, then an {@link - * AbortedDueToConcurrentModificationException} error will be thrown. If your application already - * uses retry loops to handle these Aborted errors, then it will be most efficient to set {@link - * Connection#isRetryAbortsInternally()} to false. - * - *

    Use {@link ConnectionOptions} to create a {@link Connection}. - */ -interface Connection extends AutoCloseable { - - /** Closes this connection. This is a no-op if the {@link Connection} has alread been closed. */ - @Override - void close(); - - /** @return true if this connection has been closed. */ - boolean isClosed(); - - /** - * Sets autocommit on/off for this {@link Connection}. Connections in autocommit mode will apply - * any changes to the database directly without waiting for an explicit commit. DDL- and DML - * statements as well as {@link Mutation}s are sent directly to Spanner, and committed - * automatically unless the statement caused an error. The statement is retried in case of an - * {@link AbortedException}. All other errors will cause the underlying transaction to be rolled - * back. - * - *

    A {@link Connection} that is in autocommit and read/write mode will allow all types of - * statements: Queries, DML, DDL, and Mutations (writes). If the connection is in read-only mode, - * only queries will be allowed. - * - *

    {@link Connection}s in autocommit mode may also accept partitioned DML statements. See - * {@link Connection#setAutocommitDmlMode(AutocommitDmlMode)} for more information. - * - * @param autocommit true/false to turn autocommit on/off - */ - void setAutocommit(boolean autocommit); - - /** @return true if this connection is in autocommit mode */ - boolean isAutocommit(); - - /** - * Sets this connection to read-only or read-write. This method may only be called when no - * transaction is active. A connection that is in read-only mode, will never allow any kind of - * changes to the database to be submitted. - * - * @param readOnly true/false to turn read-only mode on/off - */ - void setReadOnly(boolean readOnly); - - /** @return true if this connection is in read-only mode */ - boolean isReadOnly(); - - /** - * Sets the duration the connection should wait before automatically aborting the execution of a - * statement. The default is no timeout. Statement timeouts are applied all types of statements, - * both in autocommit and transactional mode. They also apply to {@link Connection#commit()} and - * {@link Connection#rollback()} statements. - * - *

    A DML statement in autocommit mode may or may not have actually been applied to the - * database, depending on when the timeout occurred. - * - *

    A DML statement in a transaction that times out may still have been applied to the - * transaction. If you still decide to commit the transaction after such a timeout, the DML - * statement may or may not have been part of the transaction, depending on whether the timeout - * occurred before or after the statement was (successfully) sent to Spanner. You should therefore - * either always rollback a transaction that had a DML statement that timed out, or you should - * accept that the timed out statement still might have been applied to the database. - * - *

    DDL statements and DML statements in {@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} mode - * cannot be rolled back. If such a statement times out, it may or may not have been applied to - * the database. The same applies to commit and rollback statements. - * - *

    Statements that time out will throw a {@link SpannerException} with error code {@link - * ErrorCode#DEADLINE_EXCEEDED}. - * - * @param timeout The number of {@link TimeUnit}s before a statement is automatically aborted by - * the connection. Zero or negative values are not allowed. The maximum allowed value is - * 315,576,000,000 seconds. Use {@link Connection#clearStatementTimeout()} to remove a timeout - * value that has been set. - * @param unit The {@link TimeUnit} to specify the timeout value in. Must be one of {@link - * TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link TimeUnit#MILLISECONDS}, {@link - * TimeUnit#SECONDS}. - */ - void setStatementTimeout(long timeout, TimeUnit unit); - - /** - * Clears the statement timeout value for this connection. This is a no-op if there is currently - * no statement timeout set on this connection. - */ - void clearStatementTimeout(); - - /** - * @param unit The {@link TimeUnit} to get the timeout value in. Must be one of {@link - * TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link TimeUnit#MILLISECONDS}, {@link - * TimeUnit#SECONDS} - * @return the current statement timeout value or 0 if no timeout value has been set. - */ - long getStatementTimeout(TimeUnit unit); - - /** @return true if this {@link Connection} has a statement timeout value. */ - boolean hasStatementTimeout(); - - /** - * Cancels the currently running statement on this {@link Connection} (if any). If canceling the - * statement execution succeeds, the statement will be terminated and a {@link SpannerException} - * with code {@link ErrorCode#CANCELLED} will be thrown. The result of the statement will be the - * same as when a statement times out (see {@link Connection#setStatementTimeout(long, TimeUnit)} - * for more information). - * - *

    Canceling a DDL statement in autocommit mode or a RUN BATCH statement of a DDL batch will - * cause the connection to try to cancel the execution of the DDL statement(s). This is not - * guaranteed to cancel the execution of the statement(s) on Cloud Spanner. See - * https://cloud.google.com/spanner/docs/reference/rpc/google.longrunning#google.longrunning.Operations.CancelOperation - * for more information. - * - *

    Canceling a DML statement that is running in {@link - * AutocommitDmlMode#PARTITIONED_NON_ATOMIC} mode will not cancel a statement on Cloud Spanner - * that is already being executed, and its effects will still be applied to the database. - */ - void cancel(); - - /** - * Begins a new transaction for this connection. - * - *

      - *
    • Calling this method on a connection that has no transaction and that is - * not in autocommit mode, will register a new transaction that has not yet - * started on this connection - *
    • Calling this method on a connection that has no transaction and that is - * in autocommit mode, will register a new transaction that has not yet started on this - * connection, and temporarily turn off autocommit mode until the next commit/rollback - *
    • Calling this method on a connection that already has a transaction that has not yet - * started, will cause a {@link SpannerException} - *
    • Calling this method on a connection that already has a transaction that has started, will - * cause a {@link SpannerException} (no nested transactions) - *
    - */ - void beginTransaction(); - - /** - * Sets the transaction mode to use for current transaction. This method may only be called when - * in a transaction, and before the transaction is actually started, i.e. before any statements - * have been executed in the transaction. - * - * @param transactionMode The transaction mode to use for the current transaction. - *
      - *
    • {@link TransactionMode#READ_ONLY_TRANSACTION} will create a read-only transaction and - * prevent any changes to written to the database through this transaction. The read - * timestamp to be used will be determined based on the current readOnlyStaleness - * setting of this connection. It is recommended to use {@link - * TransactionMode#READ_ONLY_TRANSACTION} instead of {@link - * TransactionMode#READ_WRITE_TRANSACTION} when possible, as read-only transactions do - * not acquire locks on Cloud Spanner, and read-only transactions never abort. - *
    • {@link TransactionMode#READ_WRITE_TRANSACTION} this value is only allowed when the - * connection is not in read-only mode and will create a read-write transaction. If - * {@link Connection#isRetryAbortsInternally()} is true, each read/write - * transaction will keep track of a running SHA256 checksum for each {@link ResultSet} - * that is returned in order to be able to retry the transaction in case the transaction - * is aborted by Spanner. - *
    - */ - void setTransactionMode(TransactionMode transactionMode); - - /** - * @return the transaction mode of the current transaction. This method may only be called when - * the connection is in a transaction. - */ - TransactionMode getTransactionMode(); - - /** - * @return true if this connection will automatically retry read/write transactions - * that abort. This method may only be called when the connection is in read/write - * transactional mode and no transaction has been started yet. - */ - boolean isRetryAbortsInternally(); - - /** - * Sets whether this connection will internally retry read/write transactions that abort. The - * default is true. When internal retry is enabled, the {@link Connection} will keep - * track of a running SHA256 checksum of all {@link ResultSet}s that have been returned from Cloud - * Spanner. If the checksum that is calculated during an internal retry differs from the original - * checksum, the transaction will abort with an {@link - * AbortedDueToConcurrentModificationException}. - * - *

    Note that retries of a read/write transaction that calls a non-deterministic function on - * Cloud Spanner, such as CURRENT_TIMESTAMP(), will never be successful, as the data returned - * during the retry will always be different from the original transaction. - * - *

    It is also highly recommended that all queries in a read/write transaction have an ORDER BY - * clause that guarantees that the data is returned in the same order as in the original - * transaction if the transaction is internally retried. The most efficient way to achieve this is - * to always include the primary key columns at the end of the ORDER BY clause. - * - *

    This method may only be called when the connection is in read/write transactional mode and - * no transaction has been started yet. - * - * @param retryAbortsInternally Set to true to internally retry transactions that are - * aborted by Spanner. When set to false, any database call on a transaction that - * has been aborted by Cloud Spanner will throw an {@link AbortedException} instead of being - * retried. Set this to false if your application already uses retry loops to handle {@link - * AbortedException}s. - */ - void setRetryAbortsInternally(boolean retryAbortsInternally); - - /** - * Add a {@link TransactionRetryListener} to this {@link Connection} for testing and logging - * purposes. The method {@link TransactionRetryListener#retryStarting(Timestamp, long, int)} will - * be called before an automatic retry is started for a read/write transaction on this connection. - * The method {@link TransactionRetryListener#retryFinished(Timestamp, long, int, - * TransactionRetryListener.RetryResult)} will be called after the retry has finished. - * - * @param listener The listener to add to this connection. - */ - void addTransactionRetryListener(TransactionRetryListener listener); - - /** - * Removes one existing {@link TransactionRetryListener} from this {@link Connection}, if it is - * present (optional operation). - * - * @param listener The listener to remove from the connection. - * @return true if a listener was removed from the connection. - */ - boolean removeTransactionRetryListener(TransactionRetryListener listener); - - /** - * @return an unmodifiable iterator of the {@link TransactionRetryListener}s registered for this - * connection. - */ - Iterator getTransactionRetryListeners(); - - /** - * Sets the mode for executing DML statements in autocommit mode for this connection. This setting - * is only used when the connection is in autocommit mode, and may only be set while the - * transaction is in autocommit mode and not in a temporary transaction. The autocommit - * transaction mode is reset to its default value of {@link AutocommitDmlMode#TRANSACTIONAL} when - * autocommit mode is changed on the connection. - * - * @param mode The DML autocommit mode to use - *

      - *
    • {@link AutocommitDmlMode#TRANSACTIONAL} DML statements are executed as single - * read-write transaction. After successful execution, the DML statement is guaranteed - * to have been applied exactly once to the database - *
    • {@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} DML statements are executed as - * partitioned DML transactions. If an error occurs during the execution of the DML - * statement, it is possible that the statement has been applied to some but not all of - * the rows specified in the statement. - *
    - */ - void setAutocommitDmlMode(AutocommitDmlMode mode); - - /** - * @return the current {@link AutocommitDmlMode} setting for this connection. This method may only - * be called on a connection that is in autocommit mode and not while in a temporary - * transaction. - */ - AutocommitDmlMode getAutocommitDmlMode(); - - /** - * Sets the staleness to use for the current read-only transaction. This method may only be called - * when the transaction mode of the current transaction is {@link - * TransactionMode#READ_ONLY_TRANSACTION} and there is no transaction that has started, or when - * the connection is in read-only and autocommit mode. - * - * @param staleness The staleness to use for the current but not yet started read-only transaction - */ - void setReadOnlyStaleness(TimestampBound staleness); - - /** - * @return the read-only staleness setting for the current read-only transaction. This method may - * only be called when the current transaction is a read-only transaction, or when the - * connection is in read-only and autocommit mode. - */ - TimestampBound getReadOnlyStaleness(); - - /** - * Sets the query optimizer version to use for this connection. - * - * @param optimizerVersion The query optimizer version to use. Must be a valid optimizer version - * number, the string LATEST or an empty string. The empty string will instruct - * the connection to use the optimizer version that is defined in the environment variable - * SPANNER_OPTIMIZER_VERSION. If no value is specified in the environment - * variable, the default query optimizer of Cloud Spanner is used. - */ - void setOptimizerVersion(String optimizerVersion); - - /** - * Gets the current query optimizer version of this connection. - * - * @return The query optimizer version that is currently used by this connection. - */ - String getOptimizerVersion(); - - /** - * Commits the current transaction of this connection. All mutations that have been buffered - * during the current transaction will be written to the database. - * - *

    If the connection is in autocommit mode, and there is a temporary transaction active on this - * connection, calling this method will cause the connection to go back to autocommit mode after - * calling this method. - * - *

    This method will throw a {@link SpannerException} with code {@link - * ErrorCode#DEADLINE_EXCEEDED} if a statement timeout has been set on this connection, and the - * commit operation takes longer than this timeout. - * - *

      - *
    • Calling this method on a connection in autocommit mode and with no temporary transaction, - * will cause an exception - *
    • Calling this method while a DDL batch is active will cause an exception - *
    • Calling this method on a connection with a transaction that has not yet started, will end - * that transaction and any properties that might have been set on that transaction, and - * return the connection to its previous state. This means that if a transaction is created - * and set to read-only, and then committed before any statements have been executed, the - * read-only transaction is ended and any subsequent statements will be executed in a new - * transaction. If the connection is in read-write mode, the default for new transactions - * will be {@link TransactionMode#READ_WRITE_TRANSACTION}. Committing an empty transaction - * also does not generate a read timestamp or a commit timestamp, and calling one of the - * methods {@link Connection#getReadTimestamp()} or {@link Connection#getCommitTimestamp()} - * will cause an exception. - *
    • Calling this method on a connection with a {@link TransactionMode#READ_ONLY_TRANSACTION} - * transaction will end that transaction. If the connection is in read-write mode, any - * subsequent transaction will by default be a {@link - * TransactionMode#READ_WRITE_TRANSACTION} transaction, unless any following transaction is - * explicitly set to {@link TransactionMode#READ_ONLY_TRANSACTION} - *
    • Calling this method on a connection with a {@link TransactionMode#READ_WRITE_TRANSACTION} - * transaction will send all buffered mutations to the database, commit any DML statements - * that have been executed during this transaction and end the transaction. - *
    - */ - void commit(); - - /** - * Rollbacks the current transaction of this connection. All mutations or DDL statements that have - * been buffered during the current transaction will be removed from the buffer. - * - *

    If the connection is in autocommit mode, and there is a temporary transaction active on this - * connection, calling this method will cause the connection to go back to autocommit mode after - * calling this method. - * - *

      - *
    • Calling this method on a connection in autocommit mode and with no temporary transaction - * will cause an exception - *
    • Calling this method while a DDL batch is active will cause an exception - *
    • Calling this method on a connection with a transaction that has not yet started, will end - * that transaction and any properties that might have been set on that transaction, and - * return the connection to its previous state. This means that if a transaction is created - * and set to read-only, and then rolled back before any statements have been executed, the - * read-only transaction is ended and any subsequent statements will be executed in a new - * transaction. If the connection is in read-write mode, the default for new transactions - * will be {@link TransactionMode#READ_WRITE_TRANSACTION}. - *
    • Calling this method on a connection with a {@link TransactionMode#READ_ONLY_TRANSACTION} - * transaction will end that transaction. If the connection is in read-write mode, any - * subsequent transaction will by default be a {@link - * TransactionMode#READ_WRITE_TRANSACTION} transaction, unless any following transaction is - * explicitly set to {@link TransactionMode#READ_ONLY_TRANSACTION} - *
    • Calling this method on a connection with a {@link TransactionMode#READ_WRITE_TRANSACTION} - * transaction will clear all buffered mutations, rollback any DML statements that have been - * executed during this transaction and end the transaction. - *
    - */ - void rollback(); - - /** - * @return true if this connection has a transaction (that has not necessarily - * started). This method will only return false when the {@link Connection} is in autocommit - * mode and no explicit transaction has been started by calling {@link - * Connection#beginTransaction()}. If the {@link Connection} is not in autocommit mode, there - * will always be a transaction. - */ - boolean isInTransaction(); - - /** - * @return true if this connection has a transaction that has started. A transaction - * is automatically started by the first statement that is executed in the transaction. - */ - boolean isTransactionStarted(); - - /** - * Returns the read timestamp of the current/last {@link TransactionMode#READ_ONLY_TRANSACTION} - * transaction, or the read timestamp of the last query in autocommit mode. - * - *
      - *
    • When in autocommit mode: The method will return the read timestamp of the last statement - * if the last statement was a query. - *
    • When in a {@link TransactionMode#READ_ONLY_TRANSACTION} transaction that has started (a - * query has been executed), or that has just committed: The read timestamp of the - * transaction. If the read-only transaction was committed without ever executing a query, - * calling this method after the commit will also throw a {@link SpannerException} - *
    • In all other cases the method will throw a {@link SpannerException}. - *
    - * - * @return the read timestamp of the current/last read-only transaction. - */ - Timestamp getReadTimestamp(); - - /** - * @return the commit timestamp of the last {@link TransactionMode#READ_WRITE_TRANSACTION} - * transaction. This method will throw a {@link SpannerException} if there is no last {@link - * TransactionMode#READ_WRITE_TRANSACTION} transaction (i.e. the last transaction was a {@link - * TransactionMode#READ_ONLY_TRANSACTION}), or if the last {@link - * TransactionMode#READ_WRITE_TRANSACTION} transaction rolled back. It will also throw a - * {@link SpannerException} if the last {@link TransactionMode#READ_WRITE_TRANSACTION} - * transaction was empty when committed. - */ - Timestamp getCommitTimestamp(); - - /** - * Starts a new DDL batch on this connection. A DDL batch allows several DDL statements to be - * grouped into a batch that can be executed as a group. DDL statements that are issued during the - * batch are buffered locally and will return immediately with an OK. It is not guaranteed that a - * DDL statement that has been issued during a batch will eventually succeed when running the - * batch. Aborting a DDL batch will clear the DDL buffer and will have made no changes to the - * database. Running a DDL batch will send all buffered DDL statements to Spanner, and Spanner - * will try to execute these. The result will be OK if all the statements executed successfully. - * If a statement cannot be executed, Spanner will stop execution at that point and return an - * error message for the statement that could not be executed. Preceding statements of the batch - * may have been executed. - * - *

    This method may only be called when the connection is in read/write mode, autocommit mode is - * enabled or no read/write transaction has been started, and there is not already another batch - * active. The connection will only accept DDL statements while a DDL batch is active. - */ - void startBatchDdl(); - - /** - * Starts a new DML batch on this connection. A DML batch allows several DML statements to be - * grouped into a batch that can be executed as a group. DML statements that are issued during the - * batch are buffered locally and will return immediately with an OK. It is not guaranteed that a - * DML statement that has been issued during a batch will eventually succeed when running the - * batch. Aborting a DML batch will clear the DML buffer and will have made no changes to the - * database. Running a DML batch will send all buffered DML statements to Spanner, and Spanner - * will try to execute these. The result will be OK if all the statements executed successfully. - * If a statement cannot be executed, Spanner will stop execution at that point and return {@link - * SpannerBatchUpdateException} for the statement that could not be executed. Preceding statements - * of the batch will have been executed, and the update counts of those statements can be - * retrieved through {@link SpannerBatchUpdateException#getUpdateCounts()}. - * - *

    This method may only be called when the connection is in read/write mode, autocommit mode is - * enabled or no read/write transaction has been started, and there is not already another batch - * active. The connection will only accept DML statements while a DML batch is active. - */ - void startBatchDml(); - - /** - * Sends all buffered DML or DDL statements of the current batch to the database, waits for these - * to be executed and ends the current batch. The method will throw an exception for the first - * statement that cannot be executed, or return successfully if all statements could be executed. - * If an exception is thrown for a statement in the batch, the preceding statements in the same - * batch may still have been applied to the database. - * - *

    This method may only be called when a (possibly empty) batch is active. - * - * @return the update counts in case of a DML batch. Returns an array containing 1 for each - * successful statement and 0 for each failed statement or statement that was not executed DDL - * in case of a DDL batch. - */ - long[] runBatch(); - - /** - * Clears all buffered statements in the current batch and ends the batch. - * - *

    This method may only be called when a (possibly empty) batch is active. - */ - void abortBatch(); - - /** @return true if a DDL batch is active on this connection. */ - boolean isDdlBatchActive(); - - /** @return true if a DML batch is active on this connection. */ - boolean isDmlBatchActive(); - - /** - * Executes the given statement if allowed in the current {@link TransactionMode} and connection - * state. The returned value depends on the type of statement: - * - *

      - *
    • Queries will return a {@link ResultSet} - *
    • DML statements will return an update count - *
    • DDL statements will return a {@link ResultType#NO_RESULT} - *
    • Connection and transaction statements (SET AUTOCOMMIT=TRUE|FALSE, SHOW AUTOCOMMIT, SET - * TRANSACTION READ ONLY, etc) will return either a {@link ResultSet} or {@link - * ResultType#NO_RESULT}, depending on the type of statement (SHOW or SET) - *
    - * - * @param statement The statement to execute - * @return the result of the statement - */ - StatementResult execute(Statement statement); - - /** - * Executes the given statement as a query and returns the result as a {@link ResultSet}. This - * method blocks and waits for a response from Spanner. If the statement does not contain a valid - * query, the method will throw a {@link SpannerException}. - * - * @param query The query statement to execute - * @param options the options to configure the query - * @return a {@link ResultSet} with the results of the query - */ - ResultSet executeQuery(Statement query, QueryOption... options); - - /** - * Analyzes a query and returns query plan and/or query execution statistics information. - * - *

    The query plan and query statistics information is contained in {@link - * com.google.spanner.v1.ResultSetStats} that can be accessed by calling {@link - * ResultSet#getStats()} on the returned {@code ResultSet}. - * - *

    -   * 
    -   * {@code
    -   * ResultSet resultSet =
    -   *     connection.analyzeQuery(
    -   *         Statement.of("SELECT SingerId, AlbumId, MarketingBudget FROM Albums"),
    -   *         ReadContext.QueryAnalyzeMode.PROFILE);
    -   * while (resultSet.next()) {
    -   *   // Discard the results. We're only processing because getStats() below requires it.
    -   * }
    -   * ResultSetStats stats = resultSet.getStats();
    -   * }
    -   * 
    -   * 
    - * - * @param query the query statement to execute - * @param queryMode the mode in which to execute the query - */ - ResultSet analyzeQuery(Statement query, QueryAnalyzeMode queryMode); - - /** - * Executes the given statement as a DML statement. If the statement does not contain a valid DML - * statement, the method will throw a {@link SpannerException}. - * - * @param update The update statement to execute - * @return the number of records that were inserted/updated/deleted by this statement - */ - long executeUpdate(Statement update); - - /** - * Executes a list of DML statements in a single request. The statements will be executed in order - * and the semantics is the same as if each statement is executed by {@link - * Connection#executeUpdate(Statement)} in a loop. This method returns an array of long integers, - * each representing the number of rows modified by each statement. - * - *

    If an individual statement fails, execution stops and a {@code SpannerBatchUpdateException} - * is returned, which includes the error and the number of rows affected by the statements that - * are run prior to the error. - * - *

    For example, if statements contains 3 statements, and the 2nd one is not a valid DML. This - * method throws a {@code SpannerBatchUpdateException} that contains the error message from the - * 2nd statement, and an array of length 1 that contains the number of rows modified by the 1st - * statement. The 3rd statement will not run. Executes the given statements as DML statements in - * one batch. If one of the statements does not contain a valid DML statement, the method will - * throw a {@link SpannerException}. - * - * @param updates The update statements that will be executed as one batch. - * @return an array containing the update counts per statement. - */ - long[] executeBatchUpdate(Iterable updates); - - /** - * Writes the specified mutation directly to the database and commits the change. The value is - * readable after the successful completion of this method. Writing multiple mutations to a - * database by calling this method multiple times mode is inefficient, as each call will need a - * round trip to the database. Instead, you should consider writing the mutations together by - * calling {@link Connection#write(Iterable)}. - * - *

    Calling this method is only allowed in autocommit mode. See {@link - * Connection#bufferedWrite(Iterable)} for writing mutations in transactions. - * - * @param mutation The {@link Mutation} to write to the database - * @throws SpannerException if the {@link Connection} is not in autocommit mode - */ - void write(Mutation mutation); - - /** - * Writes the specified mutations directly to the database and commits the changes. The values are - * readable after the successful completion of this method. - * - *

    Calling this method is only allowed in autocommit mode. See {@link - * Connection#bufferedWrite(Iterable)} for writing mutations in transactions. - * - * @param mutations The {@link Mutation}s to write to the database - * @throws SpannerException if the {@link Connection} is not in autocommit mode - */ - void write(Iterable mutations); - - /** - * Buffers the given mutation locally on the current transaction of this {@link Connection}. The - * mutation will be written to the database at the next call to {@link Connection#commit()}. The - * value will not be readable on this {@link Connection} before the transaction is committed. - * - *

    Calling this method is only allowed when not in autocommit mode. See {@link - * Connection#write(Mutation)} for writing mutations in autocommit mode. - * - * @param mutation the {@link Mutation} to buffer for writing to the database on the next commit - * @throws SpannerException if the {@link Connection} is in autocommit mode - */ - void bufferedWrite(Mutation mutation); - - /** - * Buffers the given mutations locally on the current transaction of this {@link Connection}. The - * mutations will be written to the database at the next call to {@link Connection#commit()}. The - * values will not be readable on this {@link Connection} before the transaction is committed. - * - *

    Calling this method is only allowed when not in autocommit mode. See {@link - * Connection#write(Iterable)} for writing mutations in autocommit mode. - * - * @param mutations the {@link Mutation}s to buffer for writing to the database on the next commit - * @throws SpannerException if the {@link Connection} is in autocommit mode - */ - void bufferedWrite(Iterable mutations); -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java deleted file mode 100644 index 2a83fca42bbf..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionImpl.java +++ /dev/null @@ -1,1018 +0,0 @@ -/* - * Copyright 2019 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.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.jdbc.StatementExecutor.StatementTimeout; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Stack; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import org.threeten.bp.Instant; - -/** Implementation for {@link Connection}, the generic Spanner connection API (not JDBC). */ -class ConnectionImpl implements Connection { - private static final String CLOSED_ERROR_MSG = "This connection is closed"; - private static final String ONLY_ALLOWED_IN_AUTOCOMMIT = - "This method may only be called while in autocommit mode"; - private static final String NOT_ALLOWED_IN_AUTOCOMMIT = - "This method may not be called while in autocommit mode"; - - /** - * Exception that is used to register the stacktrace of the code that opened a {@link Connection}. - * This exception is logged if the application closes without first closing the connection. - */ - static class LeakedConnectionException extends RuntimeException { - private static final long serialVersionUID = 7119433786832158700L; - - private LeakedConnectionException() { - super("Connection was opened at " + Instant.now()); - } - } - - private volatile LeakedConnectionException leakedException = new LeakedConnectionException(); - private final SpannerPool spannerPool; - private final StatementParser parser = StatementParser.INSTANCE; - /** - * The {@link ConnectionStatementExecutor} is responsible for translating parsed {@link - * ClientSideStatement}s into actual method calls on this {@link ConnectionImpl}. I.e. the {@link - * ClientSideStatement} 'SET AUTOCOMMIT ON' will be translated into the method call {@link - * ConnectionImpl#setAutocommit(boolean)} with value true. - */ - private final ConnectionStatementExecutor connectionStatementExecutor = - new ConnectionStatementExecutorImpl(this); - - /** Simple thread factory that is used for fire-and-forget rollbacks. */ - static final class DaemonThreadFactory implements ThreadFactory { - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setName("connection-rollback-executor"); - t.setDaemon(true); - return t; - } - } - - /** - * Statements are executed using a separate thread in order to be able to cancel these. Statements - * are automatically cancelled if the configured {@link ConnectionImpl#statementTimeout} is - * exceeded. In autocommit mode, the connection will try to rollback the effects of an update - * statement, but this is not guaranteed to actually succeed. - */ - private final StatementExecutor statementExecutor; - - /** - * The {@link ConnectionOptions} that were used to create this {@link ConnectionImpl}. This is - * retained as it is used for getting a {@link Spanner} object and removing this connection from - * the {@link SpannerPool}. - */ - private final ConnectionOptions options; - - /** The supported batch modes. */ - enum BatchMode { - NONE, - DDL, - DML; - } - - /** - * This query option is used internally to indicate that a query is executed by the library itself - * to fetch metadata. These queries are specifically allowed to be executed even when a DDL batch - * is active. - */ - static final class InternalMetadataQuery implements QueryOption { - static final InternalMetadataQuery INSTANCE = new InternalMetadataQuery(); - - private InternalMetadataQuery() {} - } - - /** The combination of all transaction modes and batch modes. */ - enum UnitOfWorkType { - READ_ONLY_TRANSACTION { - @Override - TransactionMode getTransactionMode() { - return TransactionMode.READ_ONLY_TRANSACTION; - } - }, - READ_WRITE_TRANSACTION { - @Override - TransactionMode getTransactionMode() { - return TransactionMode.READ_WRITE_TRANSACTION; - } - }, - DML_BATCH { - @Override - TransactionMode getTransactionMode() { - return TransactionMode.READ_WRITE_TRANSACTION; - } - }, - DDL_BATCH { - @Override - TransactionMode getTransactionMode() { - return null; - } - }; - - abstract TransactionMode getTransactionMode(); - - static UnitOfWorkType of(TransactionMode transactionMode) { - switch (transactionMode) { - case READ_ONLY_TRANSACTION: - return UnitOfWorkType.READ_ONLY_TRANSACTION; - case READ_WRITE_TRANSACTION: - return UnitOfWorkType.READ_WRITE_TRANSACTION; - default: - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "Unknown transaction mode: " + transactionMode); - } - } - } - - private StatementExecutor.StatementTimeout statementTimeout = - new StatementExecutor.StatementTimeout(); - private boolean closed = false; - - private final Spanner spanner; - private DdlClient ddlClient; - private DatabaseClient dbClient; - private boolean autocommit; - private boolean readOnly; - - private UnitOfWork currentUnitOfWork = null; - /** - * The {@link ConnectionImpl#inTransaction} field is only used in autocommit mode to indicate that - * the user has explicitly started a transaction. - */ - private boolean inTransaction = false; - /** - * This field is used to indicate that a transaction begin has been indicated. This is done by - * calling beginTransaction or by setting a transaction property while not in autocommit mode. - */ - private boolean transactionBeginMarked = false; - - private BatchMode batchMode; - private UnitOfWorkType unitOfWorkType; - private final Stack transactionStack = new Stack<>(); - private boolean retryAbortsInternally; - private final List transactionRetryListeners = new ArrayList<>(); - private AutocommitDmlMode autocommitDmlMode = AutocommitDmlMode.TRANSACTIONAL; - private TimestampBound readOnlyStaleness = TimestampBound.strong(); - private QueryOptions queryOptions = QueryOptions.getDefaultInstance(); - - /** Create a connection and register it in the SpannerPool. */ - ConnectionImpl(ConnectionOptions options) { - Preconditions.checkNotNull(options); - this.statementExecutor = new StatementExecutor(options.getStatementExecutionInterceptors()); - this.spannerPool = SpannerPool.INSTANCE; - this.options = options; - this.spanner = spannerPool.getSpanner(options, this); - this.dbClient = spanner.getDatabaseClient(options.getDatabaseId()); - this.retryAbortsInternally = options.isRetryAbortsInternally(); - this.readOnly = options.isReadOnly(); - this.autocommit = options.isAutocommit(); - this.queryOptions = this.queryOptions.toBuilder().mergeFrom(options.getQueryOptions()).build(); - this.ddlClient = createDdlClient(); - setDefaultTransactionOptions(); - } - - /** Constructor only for test purposes. */ - @VisibleForTesting - ConnectionImpl( - ConnectionOptions options, - SpannerPool spannerPool, - DdlClient ddlClient, - DatabaseClient dbClient) { - Preconditions.checkNotNull(options); - Preconditions.checkNotNull(spannerPool); - Preconditions.checkNotNull(ddlClient); - Preconditions.checkNotNull(dbClient); - this.statementExecutor = - new StatementExecutor(Collections.emptyList()); - this.spannerPool = spannerPool; - this.options = options; - this.spanner = spannerPool.getSpanner(options, this); - this.ddlClient = ddlClient; - this.dbClient = dbClient; - setReadOnly(options.isReadOnly()); - setAutocommit(options.isAutocommit()); - setDefaultTransactionOptions(); - } - - private DdlClient createDdlClient() { - return DdlClient.newBuilder() - .setDatabaseAdminClient(spanner.getDatabaseAdminClient()) - .setInstanceId(options.getInstanceId()) - .setDatabaseName(options.getDatabaseName()) - .build(); - } - - @Override - public void close() { - if (!isClosed()) { - try { - if (isTransactionStarted()) { - try { - rollback(); - } catch (Exception e) { - // Ignore as we are closing the connection. - } - } - statementExecutor.shutdownNow(); - spannerPool.removeConnection(options, this); - leakedException = null; - } finally { - this.closed = true; - } - } - } - - /** Get the current unit-of-work type of this connection. */ - UnitOfWorkType getUnitOfWorkType() { - return unitOfWorkType; - } - - /** Get the current batch mode of this connection. */ - BatchMode getBatchMode() { - return batchMode; - } - - /** @return true if this connection is in a batch. */ - boolean isInBatch() { - return batchMode != BatchMode.NONE; - } - - /** Get the call stack from when the {@link Connection} was opened. */ - LeakedConnectionException getLeakedException() { - return leakedException; - } - - @Override - public boolean isClosed() { - return closed; - } - - @Override - public void setAutocommit(boolean autocommit) { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set autocommit while in a batch"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), "Cannot set autocommit while a transaction is active"); - ConnectionPreconditions.checkState( - !(isAutocommit() && isInTransaction()), - "Cannot set autocommit while in a temporary transaction"); - ConnectionPreconditions.checkState( - !transactionBeginMarked, "Cannot set autocommit when a transaction has begun"); - this.autocommit = autocommit; - clearLastTransactionAndSetDefaultTransactionOptions(); - // Reset the readOnlyStaleness value if it is no longer compatible with the new autocommit - // value. - if (!autocommit - && (readOnlyStaleness.getMode() == Mode.MAX_STALENESS - || readOnlyStaleness.getMode() == Mode.MIN_READ_TIMESTAMP)) { - readOnlyStaleness = TimestampBound.strong(); - } - } - - @Override - public boolean isAutocommit() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return internalIsAutocommit(); - } - - private boolean internalIsAutocommit() { - return this.autocommit; - } - - @Override - public void setReadOnly(boolean readOnly) { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set read-only while in a batch"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), "Cannot set read-only while a transaction is active"); - ConnectionPreconditions.checkState( - !(isAutocommit() && isInTransaction()), - "Cannot set read-only while in a temporary transaction"); - ConnectionPreconditions.checkState( - !transactionBeginMarked, "Cannot set read-only when a transaction has begun"); - this.readOnly = readOnly; - clearLastTransactionAndSetDefaultTransactionOptions(); - } - - @Override - public boolean isReadOnly() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.readOnly; - } - - private void clearLastTransactionAndSetDefaultTransactionOptions() { - setDefaultTransactionOptions(); - this.currentUnitOfWork = null; - } - - @Override - public void setAutocommitDmlMode(AutocommitDmlMode mode) { - Preconditions.checkNotNull(mode); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "Cannot set autocommit DML mode while in a batch"); - ConnectionPreconditions.checkState( - !isInTransaction() && isAutocommit(), - "Cannot set autocommit DML mode while not in autocommit mode or while a transaction is active"); - ConnectionPreconditions.checkState( - !isReadOnly(), "Cannot set autocommit DML mode for a read-only connection"); - this.autocommitDmlMode = mode; - } - - @Override - public AutocommitDmlMode getAutocommitDmlMode() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "Cannot get autocommit DML mode while in a batch"); - return this.autocommitDmlMode; - } - - @Override - public void setReadOnlyStaleness(TimestampBound staleness) { - Preconditions.checkNotNull(staleness); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isBatchActive(), "Cannot set read-only while in a batch"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), - "Cannot set read-only staleness when a transaction has been started"); - if (staleness.getMode() == Mode.MAX_STALENESS - || staleness.getMode() == Mode.MIN_READ_TIMESTAMP) { - // These values are only allowed in autocommit mode. - ConnectionPreconditions.checkState( - isAutocommit() && !inTransaction, - "MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode"); - } - this.readOnlyStaleness = staleness; - } - - @Override - public TimestampBound getReadOnlyStaleness() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isBatchActive(), "Cannot get read-only while in a batch"); - return this.readOnlyStaleness; - } - - @Override - public void setOptimizerVersion(String optimizerVersion) { - Preconditions.checkNotNull(optimizerVersion); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - this.queryOptions = queryOptions.toBuilder().setOptimizerVersion(optimizerVersion).build(); - } - - @Override - public String getOptimizerVersion() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.queryOptions.getOptimizerVersion(); - } - - @Override - public void setStatementTimeout(long timeout, TimeUnit unit) { - Preconditions.checkArgument(timeout > 0L, "Zero or negative timeout values are not allowed"); - Preconditions.checkArgument( - StatementTimeout.isValidTimeoutUnit(unit), - "Time unit must be one of NANOSECONDS, MICROSECONDS, MILLISECONDS or SECONDS"); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - this.statementTimeout.setTimeoutValue(timeout, unit); - } - - @Override - public void clearStatementTimeout() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - this.statementTimeout.clearTimeoutValue(); - } - - @Override - public long getStatementTimeout(TimeUnit unit) { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - Preconditions.checkArgument( - StatementTimeout.isValidTimeoutUnit(unit), - "Time unit must be one of NANOSECONDS, MICROSECONDS, MILLISECONDS or SECONDS"); - return this.statementTimeout.getTimeoutValue(unit); - } - - @Override - public boolean hasStatementTimeout() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.statementTimeout.hasTimeout(); - } - - @Override - public void cancel() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - if (this.currentUnitOfWork != null) { - currentUnitOfWork.cancel(); - } - } - - @Override - public TransactionMode getTransactionMode() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isDdlBatchActive(), "This connection is in a DDL batch"); - ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); - return unitOfWorkType.getTransactionMode(); - } - - @Override - public void setTransactionMode(TransactionMode transactionMode) { - Preconditions.checkNotNull(transactionMode); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "Cannot set transaction mode while in a batch"); - ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), - "The transaction mode cannot be set after the transaction has started"); - ConnectionPreconditions.checkState( - !isReadOnly() || transactionMode == TransactionMode.READ_ONLY_TRANSACTION, - "The transaction mode can only be READ_ONLY when the connection is in read_only mode"); - - this.transactionBeginMarked = true; - this.unitOfWorkType = UnitOfWorkType.of(transactionMode); - } - - /** - * Throws an {@link SpannerException} with code {@link ErrorCode#FAILED_PRECONDITION} if the - * current state of this connection does not allow changing the setting for retryAbortsInternally. - */ - private void checkSetRetryAbortsInternallyAvailable() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); - ConnectionPreconditions.checkState( - getTransactionMode() == TransactionMode.READ_WRITE_TRANSACTION, - "RetryAbortsInternally is only available for read-write transactions"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), - "RetryAbortsInternally cannot be set after the transaction has started"); - } - - @Override - public boolean isRetryAbortsInternally() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return retryAbortsInternally; - } - - @Override - public void setRetryAbortsInternally(boolean retryAbortsInternally) { - checkSetRetryAbortsInternallyAvailable(); - this.retryAbortsInternally = retryAbortsInternally; - } - - @Override - public void addTransactionRetryListener(TransactionRetryListener listener) { - Preconditions.checkNotNull(listener); - transactionRetryListeners.add(listener); - } - - @Override - public boolean removeTransactionRetryListener(TransactionRetryListener listener) { - Preconditions.checkNotNull(listener); - return transactionRetryListeners.remove(listener); - } - - @Override - public Iterator getTransactionRetryListeners() { - return Collections.unmodifiableList(transactionRetryListeners).iterator(); - } - - @Override - public boolean isInTransaction() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return internalIsInTransaction(); - } - - /** Returns true if this connection currently is in a transaction (and not a batch). */ - private boolean internalIsInTransaction() { - return !isDdlBatchActive() && (!internalIsAutocommit() || inTransaction); - } - - @Override - public boolean isTransactionStarted() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return internalIsTransactionStarted(); - } - - private boolean internalIsTransactionStarted() { - if (internalIsAutocommit() && !inTransaction) { - return false; - } - return internalIsInTransaction() - && this.currentUnitOfWork != null - && this.currentUnitOfWork.getState() == UnitOfWorkState.STARTED; - } - - @Override - public Timestamp getReadTimestamp() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - this.currentUnitOfWork != null, "There is no transaction on this connection"); - return this.currentUnitOfWork.getReadTimestamp(); - } - - Timestamp getReadTimestampOrNull() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.currentUnitOfWork == null ? null : this.currentUnitOfWork.getReadTimestampOrNull(); - } - - @Override - public Timestamp getCommitTimestamp() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - this.currentUnitOfWork != null, "There is no transaction on this connection"); - return this.currentUnitOfWork.getCommitTimestamp(); - } - - Timestamp getCommitTimestampOrNull() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.currentUnitOfWork == null - ? null - : this.currentUnitOfWork.getCommitTimestampOrNull(); - } - - /** Resets this connection to its default transaction options. */ - private void setDefaultTransactionOptions() { - if (transactionStack.isEmpty()) { - unitOfWorkType = - isReadOnly() - ? UnitOfWorkType.READ_ONLY_TRANSACTION - : UnitOfWorkType.READ_WRITE_TRANSACTION; - batchMode = BatchMode.NONE; - } else { - popUnitOfWorkFromTransactionStack(); - } - } - - @Override - public void beginTransaction() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "This connection has an active batch and cannot begin a transaction"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), - "Beginning a new transaction is not allowed when a transaction is already running"); - ConnectionPreconditions.checkState(!transactionBeginMarked, "A transaction has already begun"); - - transactionBeginMarked = true; - clearLastTransactionAndSetDefaultTransactionOptions(); - if (isAutocommit()) { - inTransaction = true; - } - } - - /** Internal interface for ending a transaction (commit/rollback). */ - private static interface EndTransactionMethod { - public void end(UnitOfWork t); - } - - private static final class Commit implements EndTransactionMethod { - @Override - public void end(UnitOfWork t) { - t.commit(); - } - } - - private final Commit commit = new Commit(); - - @Override - public void commit() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - endCurrentTransaction(commit); - } - - private static final class Rollback implements EndTransactionMethod { - @Override - public void end(UnitOfWork t) { - t.rollback(); - } - } - - private final Rollback rollback = new Rollback(); - - @Override - public void rollback() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - endCurrentTransaction(rollback); - } - - private void endCurrentTransaction(EndTransactionMethod endTransactionMethod) { - ConnectionPreconditions.checkState(!isBatchActive(), "This connection has an active batch"); - ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); - try { - if (isTransactionStarted()) { - endTransactionMethod.end(getCurrentUnitOfWorkOrStartNewUnitOfWork()); - } else { - this.currentUnitOfWork = null; - } - } finally { - transactionBeginMarked = false; - if (isAutocommit()) { - inTransaction = false; - } - setDefaultTransactionOptions(); - } - } - - @Override - public StatementResult execute(Statement statement) { - Preconditions.checkNotNull(statement); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(statement, this.queryOptions); - switch (parsedStatement.getType()) { - case CLIENT_SIDE: - return parsedStatement - .getClientSideStatement() - .execute(connectionStatementExecutor, parsedStatement.getSqlWithoutComments()); - case QUERY: - return StatementResultImpl.of(internalExecuteQuery(parsedStatement, AnalyzeMode.NONE)); - case UPDATE: - return StatementResultImpl.of(internalExecuteUpdate(parsedStatement)); - case DDL: - executeDdl(parsedStatement); - return StatementResultImpl.noResult(); - case UNKNOWN: - default: - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Unknown statement: " + parsedStatement.getSqlWithoutComments()); - } - - @Override - public ResultSet executeQuery(Statement query, QueryOption... options) { - return parseAndExecuteQuery(query, AnalyzeMode.NONE, options); - } - - @Override - public ResultSet analyzeQuery(Statement query, QueryAnalyzeMode queryMode) { - Preconditions.checkNotNull(queryMode); - return parseAndExecuteQuery(query, AnalyzeMode.of(queryMode)); - } - - /** - * Parses the given statement as a query and executes it. Throws a {@link SpannerException} if the - * statement is not a query. - */ - private ResultSet parseAndExecuteQuery( - Statement query, AnalyzeMode analyzeMode, QueryOption... options) { - Preconditions.checkNotNull(query); - Preconditions.checkNotNull(analyzeMode); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(query, this.queryOptions); - if (parsedStatement.isQuery()) { - switch (parsedStatement.getType()) { - case CLIENT_SIDE: - return parsedStatement - .getClientSideStatement() - .execute(connectionStatementExecutor, parsedStatement.getSqlWithoutComments()) - .getResultSet(); - case QUERY: - return internalExecuteQuery(parsedStatement, analyzeMode, options); - case UPDATE: - case DDL: - case UNKNOWN: - default: - } - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Statement is not a query: " + parsedStatement.getSqlWithoutComments()); - } - - @Override - public long executeUpdate(Statement update) { - Preconditions.checkNotNull(update); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(update); - if (parsedStatement.isUpdate()) { - switch (parsedStatement.getType()) { - case UPDATE: - return internalExecuteUpdate(parsedStatement); - case CLIENT_SIDE: - case QUERY: - case DDL: - case UNKNOWN: - default: - } - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); - } - - @Override - public long[] executeBatchUpdate(Iterable updates) { - Preconditions.checkNotNull(updates); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - // Check that there are only DML statements in the input. - List parsedStatements = new LinkedList<>(); - for (Statement update : updates) { - ParsedStatement parsedStatement = parser.parse(update); - if (parsedStatement.isUpdate()) { - switch (parsedStatement.getType()) { - case UPDATE: - parsedStatements.add(parsedStatement); - break; - case CLIENT_SIDE: - case QUERY: - case DDL: - case UNKNOWN: - default: - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "The batch update list contains a statement that is not an update statement: " - + parsedStatement.getSqlWithoutComments()); - } - } - } - return internalExecuteBatchUpdate(parsedStatements); - } - - private ResultSet internalExecuteQuery( - final ParsedStatement statement, - final AnalyzeMode analyzeMode, - final QueryOption... options) { - Preconditions.checkArgument( - statement.getType() == StatementType.QUERY, "Statement must be a query"); - UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); - try { - return transaction.executeQuery(statement, analyzeMode, options); - } catch (SpannerException e) { - // In case of a timed out or cancelled query we need to replace the executor to ensure that we - // have an executor that is not busy executing a statement. Although we try to cancel the - // current statement, it is not guaranteed to actually stop the execution directly. - if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED - || e.getErrorCode() == ErrorCode.CANCELLED) { - this.statementExecutor.recreate(); - } - throw e; - } - } - - private long internalExecuteUpdate(final ParsedStatement update) { - Preconditions.checkArgument( - update.getType() == StatementType.UPDATE, "Statement must be an update"); - UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); - try { - return transaction.executeUpdate(update); - } catch (SpannerException e) { - // In case of a timed out or cancelled query we need to replace the executor to ensure that we - // have an executor that is not busy executing a statement. Although we try to cancel the - // current statement, it is not guaranteed to actually stop the execution directly. - if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED - || e.getErrorCode() == ErrorCode.CANCELLED) { - this.statementExecutor.recreate(); - } - throw e; - } - } - - private long[] internalExecuteBatchUpdate(final List updates) { - UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork(); - try { - return transaction.executeBatchUpdate(updates); - } catch (SpannerException e) { - // In case of a timed out or cancelled query we need to replace the executor to ensure that we - // have an executor that is not busy executing a statement. Although we try to cancel the - // current statement, it is not guaranteed to actually stop the execution directly. - if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED - || e.getErrorCode() == ErrorCode.CANCELLED) { - this.statementExecutor.recreate(); - } - throw e; - } - } - - /** - * Returns the current {@link UnitOfWork} of this connection, or creates a new one based on the - * current transaction settings of the connection and returns that. - */ - @VisibleForTesting - UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { - if (this.currentUnitOfWork == null || !this.currentUnitOfWork.isActive()) { - this.currentUnitOfWork = createNewUnitOfWork(); - } - return this.currentUnitOfWork; - } - - private UnitOfWork createNewUnitOfWork() { - if (isAutocommit() && !isInTransaction() && !isInBatch()) { - return SingleUseTransaction.newBuilder() - .setDdlClient(ddlClient) - .setDatabaseClient(dbClient) - .setReadOnly(isReadOnly()) - .setReadOnlyStaleness(readOnlyStaleness) - .setAutocommitDmlMode(autocommitDmlMode) - .setStatementTimeout(statementTimeout) - .withStatementExecutor(statementExecutor) - .build(); - } else { - switch (getUnitOfWorkType()) { - case READ_ONLY_TRANSACTION: - return ReadOnlyTransaction.newBuilder() - .setDatabaseClient(dbClient) - .setReadOnlyStaleness(readOnlyStaleness) - .setStatementTimeout(statementTimeout) - .withStatementExecutor(statementExecutor) - .build(); - case READ_WRITE_TRANSACTION: - return ReadWriteTransaction.newBuilder() - .setDatabaseClient(dbClient) - .setRetryAbortsInternally(retryAbortsInternally) - .setTransactionRetryListeners(transactionRetryListeners) - .setStatementTimeout(statementTimeout) - .withStatementExecutor(statementExecutor) - .build(); - case DML_BATCH: - // A DML batch can run inside the current transaction. It should therefore only - // temporarily replace the current transaction. - pushCurrentUnitOfWorkToTransactionStack(); - return DmlBatch.newBuilder() - .setTransaction(currentUnitOfWork) - .setStatementTimeout(statementTimeout) - .withStatementExecutor(statementExecutor) - .build(); - case DDL_BATCH: - return DdlBatch.newBuilder() - .setDdlClient(ddlClient) - .setDatabaseClient(dbClient) - .setStatementTimeout(statementTimeout) - .withStatementExecutor(statementExecutor) - .build(); - default: - } - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "This connection does not have an active transaction and the state of this connection does not allow any new transactions to be started"); - } - - /** Pushes the current unit of work to the stack of nested transactions. */ - private void pushCurrentUnitOfWorkToTransactionStack() { - Preconditions.checkState(currentUnitOfWork != null, "There is no current transaction"); - transactionStack.push(currentUnitOfWork); - } - - /** Set the {@link UnitOfWork} of this connection back to the previous {@link UnitOfWork}. */ - private void popUnitOfWorkFromTransactionStack() { - Preconditions.checkState( - !transactionStack.isEmpty(), "There is no unit of work in the transaction stack"); - this.currentUnitOfWork = transactionStack.pop(); - } - - private void executeDdl(ParsedStatement ddl) { - getCurrentUnitOfWorkOrStartNewUnitOfWork().executeDdl(ddl); - } - - @Override - public void write(Mutation mutation) { - Preconditions.checkNotNull(mutation); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(isAutocommit(), ONLY_ALLOWED_IN_AUTOCOMMIT); - getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutation); - } - - @Override - public void write(Iterable mutations) { - Preconditions.checkNotNull(mutations); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(isAutocommit(), ONLY_ALLOWED_IN_AUTOCOMMIT); - getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutations); - } - - @Override - public void bufferedWrite(Mutation mutation) { - Preconditions.checkNotNull(mutation); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isAutocommit(), NOT_ALLOWED_IN_AUTOCOMMIT); - getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutation); - } - - @Override - public void bufferedWrite(Iterable mutations) { - Preconditions.checkNotNull(mutations); - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(!isAutocommit(), NOT_ALLOWED_IN_AUTOCOMMIT); - getCurrentUnitOfWorkOrStartNewUnitOfWork().write(mutations); - } - - @Override - public void startBatchDdl() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "Cannot start a DDL batch when a batch is already active"); - ConnectionPreconditions.checkState( - !isReadOnly(), "Cannot start a DDL batch when the connection is in read-only mode"); - ConnectionPreconditions.checkState( - !isTransactionStarted(), "Cannot start a DDL batch while a transaction is active"); - ConnectionPreconditions.checkState( - !(isAutocommit() && isInTransaction()), - "Cannot start a DDL batch while in a temporary transaction"); - ConnectionPreconditions.checkState( - !transactionBeginMarked, "Cannot start a DDL batch when a transaction has begun"); - this.batchMode = BatchMode.DDL; - this.unitOfWorkType = UnitOfWorkType.DDL_BATCH; - this.currentUnitOfWork = createNewUnitOfWork(); - } - - @Override - public void startBatchDml() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState( - !isBatchActive(), "Cannot start a DML batch when a batch is already active"); - ConnectionPreconditions.checkState( - !isReadOnly(), "Cannot start a DML batch when the connection is in read-only mode"); - ConnectionPreconditions.checkState( - !(isInTransaction() && getTransactionMode() == TransactionMode.READ_ONLY_TRANSACTION), - "Cannot start a DML batch when a read-only transaction is in progress"); - // Make sure that there is a current unit of work that the batch can use. - getCurrentUnitOfWorkOrStartNewUnitOfWork(); - // Then create the DML batch. - this.batchMode = BatchMode.DML; - this.unitOfWorkType = UnitOfWorkType.DML_BATCH; - this.currentUnitOfWork = createNewUnitOfWork(); - } - - @Override - public long[] runBatch() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(isBatchActive(), "This connection has no active batch"); - try { - if (this.currentUnitOfWork != null) { - return this.currentUnitOfWork.runBatch(); - } - return new long[0]; - } finally { - this.batchMode = BatchMode.NONE; - setDefaultTransactionOptions(); - } - } - - @Override - public void abortBatch() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ConnectionPreconditions.checkState(isBatchActive(), "This connection has no active batch"); - try { - if (this.currentUnitOfWork != null) { - this.currentUnitOfWork.abortBatch(); - } - } finally { - this.batchMode = BatchMode.NONE; - setDefaultTransactionOptions(); - } - } - - private boolean isBatchActive() { - return isDdlBatchActive() || isDmlBatchActive(); - } - - @Override - public boolean isDdlBatchActive() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.batchMode == BatchMode.DDL; - } - - @Override - public boolean isDmlBatchActive() { - ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - return this.batchMode == BatchMode.DML; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java deleted file mode 100644 index 4ec727cd9a76..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionOptions.java +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright 2019 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.auth.Credentials; -import com.google.auth.oauth2.AccessToken; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.auth.oauth2.ServiceAccountCredentials; -import com.google.cloud.NoCredentials; -import com.google.cloud.ServiceOptions; -import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.SpannerOptions; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Options for creating a {@link Connection} to a Google Cloud Spanner database. - * - *

    Usage: - * - *

    - * 
    - * {@code
    - * ConnectionOptions options = ConnectionOptions.newBuilder()
    - *       .setUri("cloudspanner:/projects/my_project_id/instances/my_instance_id/databases/my_database_name?autocommit=false")
    - *       .setCredentialsUrl("/home/cloudspanner-keys/my-key.json")
    - *       .build();
    - * try(Connection connection = options.getConnection()) {
    - *   try(ResultSet rs = connection.executeQuery(Statement.of("SELECT SingerId, AlbumId, MarketingBudget FROM Albums"))) {
    - *     while(rs.next()) {
    - *       // do something
    - *     }
    - *   }
    - * }
    - * }
    - * 
    - * 
    - */ -class ConnectionOptions { - /** Supported connection properties that can be included in the connection URI. */ - public static class ConnectionProperty { - private static final String[] BOOLEAN_VALUES = new String[] {"true", "false"}; - private final String name; - private final String description; - private final String defaultValue; - private final String[] validValues; - private final int hashCode; - - private static ConnectionProperty createStringProperty(String name, String description) { - return new ConnectionProperty(name, description, "", null); - } - - private static ConnectionProperty createBooleanProperty( - String name, String description, boolean defaultValue) { - return new ConnectionProperty( - name, description, String.valueOf(defaultValue), BOOLEAN_VALUES); - } - - private static ConnectionProperty createEmptyProperty(String name) { - return new ConnectionProperty(name, "", "", null); - } - - private ConnectionProperty( - String name, String description, String defaultValue, String[] validValues) { - Preconditions.checkNotNull(name); - Preconditions.checkNotNull(description); - Preconditions.checkNotNull(defaultValue); - this.name = name; - this.description = description; - this.defaultValue = defaultValue; - this.validValues = validValues; - this.hashCode = name.toLowerCase().hashCode(); - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof ConnectionProperty)) { - return false; - } - return ((ConnectionProperty) o).name.equalsIgnoreCase(this.name); - } - - /** @return the name of this connection property. */ - public String getName() { - return name; - } - - /** @return the description of this connection property. */ - public String getDescription() { - return description; - } - - /** @return the default value of this connection property. */ - public String getDefaultValue() { - return defaultValue; - } - - /** - * @return the valid values for this connection property. null indicates no - * restriction. - */ - public String[] getValidValues() { - return validValues; - } - } - - private static final boolean DEFAULT_USE_PLAIN_TEXT = false; - static final boolean DEFAULT_AUTOCOMMIT = true; - static final boolean DEFAULT_READONLY = false; - static final boolean DEFAULT_RETRY_ABORTS_INTERNALLY = true; - private static final String DEFAULT_CREDENTIALS = null; - private static final String DEFAULT_OAUTH_TOKEN = null; - private static final String DEFAULT_NUM_CHANNELS = null; - private static final String DEFAULT_USER_AGENT = null; - private static final String DEFAULT_OPTIMIZER_VERSION = ""; - - private static final String PLAIN_TEXT_PROTOCOL = "http:"; - private static final String HOST_PROTOCOL = "https:"; - private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; - /** Use plain text is only for local testing purposes. */ - private static final String USE_PLAIN_TEXT_PROPERTY_NAME = "usePlainText"; - /** Name of the 'autocommit' connection property. */ - public static final String AUTOCOMMIT_PROPERTY_NAME = "autocommit"; - /** Name of the 'readonly' connection property. */ - public static final String READONLY_PROPERTY_NAME = "readonly"; - /** Name of the 'retry aborts internally' connection property. */ - public static final String RETRY_ABORTS_INTERNALLY_PROPERTY_NAME = "retryAbortsInternally"; - /** Name of the 'credentials' connection property. */ - public static final String CREDENTIALS_PROPERTY_NAME = "credentials"; - /** - * OAuth token to use for authentication. Cannot be used in combination with a credentials file. - */ - public static final String OAUTH_TOKEN_PROPERTY_NAME = "oauthToken"; - /** Name of the 'numChannels' connection property. */ - public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels"; - /** Custom user agent string is only for other Google libraries. */ - private static final String USER_AGENT_PROPERTY_NAME = "userAgent"; - /** Query optimizer version to use for a connection. */ - private static final String OPTIMIZER_VERSION_PROPERTY_NAME = "optimizerVersion"; - - /** All valid connection properties. */ - public static final Set VALID_PROPERTIES = - Collections.unmodifiableSet( - new HashSet<>( - Arrays.asList( - ConnectionProperty.createBooleanProperty( - AUTOCOMMIT_PROPERTY_NAME, "", DEFAULT_AUTOCOMMIT), - ConnectionProperty.createBooleanProperty( - READONLY_PROPERTY_NAME, "", DEFAULT_READONLY), - ConnectionProperty.createBooleanProperty( - RETRY_ABORTS_INTERNALLY_PROPERTY_NAME, "", DEFAULT_RETRY_ABORTS_INTERNALLY), - ConnectionProperty.createStringProperty(CREDENTIALS_PROPERTY_NAME, ""), - ConnectionProperty.createStringProperty(OAUTH_TOKEN_PROPERTY_NAME, ""), - ConnectionProperty.createStringProperty(NUM_CHANNELS_PROPERTY_NAME, ""), - ConnectionProperty.createBooleanProperty( - USE_PLAIN_TEXT_PROPERTY_NAME, "", DEFAULT_USE_PLAIN_TEXT), - ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, ""), - ConnectionProperty.createStringProperty(OPTIMIZER_VERSION_PROPERTY_NAME, "")))); - - private static final Set INTERNAL_PROPERTIES = - Collections.unmodifiableSet( - new HashSet<>( - Arrays.asList( - ConnectionProperty.createStringProperty(USER_AGENT_PROPERTY_NAME, "")))); - private static final Set INTERNAL_VALID_PROPERTIES = - Sets.union(VALID_PROPERTIES, INTERNAL_PROPERTIES); - - /** - * Gets the default project-id for the current environment as defined by {@link - * ServiceOptions#getDefaultProjectId()}, and if none could be found, the project-id of the given - * credentials if it contains any. - * - * @param credentials The credentials to use to get the default project-id if none could be found - * in the environment. - * @return the default project-id. - */ - public static String getDefaultProjectId(Credentials credentials) { - String projectId = SpannerOptions.getDefaultProjectId(); - if (projectId == null - && credentials != null - && credentials instanceof ServiceAccountCredentials) { - projectId = ((ServiceAccountCredentials) credentials).getProjectId(); - } - return projectId; - } - - /** - * Closes all {@link Spanner} instances that have been opened by connections - * during the lifetime of this JVM. Call this method at the end of your application to free up - * resources. You must close all {@link Connection}s that have been opened by your application - * before calling this method. Failing to do so, will cause this method to throw a {@link - * SpannerException}. - * - *

    This method is also automatically called by a shutdown hook (see {@link - * Runtime#addShutdownHook(Thread)}) when the JVM is shutdown gracefully. - */ - public static void closeSpanner() { - SpannerPool.INSTANCE.checkAndCloseSpanners(); - } - - /** Builder for {@link ConnectionOptions} instances. */ - public static class Builder { - private String uri; - private String credentialsUrl; - private String oauthToken; - private Credentials credentials; - private List statementExecutionInterceptors = - Collections.emptyList(); - - private Builder() {} - - /** Spanner {@link ConnectionOptions} URI format. */ - public static final String SPANNER_URI_FORMAT = - "(?:cloudspanner:)(?//[\\w.-]+(?:\\.[\\w\\.-]+)*[\\w\\-\\._~:/?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=.]+)?/projects/(?(([a-z]|[-.:]|[0-9])+|(DEFAULT_PROJECT_ID)))(/instances/(?([a-z]|[-]|[0-9])+)(/databases/(?([a-z]|[-]|[_]|[0-9])+))?)?(?:[?|;].*)?"; - - private static final String SPANNER_URI_REGEX = "(?is)^" + SPANNER_URI_FORMAT + "$"; - private static final Pattern SPANNER_URI_PATTERN = Pattern.compile(SPANNER_URI_REGEX); - private static final String HOST_GROUP = "HOSTGROUP"; - private static final String PROJECT_GROUP = "PROJECTGROUP"; - private static final String INSTANCE_GROUP = "INSTANCEGROUP"; - private static final String DATABASE_GROUP = "DATABASEGROUP"; - private static final String DEFAULT_PROJECT_ID_PLACEHOLDER = "DEFAULT_PROJECT_ID"; - - private boolean isValidUri(String uri) { - return SPANNER_URI_PATTERN.matcher(uri).matches(); - } - - /** - * Sets the URI of the Cloud Spanner database to connect to. A connection URI must be specified - * in this format: - * - *

    -     * cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\?property-name=property-value[;property-name=property-value]*]?
    -     * 
    - * - * The property-value strings should be url-encoded. - * - *

    The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This - * placeholder will be replaced by the default project id of the environment that is requesting - * a connection. - * - *

    The supported properties are: - * - *

      - *
    • credentials (String): URL for the credentials file to use for the connection. This - * property is only used if no credentials have been specified using the {@link - * ConnectionOptions.Builder#setCredentialsUrl(String)} method. If you do not specify any - * credentials at all, the default credentials of the environment as returned by {@link - * GoogleCredentials#getApplicationDefault()} will be used. - *
    • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is - * true. - *
    • readonly (boolean): Sets the initial readonly mode for the connection. Default is - * false. - *
    • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the - * connection. Default is true. - *
    • optimizerVersion (string): Sets the query optimizer version to use for the connection. - *
    - * - * @param uri The URI of the Spanner database to connect to. - * @return this builder - */ - public Builder setUri(String uri) { - Preconditions.checkArgument( - isValidUri(uri), - "The specified URI is not a valid Cloud Spanner connection URI. Please specify a URI in the format \"cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\\?property-name=property-value[;property-name=property-value]*]?\""); - checkValidProperties(uri); - this.uri = uri; - return this; - } - - /** - * Sets the URL of the credentials file to use for this connection. The URL may be a reference - * to a file on the local file system, or to a file on Google Cloud Storage. References to - * Google Cloud Storage files are only allowed when the application is running on Google Cloud - * and the environment has access to the specified storage location. It also requires that the - * Google Cloud Storage client library is present on the class path. The Google Cloud Storage - * library is not automatically added as a dependency by the JDBC driver. - * - *

    If you do not specify a credentialsUrl (either by using this setter, or by specifying on - * the connection URI), the credentials returned by {@link - * GoogleCredentials#getApplicationDefault()} will be used for the connection. - * - * @param credentialsUrl A valid file or Google Cloud Storage URL for the credentials file to be - * used. - * @return this builder - */ - public Builder setCredentialsUrl(String credentialsUrl) { - this.credentialsUrl = credentialsUrl; - return this; - } - - /** - * Sets the OAuth token to use with this connection. The token must be a valid token with access - * to the resources (project/instance/database) that the connection will be accessing. This - * authentication method cannot be used in combination with a credentials file. If both an OAuth - * token and a credentials file is specified, the {@link #build()} method will throw an - * exception. - * - * @param oauthToken A valid OAuth token for the Google Cloud project that is used by this - * connection. - * @return this builder - */ - public Builder setOAuthToken(String oauthToken) { - this.oauthToken = oauthToken; - return this; - } - - @VisibleForTesting - Builder setStatementExecutionInterceptors(List interceptors) { - this.statementExecutionInterceptors = interceptors; - return this; - } - - @VisibleForTesting - Builder setCredentials(Credentials credentials) { - this.credentials = credentials; - return this; - } - - /** @return the {@link ConnectionOptions} */ - public ConnectionOptions build() { - Preconditions.checkState(this.uri != null, "Connection URI is required"); - return new ConnectionOptions(this); - } - } - - /** - * Create a {@link Builder} for {@link ConnectionOptions}. Use this method to create {@link - * ConnectionOptions} that can be used to obtain a {@link Connection}. - * - * @return a new {@link Builder} - */ - public static Builder newBuilder() { - return new Builder(); - } - - private final String uri; - private final String credentialsUrl; - private final String oauthToken; - - private final boolean usePlainText; - private final String host; - private final String projectId; - private final String instanceId; - private final String databaseName; - private final Credentials credentials; - private final Integer numChannels; - private final String userAgent; - private final QueryOptions queryOptions; - - private final boolean autocommit; - private final boolean readOnly; - private final boolean retryAbortsInternally; - private final List statementExecutionInterceptors; - - private ConnectionOptions(Builder builder) { - Matcher matcher = Builder.SPANNER_URI_PATTERN.matcher(builder.uri); - Preconditions.checkArgument( - matcher.find(), String.format("Invalid connection URI specified: %s", builder.uri)); - checkValidProperties(builder.uri); - - this.uri = builder.uri; - this.credentialsUrl = - builder.credentialsUrl != null ? builder.credentialsUrl : parseCredentials(builder.uri); - this.oauthToken = - builder.oauthToken != null ? builder.oauthToken : parseOAuthToken(builder.uri); - // Check that not both credentials and an OAuth token have been specified. - Preconditions.checkArgument( - (builder.credentials == null && this.credentialsUrl == null) || this.oauthToken == null, - "Cannot specify both credentials and an OAuth token."); - - this.usePlainText = parseUsePlainText(this.uri); - this.userAgent = parseUserAgent(this.uri); - QueryOptions.Builder queryOptionsBuilder = QueryOptions.newBuilder(); - queryOptionsBuilder.setOptimizerVersion(parseOptimizerVersion(this.uri)); - this.queryOptions = queryOptionsBuilder.build(); - - this.host = - matcher.group(Builder.HOST_GROUP) == null - ? DEFAULT_HOST - : (usePlainText ? PLAIN_TEXT_PROTOCOL : HOST_PROTOCOL) - + matcher.group(Builder.HOST_GROUP); - this.instanceId = matcher.group(Builder.INSTANCE_GROUP); - this.databaseName = matcher.group(Builder.DATABASE_GROUP); - // Using credentials on a plain text connection is not allowed, so if the user has not specified - // any credentials and is using a plain text connection, we should not try to get the - // credentials from the environment, but default to NoCredentials. - if (builder.credentials == null - && this.credentialsUrl == null - && this.oauthToken == null - && this.usePlainText) { - this.credentials = NoCredentials.getInstance(); - } else if (this.oauthToken != null) { - this.credentials = new GoogleCredentials(new AccessToken(oauthToken, null)); - } else { - this.credentials = - builder.credentials == null - ? getCredentialsService().createCredentials(this.credentialsUrl) - : builder.credentials; - } - String numChannelsValue = parseNumChannels(builder.uri); - if (numChannelsValue != null) { - try { - this.numChannels = Integer.valueOf(numChannelsValue); - } catch (NumberFormatException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Invalid numChannels value specified: " + numChannelsValue, - e); - } - } else { - this.numChannels = null; - } - - String projectId = matcher.group(Builder.PROJECT_GROUP); - if (Builder.DEFAULT_PROJECT_ID_PLACEHOLDER.equalsIgnoreCase(projectId)) { - projectId = getDefaultProjectId(this.credentials); - } - this.projectId = projectId; - - this.autocommit = parseAutocommit(this.uri); - this.readOnly = parseReadOnly(this.uri); - this.retryAbortsInternally = parseRetryAbortsInternally(this.uri); - this.statementExecutionInterceptors = - Collections.unmodifiableList(builder.statementExecutionInterceptors); - } - - @VisibleForTesting - CredentialsService getCredentialsService() { - return CredentialsService.INSTANCE; - } - - @VisibleForTesting - static boolean parseUsePlainText(String uri) { - String value = parseUriProperty(uri, USE_PLAIN_TEXT_PROPERTY_NAME); - return value != null ? Boolean.valueOf(value) : DEFAULT_USE_PLAIN_TEXT; - } - - @VisibleForTesting - static boolean parseAutocommit(String uri) { - String value = parseUriProperty(uri, AUTOCOMMIT_PROPERTY_NAME); - return value != null ? Boolean.valueOf(value) : DEFAULT_AUTOCOMMIT; - } - - @VisibleForTesting - static boolean parseReadOnly(String uri) { - String value = parseUriProperty(uri, READONLY_PROPERTY_NAME); - return value != null ? Boolean.valueOf(value) : DEFAULT_READONLY; - } - - @VisibleForTesting - static boolean parseRetryAbortsInternally(String uri) { - String value = parseUriProperty(uri, RETRY_ABORTS_INTERNALLY_PROPERTY_NAME); - return value != null ? Boolean.valueOf(value) : DEFAULT_RETRY_ABORTS_INTERNALLY; - } - - @VisibleForTesting - static String parseCredentials(String uri) { - String value = parseUriProperty(uri, CREDENTIALS_PROPERTY_NAME); - return value != null ? value : DEFAULT_CREDENTIALS; - } - - @VisibleForTesting - static String parseOAuthToken(String uri) { - String value = parseUriProperty(uri, OAUTH_TOKEN_PROPERTY_NAME); - return value != null ? value : DEFAULT_OAUTH_TOKEN; - } - - @VisibleForTesting - static String parseNumChannels(String uri) { - String value = parseUriProperty(uri, NUM_CHANNELS_PROPERTY_NAME); - return value != null ? value : DEFAULT_NUM_CHANNELS; - } - - @VisibleForTesting - static String parseUserAgent(String uri) { - String value = parseUriProperty(uri, USER_AGENT_PROPERTY_NAME); - return value != null ? value : DEFAULT_USER_AGENT; - } - - @VisibleForTesting - static String parseOptimizerVersion(String uri) { - String value = parseUriProperty(uri, OPTIMIZER_VERSION_PROPERTY_NAME); - return value != null ? value : DEFAULT_OPTIMIZER_VERSION; - } - - @VisibleForTesting - static String parseUriProperty(String uri, String property) { - Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); - Matcher matcher = pattern.matcher(uri); - if (matcher.find() && matcher.groupCount() == 1) { - return matcher.group(1); - } - return null; - } - - /** Check that only valid properties have been specified. */ - @VisibleForTesting - static void checkValidProperties(String uri) { - String invalidProperties = ""; - List properties = parseProperties(uri); - for (String property : properties) { - if (!INTERNAL_VALID_PROPERTIES.contains(ConnectionProperty.createEmptyProperty(property))) { - if (invalidProperties.length() > 0) { - invalidProperties = invalidProperties + ", "; - } - invalidProperties = invalidProperties + property; - } - } - Preconditions.checkArgument( - invalidProperties.isEmpty(), - "Invalid properties found in connection URI: " + invalidProperties.toString()); - } - - @VisibleForTesting - static List parseProperties(String uri) { - Pattern pattern = Pattern.compile("(?is)(?:\\?|;)(?.*?)=(?:.*?)"); - Matcher matcher = pattern.matcher(uri); - List res = new ArrayList<>(); - while (matcher.find() && matcher.group("PROPERTY") != null) { - res.add(matcher.group("PROPERTY")); - } - return res; - } - - /** - * Create a new {@link Connection} from this {@link ConnectionOptions}. Calling this method - * multiple times for the same {@link ConnectionOptions} will return multiple instances of {@link - * Connection}s to the same database. - * - * @return a new {@link Connection} to the database referenced by this {@link ConnectionOptions} - */ - public Connection getConnection() { - return new ConnectionImpl(this); - } - - /** The URI of this {@link ConnectionOptions} */ - public String getUri() { - return uri; - } - - /** The credentials URL of this {@link ConnectionOptions} */ - public String getCredentialsUrl() { - return credentialsUrl; - } - - /** The number of channels to use for the connection. */ - public Integer getNumChannels() { - return numChannels; - } - - /** The host and port number that this {@link ConnectionOptions} will connect to */ - public String getHost() { - return host; - } - - /** The Google Project ID that this {@link ConnectionOptions} will connect to */ - public String getProjectId() { - return projectId; - } - - /** The Spanner Instance ID that this {@link ConnectionOptions} will connect to */ - public String getInstanceId() { - return instanceId; - } - - /** The Spanner database name that this {@link ConnectionOptions} will connect to */ - public String getDatabaseName() { - return databaseName; - } - - /** The Spanner {@link DatabaseId} that this {@link ConnectionOptions} will connect to */ - public DatabaseId getDatabaseId() { - Preconditions.checkState(projectId != null, "Project ID is not specified"); - Preconditions.checkState(instanceId != null, "Instance ID is not specified"); - Preconditions.checkState(databaseName != null, "Database name is not specified"); - return DatabaseId.of(projectId, instanceId, databaseName); - } - - /** - * The {@link Credentials} of this {@link ConnectionOptions}. This is either the credentials - * specified in the credentialsUrl or the default Google application credentials - */ - public Credentials getCredentials() { - return credentials; - } - - /** The initial autocommit value for connections created by this {@link ConnectionOptions} */ - public boolean isAutocommit() { - return autocommit; - } - - /** The initial readonly value for connections created by this {@link ConnectionOptions} */ - public boolean isReadOnly() { - return readOnly; - } - - /** - * The initial retryAbortsInternally value for connections created by this {@link - * ConnectionOptions} - */ - public boolean isRetryAbortsInternally() { - return retryAbortsInternally; - } - - /** Use http instead of https. Only valid for (local) test servers. */ - boolean isUsePlainText() { - return usePlainText; - } - - /** - * The (custom) user agent string to use for this connection. If null, then the - * default JDBC user agent string will be used. - */ - String getUserAgent() { - return userAgent; - } - - /** The {@link QueryOptions} to use for the connection. */ - QueryOptions getQueryOptions() { - return queryOptions; - } - - /** Interceptors that should be executed after each statement */ - List getStatementExecutionInterceptors() { - return statementExecutionInterceptors; - } - - @Override - public String toString() { - return getUri(); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java deleted file mode 100644 index 02f3953352e2..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPreconditions.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import javax.annotation.Nullable; - -/** - * Static convenience methods that help a method or constructor in the Connection API to check - * whether it was invoked correctly. - */ -class ConnectionPreconditions { - /** - * Ensures the truth of an expression involving the state of the calling instance, but not - * involving any parameters to the calling method. - * - * @param expression a boolean expression - * @param errorMessage the exception message to use if the check fails; will be converted to a - * string using {@link String#valueOf(Object)}. - * @throws SpannerException with {@link ErrorCode#FAILED_PRECONDITION} if {@code expression} is - * false. - */ - static void checkState(boolean expression, @Nullable Object errorMessage) { - if (!expression) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, String.valueOf(errorMessage)); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java deleted file mode 100644 index 4de1f3f0cf43..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutor.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 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.TimestampBound; -import com.google.protobuf.Duration; - -/** - * The Cloud Spanner JDBC driver supports a number of client side statements that are interpreted by - * the driver and that can modify the current state of a connection, or report the current state of - * a connection. Each of the methods in this interface correspond with one such client side - * statement. - * - *

    The methods in this interface are called by the different {@link ClientSideStatement}s. These - * method calls are then forwarded into the appropriate method of a {@link Connection} instance. - * - *

    The client side statements are defined in the ClientSideStatements.json file. - */ -interface ConnectionStatementExecutor { - - StatementResult statementSetAutocommit(Boolean autocommit); - - StatementResult statementShowAutocommit(); - - StatementResult statementSetReadOnly(Boolean readOnly); - - StatementResult statementShowReadOnly(); - - StatementResult statementSetRetryAbortsInternally(Boolean retryAbortsInternally); - - StatementResult statementShowRetryAbortsInternally(); - - StatementResult statementSetAutocommitDmlMode(AutocommitDmlMode mode); - - StatementResult statementShowAutocommitDmlMode(); - - StatementResult statementSetStatementTimeout(Duration duration); - - StatementResult statementShowStatementTimeout(); - - StatementResult statementShowReadTimestamp(); - - StatementResult statementShowCommitTimestamp(); - - StatementResult statementSetReadOnlyStaleness(TimestampBound staleness); - - StatementResult statementShowReadOnlyStaleness(); - - StatementResult statementSetOptimizerVersion(String optimizerVersion); - - StatementResult statementShowOptimizerVersion(); - - StatementResult statementBeginTransaction(); - - StatementResult statementCommit(); - - StatementResult statementRollback(); - - StatementResult statementSetTransactionMode(TransactionMode mode); - - StatementResult statementStartBatchDdl(); - - StatementResult statementStartBatchDml(); - - StatementResult statementRunBatch(); - - StatementResult statementAbortBatch(); -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java deleted file mode 100644 index c8aa40d77a34..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorImpl.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2019 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 com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.ABORT_BATCH; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.BEGIN; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.COMMIT; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.ROLLBACK; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.RUN_BATCH; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_OPTIMIZER_VERSION; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READONLY; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_READ_ONLY_STALENESS; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_RETRY_ABORTS_INTERNALLY; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_STATEMENT_TIMEOUT; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SET_TRANSACTION_MODE; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_AUTOCOMMIT_DML_MODE; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_COMMIT_TIMESTAMP; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_VERSION; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READONLY; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_ONLY_STALENESS; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_READ_TIMESTAMP; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.SHOW_STATEMENT_TIMEOUT; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.START_BATCH_DDL; -import static com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType.START_BATCH_DML; -import static com.google.cloud.spanner.jdbc.StatementResultImpl.noResult; -import static com.google.cloud.spanner.jdbc.StatementResultImpl.resultSet; - -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.DurationValueGetter; -import com.google.common.base.Preconditions; -import com.google.protobuf.Duration; -import java.util.concurrent.TimeUnit; - -/** - * The methods in this class are called by the different {@link ClientSideStatement}s. These method - * calls are then forwarded into a {@link Connection}. - */ -class ConnectionStatementExecutorImpl implements ConnectionStatementExecutor { - static final class StatementTimeoutGetter implements DurationValueGetter { - private final Connection connection; - - public StatementTimeoutGetter(Connection connection) { - this.connection = connection; - } - - @Override - public long getDuration(TimeUnit unit) { - return connection.getStatementTimeout(unit); - } - - @Override - public boolean hasDuration() { - return connection.hasStatementTimeout(); - } - } - - /** The connection to execute the statements on. */ - private final ConnectionImpl connection; - - ConnectionStatementExecutorImpl(ConnectionImpl connection) { - this.connection = connection; - } - - ConnectionImpl getConnection() { - return connection; - } - - @Override - public StatementResult statementSetAutocommit(Boolean autocommit) { - Preconditions.checkNotNull(autocommit); - getConnection().setAutocommit(autocommit); - return noResult(SET_AUTOCOMMIT); - } - - @Override - public StatementResult statementShowAutocommit() { - return resultSet("AUTOCOMMIT", getConnection().isAutocommit(), SHOW_AUTOCOMMIT); - } - - @Override - public StatementResult statementSetReadOnly(Boolean readOnly) { - Preconditions.checkNotNull(readOnly); - getConnection().setReadOnly(readOnly); - return noResult(SET_READONLY); - } - - @Override - public StatementResult statementShowReadOnly() { - return StatementResultImpl.resultSet("READONLY", getConnection().isReadOnly(), SHOW_READONLY); - } - - @Override - public StatementResult statementSetRetryAbortsInternally(Boolean retryAbortsInternally) { - Preconditions.checkNotNull(retryAbortsInternally); - getConnection().setRetryAbortsInternally(retryAbortsInternally); - return noResult(SET_RETRY_ABORTS_INTERNALLY); - } - - @Override - public StatementResult statementShowRetryAbortsInternally() { - return StatementResultImpl.resultSet( - "RETRY_ABORTS_INTERNALLY", - getConnection().isRetryAbortsInternally(), - SHOW_RETRY_ABORTS_INTERNALLY); - } - - @Override - public StatementResult statementSetAutocommitDmlMode(AutocommitDmlMode mode) { - getConnection().setAutocommitDmlMode(mode); - return noResult(SET_AUTOCOMMIT_DML_MODE); - } - - @Override - public StatementResult statementShowAutocommitDmlMode() { - return resultSet( - "AUTOCOMMIT_DML_MODE", getConnection().getAutocommitDmlMode(), SHOW_AUTOCOMMIT_DML_MODE); - } - - @Override - public StatementResult statementSetStatementTimeout(Duration duration) { - if (duration.getSeconds() == 0L && duration.getNanos() == 0) { - getConnection().clearStatementTimeout(); - } else { - TimeUnit unit = - ReadOnlyStalenessUtil.getAppropriateTimeUnit( - new ReadOnlyStalenessUtil.DurationGetter(duration)); - getConnection() - .setStatementTimeout(ReadOnlyStalenessUtil.durationToUnits(duration, unit), unit); - } - return noResult(SET_STATEMENT_TIMEOUT); - } - - @Override - public StatementResult statementShowStatementTimeout() { - return resultSet( - "STATEMENT_TIMEOUT", - getConnection().hasStatementTimeout() - ? ReadOnlyStalenessUtil.durationToString(new StatementTimeoutGetter(getConnection())) - : null, - SHOW_STATEMENT_TIMEOUT); - } - - @Override - public StatementResult statementShowReadTimestamp() { - return resultSet( - "READ_TIMESTAMP", getConnection().getReadTimestampOrNull(), SHOW_READ_TIMESTAMP); - } - - @Override - public StatementResult statementShowCommitTimestamp() { - return resultSet( - "COMMIT_TIMESTAMP", getConnection().getCommitTimestampOrNull(), SHOW_COMMIT_TIMESTAMP); - } - - @Override - public StatementResult statementSetReadOnlyStaleness(TimestampBound staleness) { - getConnection().setReadOnlyStaleness(staleness); - return noResult(SET_READ_ONLY_STALENESS); - } - - @Override - public StatementResult statementShowReadOnlyStaleness() { - TimestampBound staleness = getConnection().getReadOnlyStaleness(); - return resultSet( - "READ_ONLY_STALENESS", - ReadOnlyStalenessUtil.timestampBoundToString(staleness), - SHOW_READ_ONLY_STALENESS); - } - - @Override - public StatementResult statementSetOptimizerVersion(String optimizerVersion) { - getConnection().setOptimizerVersion(optimizerVersion); - return noResult(SET_OPTIMIZER_VERSION); - } - - @Override - public StatementResult statementShowOptimizerVersion() { - return resultSet( - "OPTIMIZER_VERSION", getConnection().getOptimizerVersion(), SHOW_OPTIMIZER_VERSION); - } - - @Override - public StatementResult statementBeginTransaction() { - getConnection().beginTransaction(); - return noResult(BEGIN); - } - - @Override - public StatementResult statementCommit() { - getConnection().commit(); - return noResult(COMMIT); - } - - @Override - public StatementResult statementRollback() { - getConnection().rollback(); - return noResult(ROLLBACK); - } - - @Override - public StatementResult statementSetTransactionMode(TransactionMode mode) { - getConnection().setTransactionMode(mode); - return noResult(SET_TRANSACTION_MODE); - } - - @Override - public StatementResult statementStartBatchDdl() { - getConnection().startBatchDdl(); - return noResult(START_BATCH_DDL); - } - - @Override - public StatementResult statementStartBatchDml() { - getConnection().startBatchDml(); - return noResult(START_BATCH_DML); - } - - @Override - public StatementResult statementRunBatch() { - long[] updateCounts = getConnection().runBatch(); - return resultSet("UPDATE_COUNTS", updateCounts, RUN_BATCH); - } - - @Override - public StatementResult statementAbortBatch() { - getConnection().abortBatch(); - return noResult(ABORT_BATCH); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java deleted file mode 100644 index 1bb314e794dd..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CredentialsService.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2019 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.auth.oauth2.GoogleCredentials; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** Service class for getting credentials from key files. */ -class CredentialsService { - static final String GCS_NOT_SUPPORTED_MSG = - "Credentials that is stored on Google Cloud Storage is no longer supported. Download the credentials to a local file and reference the local file in the connection URL."; - static final CredentialsService INSTANCE = new CredentialsService(); - - CredentialsService() {} - - /** - * Create credentials from the given URL pointing to a credentials json file. This may be a local - * file or a file on Google Cloud Storage. Credentials on Google Cloud Storage can only be used if - * the application is running in an environment where application default credentials have been - * set. - * - * @param credentialsUrl The URL of the credentials file to read. If null, then this - * method will return the application default credentials of the environment. - * @return the {@link GoogleCredentials} object pointed to by the URL. - * @throws SpannerException If the URL does not point to a valid credentials file, or if the file - * cannot be accessed. - */ - GoogleCredentials createCredentials(String credentialsUrl) { - try { - if (credentialsUrl == null) { - return internalGetApplicationDefault(); - } else { - return getCredentialsFromUrl(credentialsUrl); - } - } catch (IOException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "Invalid credentials path specified", e); - } - } - - @VisibleForTesting - GoogleCredentials internalGetApplicationDefault() throws IOException { - return GoogleCredentials.getApplicationDefault(); - } - - private GoogleCredentials getCredentialsFromUrl(String credentialsUrl) throws IOException { - Preconditions.checkNotNull(credentialsUrl); - Preconditions.checkArgument( - credentialsUrl.length() > 0, "credentialsUrl may not be an empty string"); - if (credentialsUrl.startsWith("gs://")) { - throw new IOException(GCS_NOT_SUPPORTED_MSG); - } else { - return getCredentialsFromLocalFile(credentialsUrl); - } - } - - private GoogleCredentials getCredentialsFromLocalFile(String filePath) throws IOException { - File credentialsFile = new File(filePath); - if (!credentialsFile.isFile()) { - throw new IOException( - String.format("Error reading credential file %s: File does not exist", filePath)); - } - try (InputStream credentialsStream = new FileInputStream(credentialsFile)) { - return GoogleCredentials.fromStream(credentialsStream); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java deleted file mode 100644 index 3431b29624bb..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlBatch.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2019 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.api.gax.longrunning.OperationFuture; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import org.apache.commons.lang3.ArrayUtils; - -/** - * {@link UnitOfWork} that is used when a DDL batch is started. These batches only accept DDL - * statements. All DDL statements are buffered locally and sent to Spanner when runBatch() is - * called. Running a {@link DdlBatch} is not an atomic operation. If the execution fails, then some - * (possibly empty) prefix of the statements in the batch have been successfully applied to the - * database, and the others have not. Note that the statements that succeed may not all happen at - * the same time, but they will always happen in order. - */ -class DdlBatch extends AbstractBaseUnitOfWork { - private final DdlClient ddlClient; - private final DatabaseClient dbClient; - private final List statements = new ArrayList<>(); - private UnitOfWorkState state = UnitOfWorkState.STARTED; - - static class Builder extends AbstractBaseUnitOfWork.Builder { - private DdlClient ddlClient; - private DatabaseClient dbClient; - - private Builder() {} - - Builder setDdlClient(DdlClient client) { - Preconditions.checkNotNull(client); - this.ddlClient = client; - return this; - } - - Builder setDatabaseClient(DatabaseClient client) { - Preconditions.checkNotNull(client); - this.dbClient = client; - return this; - } - - @Override - DdlBatch build() { - Preconditions.checkState(ddlClient != null, "No DdlClient specified"); - Preconditions.checkState(dbClient != null, "No DbClient specified"); - return new DdlBatch(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private DdlBatch(Builder builder) { - super(builder); - this.ddlClient = builder.ddlClient; - this.dbClient = builder.dbClient; - } - - @Override - public Type getType() { - return Type.BATCH; - } - - @Override - public UnitOfWorkState getState() { - return this.state; - } - - @Override - public boolean isActive() { - return getState().isActive(); - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - public ResultSet executeQuery( - final ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { - if (options != null) { - for (int i = 0; i < options.length; i++) { - if (options[i] instanceof InternalMetadataQuery) { - Preconditions.checkNotNull(statement); - Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); - Preconditions.checkArgument( - analyzeMode == AnalyzeMode.NONE, "Analyze is not allowed for DDL batch"); - // Queries marked with internal metadata queries are allowed during a DDL batch. - // These can only be generated by library internal methods and may be used to check - // whether a database object such as table or an index exists. - final QueryOption[] internalOptions = ArrayUtils.remove(options, i); - Callable callable = - new Callable() { - @Override - public ResultSet call() throws Exception { - return DirectExecuteResultSet.ofResultSet( - dbClient.singleUse().executeQuery(statement.getStatement(), internalOptions)); - } - }; - return asyncExecuteStatement(statement, callable); - } - } - } - // Queries are by default not allowed on DDL batches. - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing queries is not allowed for DDL batches."); - } - - @Override - public Timestamp getReadTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "There is no read timestamp available for DDL batches."); - } - - @Override - public Timestamp getReadTimestampOrNull() { - return null; - } - - @Override - public Timestamp getCommitTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "There is no commit timestamp available for DDL batches."); - } - - @Override - public Timestamp getCommitTimestampOrNull() { - return null; - } - - @Override - public void executeDdl(ParsedStatement ddl) { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, - "The batch is no longer active and cannot be used for further statements"); - Preconditions.checkArgument( - ddl.getType() == StatementType.DDL, - "Only DDL statements are allowed. \"" - + ddl.getSqlWithoutComments() - + "\" is not a DDL-statement."); - statements.add(ddl.getSqlWithoutComments()); - } - - @Override - public long executeUpdate(ParsedStatement update) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing updates is not allowed for DDL batches."); - } - - @Override - public long[] executeBatchUpdate(Iterable updates) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing batch updates is not allowed for DDL batches."); - } - - @Override - public void write(Mutation mutation) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DDL batches."); - } - - @Override - public void write(Iterable mutations) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DDL batches."); - } - - /** - * Create a {@link ParsedStatement} that we can use as input for the generic execute method when - * the {@link #runBatch()} method is executed. This method uses the generic execute method that - * allows statements to be cancelled and to timeout, which requires the input to be a {@link - * ParsedStatement}. - */ - private static final ParsedStatement RUN_BATCH = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - - @Override - public long[] runBatch() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be ran"); - try { - if (!statements.isEmpty()) { - // create a statement that can be passed in to the execute method - Callable callable = - new Callable() { - @Override - public UpdateDatabaseDdlMetadata call() throws Exception { - OperationFuture operation = - ddlClient.executeDdl(statements); - try { - // Wait until the operation has finished. - operation.get(); - // Return metadata. - return operation.getMetadata().get(); - } catch (ExecutionException e) { - SpannerException spannerException = extractSpannerCause(e); - long[] updateCounts = extractUpdateCounts(operation.getMetadata().get()); - throw SpannerExceptionFactory.newSpannerBatchUpdateException( - spannerException == null - ? ErrorCode.UNKNOWN - : spannerException.getErrorCode(), - e.getMessage(), - updateCounts); - } catch (InterruptedException e) { - long[] updateCounts = extractUpdateCounts(operation.getMetadata().get()); - throw SpannerExceptionFactory.newSpannerBatchUpdateException( - ErrorCode.CANCELLED, e.getMessage(), updateCounts); - } - } - }; - asyncExecuteStatement(RUN_BATCH, callable); - } - this.state = UnitOfWorkState.RAN; - long[] updateCounts = new long[statements.size()]; - Arrays.fill(updateCounts, 1L); - return updateCounts; - } catch (SpannerException e) { - this.state = UnitOfWorkState.RUN_FAILED; - throw e; - } - } - - private SpannerException extractSpannerCause(ExecutionException e) { - Throwable cause = e.getCause(); - Set causes = new HashSet<>(); - while (cause != null && !causes.contains(cause)) { - if (cause instanceof SpannerException) { - return (SpannerException) cause; - } - causes.add(cause); - cause = cause.getCause(); - } - return null; - } - - @VisibleForTesting - long[] extractUpdateCounts(UpdateDatabaseDdlMetadata metadata) { - long[] updateCounts = new long[metadata.getStatementsCount()]; - for (int i = 0; i < updateCounts.length; i++) { - if (metadata.getCommitTimestampsCount() > i && metadata.getCommitTimestamps(i) != null) { - updateCounts[i] = 1L; - } else { - updateCounts[i] = 0L; - } - } - return updateCounts; - } - - @Override - public void abortBatch() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be aborted."); - this.state = UnitOfWorkState.ABORTED; - } - - @Override - public void commit() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Commit is not allowed for DDL batches."); - } - - @Override - public void rollback() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Rollback is not allowed for DDL batches."); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java deleted file mode 100644 index 5f921d7b43f7..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DdlClient.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import java.util.Arrays; -import java.util.List; - -/** - * Convenience class for executing Data Definition Language statements on transactions that support - * DDL statements, i.e. DdlBatchTransaction and SingleUseTransaction. - */ -class DdlClient { - private final DatabaseAdminClient dbAdminClient; - private final String instanceId; - private final String databaseName; - - static class Builder { - private DatabaseAdminClient dbAdminClient; - private String instanceId; - private String databaseName; - - private Builder() {} - - Builder setDatabaseAdminClient(DatabaseAdminClient client) { - Preconditions.checkNotNull(client); - this.dbAdminClient = client; - return this; - } - - Builder setInstanceId(String instanceId) { - Preconditions.checkArgument( - !Strings.isNullOrEmpty(instanceId), "Empty instanceId is not allowed"); - this.instanceId = instanceId; - return this; - } - - Builder setDatabaseName(String name) { - Preconditions.checkArgument( - !Strings.isNullOrEmpty(name), "Empty database name is not allowed"); - this.databaseName = name; - return this; - } - - DdlClient build() { - Preconditions.checkState(dbAdminClient != null, "No DatabaseAdminClient specified"); - Preconditions.checkState(!Strings.isNullOrEmpty(instanceId), "No InstanceId specified"); - Preconditions.checkArgument( - !Strings.isNullOrEmpty(databaseName), "No database name specified"); - return new DdlClient(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private DdlClient(Builder builder) { - this.dbAdminClient = builder.dbAdminClient; - this.instanceId = builder.instanceId; - this.databaseName = builder.databaseName; - } - - /** Execute a single DDL statement. */ - OperationFuture executeDdl(String ddl) { - return executeDdl(Arrays.asList(ddl)); - } - - /** Execute a list of DDL statements as one operation. */ - OperationFuture executeDdl(List statements) { - return dbAdminClient.updateDatabaseDdl(instanceId, databaseName, statements, null); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java deleted file mode 100644 index 90ca044166e8..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSet.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2019 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.ByteArray; -import com.google.cloud.Date; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type; -import com.google.common.base.Preconditions; -import com.google.spanner.v1.ResultSetStats; -import java.util.List; - -/** - * {@link ResultSet} implementation used by the Spanner connection API to ensure that the query for - * a {@link ResultSet} is executed directly when it is created. This is done by calling {@link - * ResultSet#next()} directly after creation. This ensures that a statement timeout can be applied - * to the actual query execution. It also ensures that any invalid query will throw an exception at - * execution instead of the first next() call by a client. - */ -class DirectExecuteResultSet implements ResultSet { - private static final String MISSING_NEXT_CALL = "Must be preceded by a next() call"; - private final ResultSet delegate; - private boolean nextCalledByClient = false; - private final boolean initialNextResult; - private boolean nextHasReturnedFalse = false; - - /** - * Creates a new {@link DirectExecuteResultSet} from the given delegate {@link ResultSet}. This - * automatically executes the query of the given delegate {@link ResultSet} by calling next() on - * the delegate. The delegate must not have been used (i.e. next() must not have been called on - * it). - * - * @param delegate The underlying {@link ResultSet} for this {@link DirectExecuteResultSet}. - * @return a {@link DirectExecuteResultSet} that has already executed the query associated with - * the delegate {@link ResultSet}. - */ - static DirectExecuteResultSet ofResultSet(ResultSet delegate) { - return new DirectExecuteResultSet(delegate); - } - - DirectExecuteResultSet(ResultSet delegate) { - Preconditions.checkNotNull(delegate); - this.delegate = delegate; - initialNextResult = delegate.next(); - } - - @Override - public boolean next() throws SpannerException { - if (nextCalledByClient) { - boolean res = delegate.next(); - nextHasReturnedFalse = !res; - return res; - } - nextCalledByClient = true; - nextHasReturnedFalse = !initialNextResult; - return initialNextResult; - } - - @Override - public Struct getCurrentRowAsStruct() { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getCurrentRowAsStruct(); - } - - @Override - public void close() { - delegate.close(); - } - - @Override - public ResultSetStats getStats() { - if (nextHasReturnedFalse) { - return delegate.getStats(); - } - return null; - } - - @Override - public Type getType() { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getType(); - } - - @Override - public int getColumnCount() { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getColumnCount(); - } - - @Override - public int getColumnIndex(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getColumnIndex(columnName); - } - - @Override - public Type getColumnType(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getColumnType(columnIndex); - } - - @Override - public Type getColumnType(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getColumnType(columnName); - } - - @Override - public boolean isNull(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.isNull(columnIndex); - } - - @Override - public boolean isNull(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.isNull(columnName); - } - - @Override - public boolean getBoolean(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBoolean(columnIndex); - } - - @Override - public boolean getBoolean(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBoolean(columnName); - } - - @Override - public long getLong(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLong(columnIndex); - } - - @Override - public long getLong(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLong(columnName); - } - - @Override - public double getDouble(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDouble(columnIndex); - } - - @Override - public double getDouble(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDouble(columnName); - } - - @Override - public String getString(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getString(columnIndex); - } - - @Override - public String getString(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getString(columnName); - } - - @Override - public ByteArray getBytes(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBytes(columnIndex); - } - - @Override - public ByteArray getBytes(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBytes(columnName); - } - - @Override - public Timestamp getTimestamp(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getTimestamp(columnIndex); - } - - @Override - public Timestamp getTimestamp(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getTimestamp(columnName); - } - - @Override - public Date getDate(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDate(columnIndex); - } - - @Override - public Date getDate(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDate(columnName); - } - - @Override - public boolean[] getBooleanArray(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBooleanArray(columnIndex); - } - - @Override - public boolean[] getBooleanArray(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBooleanArray(columnName); - } - - @Override - public List getBooleanList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBooleanList(columnIndex); - } - - @Override - public List getBooleanList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBooleanList(columnName); - } - - @Override - public long[] getLongArray(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLongArray(columnIndex); - } - - @Override - public long[] getLongArray(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLongArray(columnName); - } - - @Override - public List getLongList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLongList(columnIndex); - } - - @Override - public List getLongList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getLongList(columnName); - } - - @Override - public double[] getDoubleArray(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDoubleArray(columnIndex); - } - - @Override - public double[] getDoubleArray(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDoubleArray(columnName); - } - - @Override - public List getDoubleList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDoubleList(columnIndex); - } - - @Override - public List getDoubleList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDoubleList(columnName); - } - - @Override - public List getStringList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getStringList(columnIndex); - } - - @Override - public List getStringList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getStringList(columnName); - } - - @Override - public List getBytesList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBytesList(columnIndex); - } - - @Override - public List getBytesList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getBytesList(columnName); - } - - @Override - public List getTimestampList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getTimestampList(columnIndex); - } - - @Override - public List getTimestampList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getTimestampList(columnName); - } - - @Override - public List getDateList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDateList(columnIndex); - } - - @Override - public List getDateList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getDateList(columnName); - } - - @Override - public List getStructList(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getStructList(columnIndex); - } - - @Override - public List getStructList(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); - return delegate.getStructList(columnName); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof DirectExecuteResultSet)) { - return false; - } - return ((DirectExecuteResultSet) o).delegate.equals(delegate); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java deleted file mode 100644 index 55da9fb1bc67..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/DmlBatch.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2019 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.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.common.base.Preconditions; -import java.util.ArrayList; -import java.util.List; - -/** - * {@link UnitOfWork} that is used when a DML batch is started. These batches only accept DML - * statements. All DML statements are buffered locally and sent to Spanner when runBatch() is - * called. - */ -class DmlBatch extends AbstractBaseUnitOfWork { - private final UnitOfWork transaction; - private final List statements = new ArrayList<>(); - private UnitOfWorkState state = UnitOfWorkState.STARTED; - - static class Builder extends AbstractBaseUnitOfWork.Builder { - private UnitOfWork transaction; - - private Builder() {} - - Builder setTransaction(UnitOfWork transaction) { - Preconditions.checkNotNull(transaction); - this.transaction = transaction; - return this; - } - - @Override - DmlBatch build() { - Preconditions.checkState(transaction != null, "No transaction specified"); - return new DmlBatch(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private DmlBatch(Builder builder) { - super(builder); - this.transaction = builder.transaction; - } - - @Override - public Type getType() { - return Type.BATCH; - } - - @Override - public UnitOfWorkState getState() { - return this.state; - } - - @Override - public boolean isActive() { - return getState().isActive(); - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - public ResultSet executeQuery( - ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing queries is not allowed for DML batches."); - } - - @Override - public Timestamp getReadTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "There is no read timestamp available for DML batches."); - } - - @Override - public Timestamp getReadTimestampOrNull() { - return null; - } - - @Override - public Timestamp getCommitTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "There is no commit timestamp available for DML batches."); - } - - @Override - public Timestamp getCommitTimestampOrNull() { - return null; - } - - @Override - public void executeDdl(ParsedStatement ddl) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing DDL statements is not allowed for DML batches."); - } - - @Override - public long executeUpdate(ParsedStatement update) { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, - "The batch is no longer active and cannot be used for further statements"); - Preconditions.checkArgument( - update.getType() == StatementType.UPDATE, - "Only DML statements are allowed. \"" - + update.getSqlWithoutComments() - + "\" is not a DML-statement."); - statements.add(update); - return -1L; - } - - @Override - public long[] executeBatchUpdate(Iterable updates) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Executing batch updates is not allowed for DML batches."); - } - - @Override - public void write(Mutation mutation) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DML batches."); - } - - @Override - public void write(Iterable mutations) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DML batches."); - } - - @Override - public long[] runBatch() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be ran"); - try { - long[] res; - if (statements.isEmpty()) { - res = new long[0]; - } else { - res = transaction.executeBatchUpdate(statements); - } - this.state = UnitOfWorkState.RAN; - return res; - } catch (SpannerException e) { - this.state = UnitOfWorkState.RUN_FAILED; - throw e; - } - } - - @Override - public void abortBatch() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, "The batch is no longer active and cannot be aborted."); - this.state = UnitOfWorkState.ABORTED; - } - - @Override - public void commit() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Commit is not allowed for DML batches."); - } - - @Override - public void rollback() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Rollback is not allowed for DML batches."); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java deleted file mode 100644 index d96d98a829a4..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedBatchUpdate.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2019 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.AbortedException; -import com.google.cloud.spanner.SpannerBatchUpdateException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.common.base.Preconditions; -import java.util.Arrays; -import java.util.Objects; - -/** - * A batch update that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The - * batch update can be retried if the transaction is aborted, and should throw the same exception - * during retry as during the original transaction. - */ -final class FailedBatchUpdate implements RetriableStatement { - private final ReadWriteTransaction transaction; - private final SpannerException exception; - private final Iterable statements; - - FailedBatchUpdate( - ReadWriteTransaction transaction, - SpannerException exception, - Iterable statements) { - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(exception); - Preconditions.checkNotNull(statements); - this.transaction = transaction; - this.exception = exception; - this.statements = statements; - } - - @Override - public void retry(AbortedException aborted) throws AbortedException { - transaction - .getStatementExecutor() - .invokeInterceptors( - ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, - StatementExecutionStep.RETRY_STATEMENT, - transaction); - try { - transaction.getReadContext().batchUpdate(statements); - } catch (SpannerBatchUpdateException e) { - // Check that we got the same exception as in the original transaction. - if (exception instanceof SpannerBatchUpdateException - && e.getErrorCode() == exception.getErrorCode() - && Objects.equals(e.getMessage(), exception.getMessage())) { - // Check that the returned update counts are equal. - if (Arrays.equals( - e.getUpdateCounts(), ((SpannerBatchUpdateException) exception).getUpdateCounts())) { - return; - } - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } catch (SpannerException e) { - // Check that we got the same exception as in the original transaction. - if (e.getErrorCode() == exception.getErrorCode() - && Objects.equals(e.getMessage(), exception.getMessage())) { - return; - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java deleted file mode 100644 index 4e2a3ecda871..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedQuery.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 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.AbortedException; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; -import java.util.Objects; - -/** - * A query that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The query - * can be retried if the transaction is aborted, and should throw the same exception during retry as - * during the original transaction. - */ -final class FailedQuery implements RetriableStatement { - private final ReadWriteTransaction transaction; - private final SpannerException exception; - private final ParsedStatement statement; - private final AnalyzeMode analyzeMode; - private final QueryOption[] options; - - FailedQuery( - ReadWriteTransaction transaction, - SpannerException exception, - ParsedStatement statement, - AnalyzeMode analyzeMode, - QueryOption... options) { - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(exception); - Preconditions.checkNotNull(statement); - this.transaction = transaction; - this.exception = exception; - this.statement = statement; - this.analyzeMode = analyzeMode; - this.options = options; - } - - @Override - public void retry(AbortedException aborted) throws AbortedException { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - try { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - try (ResultSet rs = - DirectExecuteResultSet.ofResultSet( - transaction.internalExecuteQuery(statement, analyzeMode, options))) { - // Do nothing with the results, we are only interested in whether the statement throws the - // same exception as in the original transaction. - } - } catch (SpannerException e) { - // Check that we got the same exception as in the original transaction - if (e.getErrorCode() == exception.getErrorCode() - && Objects.equals(e.getMessage(), exception.getMessage())) { - return; - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java deleted file mode 100644 index 1974f0ccdbbe..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/FailedUpdate.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019 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.AbortedException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; -import java.util.Objects; - -/** - * An update that failed with a {@link SpannerException} on a {@link ReadWriteTransaction}. The - * update can be retried if the transaction is aborted, and should throw the same exception during - * retry as during the original transaction. - */ -final class FailedUpdate implements RetriableStatement { - private final ReadWriteTransaction transaction; - private final SpannerException exception; - private final ParsedStatement statement; - - FailedUpdate( - ReadWriteTransaction transaction, SpannerException exception, ParsedStatement statement) { - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(exception); - Preconditions.checkNotNull(statement); - this.transaction = transaction; - this.exception = exception; - this.statement = statement; - } - - @Override - public void retry(AbortedException aborted) throws AbortedException { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - try { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - transaction.getReadContext().executeUpdate(statement.getStatement()); - } catch (SpannerException e) { - // Check that we got the same exception as in the original transaction. - if (e.getErrorCode() == exception.getErrorCode() - && Objects.equals(e.getMessage(), exception.getMessage())) { - return; - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 08b2a823b619..5aefd35b5ddb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -16,8 +16,13 @@ package com.google.cloud.spanner.jdbc; +import com.google.api.client.util.Preconditions; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.StatementParser; +import com.google.common.base.Function; +import com.google.common.collect.Iterators; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; @@ -383,22 +388,104 @@ public void bufferedWrite(Iterable mutations) throws SQLException { } } + @SuppressWarnings("deprecation") + private static final class JdbcToSpannerTransactionRetryListener + implements com.google.cloud.spanner.connection.TransactionRetryListener { + private final TransactionRetryListener delegate; + + JdbcToSpannerTransactionRetryListener(TransactionRetryListener delegate) { + this.delegate = Preconditions.checkNotNull(delegate); + } + + @Override + public void retryStarting( + com.google.cloud.Timestamp transactionStarted, long transactionId, int retryAttempt) { + delegate.retryStarting(transactionStarted, transactionId, retryAttempt); + } + + @Override + public void retryFinished( + com.google.cloud.Timestamp transactionStarted, + long transactionId, + int retryAttempt, + RetryResult result) { + delegate.retryFinished( + transactionStarted, + transactionId, + retryAttempt, + TransactionRetryListener.RetryResult.valueOf(result.name())); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof JdbcToSpannerTransactionRetryListener)) { + return false; + } + JdbcToSpannerTransactionRetryListener other = (JdbcToSpannerTransactionRetryListener) o; + return this.delegate.equals(other.delegate); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + } + + @SuppressWarnings("deprecation") @Override public void addTransactionRetryListener(TransactionRetryListener listener) throws SQLException { checkClosed(); + getSpannerConnection() + .addTransactionRetryListener(new JdbcToSpannerTransactionRetryListener(listener)); + } + + @Override + public void addTransactionRetryListener( + com.google.cloud.spanner.connection.TransactionRetryListener listener) throws SQLException { + checkClosed(); getSpannerConnection().addTransactionRetryListener(listener); } + @SuppressWarnings("deprecation") @Override public boolean removeTransactionRetryListener(TransactionRetryListener listener) throws SQLException { checkClosed(); + return getSpannerConnection() + .removeTransactionRetryListener(new JdbcToSpannerTransactionRetryListener(listener)); + } + + @Override + public boolean removeTransactionRetryListener( + com.google.cloud.spanner.connection.TransactionRetryListener listener) throws SQLException { + checkClosed(); return getSpannerConnection().removeTransactionRetryListener(listener); } + @SuppressWarnings("deprecation") @Override public Iterator getTransactionRetryListeners() throws SQLException { checkClosed(); + return Iterators.transform( + getSpannerConnection().getTransactionRetryListeners(), + new Function< + com.google.cloud.spanner.connection.TransactionRetryListener, + TransactionRetryListener>() { + @Override + public TransactionRetryListener apply( + com.google.cloud.spanner.connection.TransactionRetryListener input) { + if (input instanceof JdbcToSpannerTransactionRetryListener) { + return ((JdbcToSpannerTransactionRetryListener) input).delegate; + } + return null; + } + }); + } + + @Override + public Iterator + getTransactionRetryListenersFromConnection() throws SQLException { + checkClosed(); return getSpannerConnection().getTransactionRetryListeners(); } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java index a8cca8abc40b..58c9e5bb3ba3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java @@ -16,7 +16,6 @@ package com.google.cloud.spanner.jdbc; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; import java.sql.ResultSet; import java.sql.Statement; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java index 31a4ad44e750..72a641cc97ff 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.rpc.Code; import java.io.PrintWriter; import java.sql.Connection; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index a15ad721ee4f..22176595ec9f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -23,7 +23,7 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; -import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; +import com.google.cloud.spanner.connection.Connection.InternalMetadataQuery; import com.google.common.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.InputStream; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 229c0a6fb847..2d83a34d07a7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -19,7 +19,8 @@ import com.google.api.core.InternalApi; import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.jdbc.ConnectionOptions.ConnectionProperty; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; import com.google.rpc.Code; import java.sql.Connection; import java.sql.Driver; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 4d5cfe88955d..7a0e84235505 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -18,6 +18,7 @@ import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; import java.sql.PreparedStatement; import java.sql.ResultSet; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index e87558e68e92..b4eaa0d17a45 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -24,6 +24,8 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.connection.StatementParser; +import com.google.cloud.spanner.connection.StatementResult; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.rpc.Code; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java deleted file mode 100644 index 291665867409..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtil.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2019 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.api.client.util.DateTime; -import com.google.api.client.util.DateTime.SecondsAndNanos; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.protobuf.Duration; -import com.google.protobuf.util.Durations; -import java.util.concurrent.TimeUnit; - -/** - * Util class for parsing and converting ReadOnlyStaleness values to/from strings. This util is used - * to parse client side statements and values for read only staleness for read-only transactions on - * Cloud Spanner. - */ -class ReadOnlyStalenessUtil { - /** - * Parses an RFC3339 date/time value with nanosecond precision and returns this as a {@link - * Timestamp}. - */ - static Timestamp parseRfc3339(String str) throws SpannerException { - try { - SecondsAndNanos secondsAndNanos = DateTime.parseRfc3339ToSecondsAndNanos(str); - return Timestamp.ofTimeSecondsAndNanos( - secondsAndNanos.getSeconds(), secondsAndNanos.getNanos()); - } catch (NumberFormatException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, String.format("Invalid timestamp: %s", str), e); - } - } - - /** The abbreviations for time units that may be used for client side statements. */ - enum TimeUnitAbbreviation { - NANOSECONDS("ns", TimeUnit.NANOSECONDS), - MICROSECONDS("us", TimeUnit.MICROSECONDS), - MILLISECONDS("ms", TimeUnit.MILLISECONDS), - SECONDS("s", TimeUnit.SECONDS); - - private final String abbreviation; - private final TimeUnit unit; - - private TimeUnitAbbreviation(String abbreviation, TimeUnit unit) { - this.abbreviation = abbreviation; - this.unit = unit; - } - - String getAbbreviation() { - return abbreviation; - } - - TimeUnit getUnit() { - return unit; - } - } - - /** Get the abbreviation for the given {@link TimeUnit}. */ - static String getTimeUnitAbbreviation(TimeUnit unit) { - for (TimeUnitAbbreviation abb : TimeUnitAbbreviation.values()) { - if (abb.unit == unit) return abb.abbreviation; - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "Invalid option for time unit: " + unit); - } - - /** Get the {@link TimeUnit} corresponding with the given abbreviation. */ - static TimeUnit parseTimeUnit(String unit) { - for (TimeUnitAbbreviation abb : TimeUnitAbbreviation.values()) { - if (abb.abbreviation.equalsIgnoreCase(unit)) return abb.unit; - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "Invalid option for time unit: " + unit); - } - - /** - * Internal interface that is used to generalize getting a time duration from Cloud Spanner - * read-only staleness settings. - */ - static interface DurationValueGetter { - long getDuration(TimeUnit unit); - - boolean hasDuration(); - } - - static final class GetExactStaleness implements DurationValueGetter { - private final TimestampBound staleness; - - public GetExactStaleness(TimestampBound staleness) { - this.staleness = staleness; - } - - @Override - public long getDuration(TimeUnit unit) { - return staleness.getExactStaleness(unit); - } - - @Override - public boolean hasDuration() { - return staleness.getMode() == Mode.EXACT_STALENESS; - } - } - - static final class MaxStalenessGetter implements DurationValueGetter { - private final TimestampBound staleness; - - public MaxStalenessGetter(TimestampBound staleness) { - this.staleness = staleness; - } - - @Override - public long getDuration(TimeUnit unit) { - return staleness.getMaxStaleness(unit); - } - - @Override - public boolean hasDuration() { - return staleness.getMode() == Mode.MAX_STALENESS; - } - } - - static final class DurationGetter implements DurationValueGetter { - private final Duration duration; - - public DurationGetter(Duration duration) { - this.duration = duration; - } - - @Override - public long getDuration(TimeUnit unit) { - return durationToUnits(duration, unit); - } - - @Override - public boolean hasDuration() { - return duration.getNanos() > 0 || duration.getSeconds() > 0L; - } - } - - /** - * Converts a {@link TimestampBound} to a human readable string representation. - * - * @param staleness The staleness to convert - * @return a human readable representation of the staleness. - */ - static String timestampBoundToString(TimestampBound staleness) { - switch (staleness.getMode()) { - case STRONG: - return "STRONG"; - case READ_TIMESTAMP: - return "READ_TIMESTAMP " + staleness.getReadTimestamp().toString(); - case MIN_READ_TIMESTAMP: - return "MIN_READ_TIMESTAMP " + staleness.getMinReadTimestamp().toString(); - case EXACT_STALENESS: - return "EXACT_STALENESS " + durationToString(new GetExactStaleness(staleness)); - case MAX_STALENESS: - return "MAX_STALENESS " + durationToString(new MaxStalenessGetter(staleness)); - default: - throw new IllegalStateException("Unknown mode: " + staleness.getMode()); - } - } - - /** The {@link TimeUnit}s that are supported for timeout and staleness durations. */ - static final TimeUnit[] SUPPORTED_UNITS = - new TimeUnit[] { - TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS - }; - - /** - * Converts a duration value to a human readable string. The method will search for the most - * appropriate {@link TimeUnit} to use to represent the value. - * - * @param function The function that should be called to get the duration in a specific {@link - * TimeUnit}. - * @return a human readable value of the duration. - */ - static String durationToString(DurationValueGetter function) { - TimeUnit unit = getAppropriateTimeUnit(function); - return String.valueOf(function.getDuration(unit)) + getTimeUnitAbbreviation(unit); - } - - /** - * Calculates the most appropriate {@link TimeUnit} to use to represent the duration that is - * returned by the given function. The most appropriate {@link TimeUnit} is the unit with the - * least precision that still retains all information of the given input. - * - * @param durationGetter The function that will return the duration in different {@link - * TimeUnit}s. - * @return the most appropriate {@link TimeUnit} to represent the duration. - */ - static TimeUnit getAppropriateTimeUnit(DurationValueGetter durationGetter) { - int index = 0; - if (durationGetter.hasDuration()) { - for (TimeUnit unit : SUPPORTED_UNITS) { - long duration = durationGetter.getDuration(unit); - if (index + 1 < SUPPORTED_UNITS.length) { - if (duration > 0L - && duration * 1000 == durationGetter.getDuration(SUPPORTED_UNITS[index + 1])) { - return unit; - } - } else { - // last unit, we have to use this one - return unit; - } - index++; - } - throw new IllegalStateException("Unsupported duration"); - } - return TimeUnit.NANOSECONDS; - } - - /** Converts a value into a duration using the specified {@link TimeUnit}. */ - static Duration createDuration(long num, TimeUnit units) { - switch (units) { - case NANOSECONDS: - return Durations.fromNanos(num); - case MICROSECONDS: - return Durations.fromMicros(num); - case MILLISECONDS: - return Durations.fromMillis(num); - case SECONDS: - return Durations.fromSeconds(num); - default: - return Durations.fromMillis(units.toMillis(num)); - } - } - - /** Converts a duration to a number using the specified {@link TimeUnit}. */ - static long durationToUnits(Duration duration, TimeUnit units) { - switch (units) { - case NANOSECONDS: - return Durations.toNanos(duration); - case MICROSECONDS: - return Durations.toMicros(duration); - case MILLISECONDS: - return Durations.toMillis(duration); - case SECONDS: - return Durations.toSeconds(duration); - default: - throw new IllegalArgumentException(); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java deleted file mode 100644 index e0c408970032..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadOnlyTransaction.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2019 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.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ReadContext; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; - -/** - * Transaction that is used when a {@link Connection} is in read-only mode or when the transaction - * mode is set to read-only. This transaction can only be used to execute queries. - */ -class ReadOnlyTransaction extends AbstractMultiUseTransaction { - private final DatabaseClient dbClient; - private final TimestampBound readOnlyStaleness; - private com.google.cloud.spanner.ReadOnlyTransaction transaction; - private UnitOfWorkState state = UnitOfWorkState.STARTED; - - static class Builder extends AbstractBaseUnitOfWork.Builder { - private DatabaseClient dbClient; - private TimestampBound readOnlyStaleness; - - private Builder() {} - - Builder setDatabaseClient(DatabaseClient client) { - Preconditions.checkNotNull(client); - this.dbClient = client; - return this; - } - - Builder setReadOnlyStaleness(TimestampBound staleness) { - Preconditions.checkNotNull(staleness); - this.readOnlyStaleness = staleness; - return this; - } - - @Override - ReadOnlyTransaction build() { - Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); - Preconditions.checkState(readOnlyStaleness != null, "No ReadOnlyStaleness specified"); - return new ReadOnlyTransaction(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private ReadOnlyTransaction(Builder builder) { - super(builder); - this.dbClient = builder.dbClient; - this.readOnlyStaleness = builder.readOnlyStaleness; - } - - @Override - public UnitOfWorkState getState() { - return this.state; - } - - @Override - public boolean isReadOnly() { - return true; - } - - @Override - void checkValidTransaction() { - if (transaction == null) { - transaction = dbClient.readOnlyTransaction(readOnlyStaleness); - } - } - - @Override - ReadContext getReadContext() { - ConnectionPreconditions.checkState(transaction != null, "Missing read-only transaction"); - return transaction; - } - - @Override - public Timestamp getReadTimestamp() { - ConnectionPreconditions.checkState( - transaction != null, "There is no read timestamp available for this transaction."); - ConnectionPreconditions.checkState( - state != UnitOfWorkState.ROLLED_BACK, "This transaction was rolled back"); - return transaction.getReadTimestamp(); - } - - @Override - public Timestamp getReadTimestampOrNull() { - if (transaction != null && state != UnitOfWorkState.ROLLED_BACK) { - try { - return transaction.getReadTimestamp(); - } catch (SpannerException e) { - // ignore - } - } - return null; - } - - @Override - public Timestamp getCommitTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "There is no commit timestamp available for this transaction."); - } - - @Override - public Timestamp getCommitTimestampOrNull() { - return null; - } - - @Override - public void executeDdl(ParsedStatement ddl) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "DDL statements are not allowed for read-only transactions"); - } - - @Override - public long executeUpdate(ParsedStatement update) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "Update statements are not allowed for read-only transactions"); - } - - @Override - public long[] executeBatchUpdate(Iterable updates) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Batch updates are not allowed for read-only transactions."); - } - - @Override - public void write(Mutation mutation) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Mutations are not allowed for read-only transactions"); - } - - @Override - public void write(Iterable mutations) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Mutations are not allowed for read-only transactions"); - } - - @Override - public void commit() { - if (this.transaction != null) { - this.transaction.close(); - } - this.state = UnitOfWorkState.COMMITTED; - } - - @Override - public void rollback() { - if (this.transaction != null) { - this.transaction.close(); - } - this.state = UnitOfWorkState.ROLLED_BACK; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java deleted file mode 100644 index a9fcbc53883b..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReadWriteTransaction.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright 2019 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 com.google.common.base.Preconditions.checkNotNull; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.TransactionRetryListener.RetryResult; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Transaction that is used when a {@link Connection} is normal read/write mode (i.e. not autocommit - * and not read-only). These transactions can be automatically retried if an {@link - * AbortedException} is thrown. The transaction will keep track of a running checksum of all {@link - * ResultSet}s that have been returned, and the update counts returned by any DML statement executed - * during the transaction. As long as these checksums and update counts are equal for both the - * original transaction and the retried transaction, the retry can safely be assumed to have the - * exact same results as the original transaction. - */ -class ReadWriteTransaction extends AbstractMultiUseTransaction { - private static final Logger logger = Logger.getLogger(ReadWriteTransaction.class.getName()); - private static final AtomicLong ID_GENERATOR = new AtomicLong(); - private static final String MAX_INTERNAL_RETRIES_EXCEEDED = - "Internal transaction retry maximum exceeded"; - private static final int MAX_INTERNAL_RETRIES = 50; - private final long transactionId; - private final DatabaseClient dbClient; - private TransactionManager txManager; - private final boolean retryAbortsInternally; - private int transactionRetryAttempts; - private int successfulRetries; - private final List transactionRetryListeners; - private volatile TransactionContext txContext; - private volatile UnitOfWorkState state = UnitOfWorkState.STARTED; - private boolean timedOutOrCancelled = false; - private final List statements = new ArrayList<>(); - private final List mutations = new ArrayList<>(); - private Timestamp transactionStarted; - - static class Builder extends AbstractMultiUseTransaction.Builder { - private DatabaseClient dbClient; - private Boolean retryAbortsInternally; - private List transactionRetryListeners; - - private Builder() {} - - Builder setDatabaseClient(DatabaseClient client) { - Preconditions.checkNotNull(client); - this.dbClient = client; - return this; - } - - Builder setRetryAbortsInternally(boolean retryAbortsInternally) { - this.retryAbortsInternally = retryAbortsInternally; - return this; - } - - Builder setTransactionRetryListeners(List listeners) { - Preconditions.checkNotNull(listeners); - this.transactionRetryListeners = listeners; - return this; - } - - @Override - ReadWriteTransaction build() { - Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); - Preconditions.checkState( - retryAbortsInternally != null, "RetryAbortsInternally is not specified"); - Preconditions.checkState( - transactionRetryListeners != null, "TransactionRetryListeners are not specified"); - return new ReadWriteTransaction(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private ReadWriteTransaction(Builder builder) { - super(builder); - this.transactionId = ID_GENERATOR.incrementAndGet(); - this.dbClient = builder.dbClient; - this.retryAbortsInternally = builder.retryAbortsInternally; - this.transactionRetryListeners = builder.transactionRetryListeners; - this.txManager = dbClient.transactionManager(); - } - - @Override - public String toString() { - return new StringBuilder() - .append("ReadWriteTransaction - ID: ") - .append(transactionId) - .append("; Status: ") - .append(internalGetStateName()) - .append("; Started: ") - .append(internalGetTimeStarted()) - .append("; Retry attempts: ") - .append(transactionRetryAttempts) - .append("; Successful retries: ") - .append(successfulRetries) - .toString(); - } - - private String internalGetStateName() { - return transactionStarted == null ? "Not yet started" : getState().toString(); - } - - private String internalGetTimeStarted() { - return transactionStarted == null ? "Not yet started" : transactionStarted.toString(); - } - - @Override - public UnitOfWorkState getState() { - return this.state; - } - - @Override - public boolean isReadOnly() { - return false; - } - - @Override - void checkValidTransaction() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, - "This transaction has status " - + state.name() - + ", only " - + UnitOfWorkState.STARTED - + " is allowed."); - ConnectionPreconditions.checkState( - !timedOutOrCancelled, - "The last statement of this transaction timed out or was cancelled. " - + "The transaction is no longer usable. " - + "Rollback the transaction and start a new one."); - if (txManager.getState() == null) { - transactionStarted = Timestamp.now(); - txContext = txManager.begin(); - } - if (txManager.getState() - != com.google.cloud.spanner.TransactionManager.TransactionState.STARTED) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - String.format("Invalid transaction state: %s", txManager.getState())); - } - } - - @Override - TransactionContext getReadContext() { - ConnectionPreconditions.checkState(txContext != null, "Missing transaction context"); - return txContext; - } - - @Override - public Timestamp getReadTimestamp() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "There is no read timestamp available for read/write transactions."); - } - - @Override - public Timestamp getReadTimestampOrNull() { - return null; - } - - private boolean hasCommitTimestamp() { - return txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.COMMITTED; - } - - @Override - public Timestamp getCommitTimestamp() { - ConnectionPreconditions.checkState(hasCommitTimestamp(), "This transaction has not committed."); - return txManager.getCommitTimestamp(); - } - - @Override - public Timestamp getCommitTimestampOrNull() { - return hasCommitTimestamp() ? txManager.getCommitTimestamp() : null; - } - - @Override - public void executeDdl(ParsedStatement ddl) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "DDL-statements are not allowed inside a read/write transaction."); - } - - private void handlePossibleInvalidatingException(SpannerException e) { - if (e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED - || e.getErrorCode() == ErrorCode.CANCELLED) { - this.timedOutOrCancelled = true; - } - } - - @Override - public ResultSet executeQuery( - final ParsedStatement statement, - final AnalyzeMode analyzeMode, - final QueryOption... options) { - Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); - checkValidTransaction(); - try { - if (retryAbortsInternally) { - return asyncExecuteStatement( - statement, - new Callable() { - @Override - public ResultSet call() throws Exception { - return runWithRetry( - new Callable() { - @Override - public ResultSet call() throws Exception { - try { - getStatementExecutor() - .invokeInterceptors( - statement, - StatementExecutionStep.EXECUTE_STATEMENT, - ReadWriteTransaction.this); - ResultSet delegate = - DirectExecuteResultSet.ofResultSet( - internalExecuteQuery(statement, analyzeMode, options)); - return createAndAddRetryResultSet( - delegate, statement, analyzeMode, options); - } catch (AbortedException e) { - throw e; - } catch (SpannerException e) { - createAndAddFailedQuery(e, statement, analyzeMode, options); - throw e; - } - } - }); - } - }, - InterceptorsUsage - .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the - // Callable. - } else { - return super.executeQuery(statement, analyzeMode, options); - } - } catch (SpannerException e) { - handlePossibleInvalidatingException(e); - throw e; - } - } - - @Override - public long executeUpdate(final ParsedStatement update) { - Preconditions.checkNotNull(update); - Preconditions.checkArgument(update.isUpdate(), "The statement is not an update statement"); - checkValidTransaction(); - try { - if (retryAbortsInternally) { - return asyncExecuteStatement( - update, - new Callable() { - @Override - public Long call() throws Exception { - return runWithRetry( - new Callable() { - @Override - public Long call() throws Exception { - try { - getStatementExecutor() - .invokeInterceptors( - update, - StatementExecutionStep.EXECUTE_STATEMENT, - ReadWriteTransaction.this); - long updateCount = txContext.executeUpdate(update.getStatement()); - createAndAddRetriableUpdate(update, updateCount); - return updateCount; - } catch (AbortedException e) { - throw e; - } catch (SpannerException e) { - createAndAddFailedUpdate(e, update); - throw e; - } - } - }); - } - }, - InterceptorsUsage - .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the - // Callable. - } else { - return asyncExecuteStatement( - update, - new Callable() { - @Override - public Long call() throws Exception { - return txContext.executeUpdate(update.getStatement()); - } - }); - } - } catch (SpannerException e) { - handlePossibleInvalidatingException(e); - throw e; - } - } - - /** - * Create a RUN BATCH statement to use with the {@link #executeBatchUpdate(Iterable)} method to - * allow it to be cancelled, time out or retried. - * - *

    {@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, - * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout - * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link - * #executeBatchUpdate(Iterable)} method is called, we do not have one {@link ParsedStatement}, - * and the method uses this statement instead in order to use the same logic as the other - * statements. - */ - static final ParsedStatement EXECUTE_BATCH_UPDATE_STATEMENT = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - - @Override - public long[] executeBatchUpdate(final Iterable updates) { - Preconditions.checkNotNull(updates); - final List updateStatements = new LinkedList<>(); - for (ParsedStatement update : updates) { - Preconditions.checkArgument( - update.isUpdate(), - "Statement is not an update statement: " + update.getSqlWithoutComments()); - updateStatements.add(update.getStatement()); - } - checkValidTransaction(); - try { - if (retryAbortsInternally) { - return asyncExecuteStatement( - EXECUTE_BATCH_UPDATE_STATEMENT, - new Callable() { - @Override - public long[] call() throws Exception { - return runWithRetry( - new Callable() { - @Override - public long[] call() throws Exception { - try { - getStatementExecutor() - .invokeInterceptors( - EXECUTE_BATCH_UPDATE_STATEMENT, - StatementExecutionStep.EXECUTE_STATEMENT, - ReadWriteTransaction.this); - long[] updateCounts = txContext.batchUpdate(updateStatements); - createAndAddRetriableBatchUpdate(updateStatements, updateCounts); - return updateCounts; - } catch (AbortedException e) { - throw e; - } catch (SpannerException e) { - createAndAddFailedBatchUpdate(e, updateStatements); - throw e; - } - } - }); - } - }, - InterceptorsUsage - .IGNORE_INTERCEPTORS); // ignore interceptors here as they are invoked in the - // Callable. - } else { - return asyncExecuteStatement( - EXECUTE_BATCH_UPDATE_STATEMENT, - new Callable() { - @Override - public long[] call() throws Exception { - return txContext.batchUpdate(updateStatements); - } - }); - } - } catch (SpannerException e) { - handlePossibleInvalidatingException(e); - throw e; - } - } - - @Override - public void write(Mutation mutation) { - Preconditions.checkNotNull(mutation); - checkValidTransaction(); - mutations.add(mutation); - } - - @Override - public void write(Iterable mutations) { - Preconditions.checkNotNull(mutations); - checkValidTransaction(); - for (Mutation mutation : mutations) { - this.mutations.add(checkNotNull(mutation)); - } - } - - /** - * Create a COMMIT statement to use with the {@link #commit()} method to allow it to be cancelled, - * time out or retried. - * - *

    {@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, - * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout - * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link - * #commit()} method is called directly, we do not have a {@link ParsedStatement}, and the method - * uses this statement instead in order to use the same logic as the other statements. - */ - private static final ParsedStatement COMMIT_STATEMENT = - StatementParser.INSTANCE.parse(Statement.of("COMMIT")); - - private final Callable commitCallable = - new Callable() { - @Override - public Void call() throws Exception { - txContext.buffer(mutations); - txManager.commit(); - return null; - } - }; - - @Override - public void commit() { - checkValidTransaction(); - try { - if (retryAbortsInternally) { - asyncExecuteStatement( - COMMIT_STATEMENT, - new Callable() { - @Override - public Void call() throws Exception { - return runWithRetry( - new Callable() { - @Override - public Void call() throws Exception { - getStatementExecutor() - .invokeInterceptors( - COMMIT_STATEMENT, - StatementExecutionStep.EXECUTE_STATEMENT, - ReadWriteTransaction.this); - commitCallable.call(); - return null; - } - }); - } - }, - InterceptorsUsage.IGNORE_INTERCEPTORS); - } else { - asyncExecuteStatement(COMMIT_STATEMENT, commitCallable); - } - ReadWriteTransaction.this.state = UnitOfWorkState.COMMITTED; - } catch (SpannerException e) { - try { - txManager.close(); - } catch (Throwable t) { - // ignore - } - this.state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } - } - - /** - * Executes a database call that could throw an {@link AbortedException}. If an {@link - * AbortedException} is thrown, the transaction will automatically be retried and the checksums of - * all {@link ResultSet}s and update counts of DML statements will be checked against the original - * values of the original transaction. If the checksums and/or update counts do not match, the - * method will throw an {@link AbortedException} that cannot be retried, as the underlying data - * have actually changed. - * - *

    If {@link ReadWriteTransaction#retryAbortsInternally} has been set to false, - * this method will throw an exception instead of retrying the transaction if the transaction was - * aborted. - * - * @param callable The actual database calls. - * @return the results of the database calls. - * @throws SpannerException if the database calls threw an exception, an {@link - * AbortedDueToConcurrentModificationException} if a retry of the transaction yielded - * different results than the original transaction, or an {@link AbortedException} if the - * maximum number of retries has been exceeded. - */ - T runWithRetry(Callable callable) throws SpannerException { - while (true) { - try { - return callable.call(); - } catch (final AbortedException aborted) { - if (retryAbortsInternally) { - handleAborted(aborted); - } else { - throw aborted; - } - } catch (SpannerException e) { - throw e; - } catch (Exception e) { - throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, e.getMessage(), e); - } - } - } - - /** - * Registers a {@link ResultSet} on this transaction that must be checked during a retry, and - * returns a retryable {@link ResultSet}. - */ - private ResultSet createAndAddRetryResultSet( - ResultSet resultSet, - ParsedStatement statement, - AnalyzeMode analyzeMode, - QueryOption... options) { - if (retryAbortsInternally) { - ChecksumResultSet checksumResultSet = - createChecksumResultSet(resultSet, statement, analyzeMode, options); - addRetryStatement(checksumResultSet); - return checksumResultSet; - } - return resultSet; - } - - /** Registers the statement as a query that should return an error during a retry. */ - private void createAndAddFailedQuery( - SpannerException e, - ParsedStatement statement, - AnalyzeMode analyzeMode, - QueryOption... options) { - if (retryAbortsInternally) { - addRetryStatement(new FailedQuery(this, e, statement, analyzeMode, options)); - } - } - - private void createAndAddRetriableUpdate(ParsedStatement update, long updateCount) { - if (retryAbortsInternally) { - addRetryStatement(new RetriableUpdate(this, update, updateCount)); - } - } - - private void createAndAddRetriableBatchUpdate(Iterable updates, long[] updateCounts) { - if (retryAbortsInternally) { - addRetryStatement(new RetriableBatchUpdate(this, updates, updateCounts)); - } - } - - /** Registers the statement as an update that should return an error during a retry. */ - private void createAndAddFailedUpdate(SpannerException e, ParsedStatement update) { - if (retryAbortsInternally) { - addRetryStatement(new FailedUpdate(this, e, update)); - } - } - - /** Registers the statements as a batch of updates that should return an error during a retry. */ - private void createAndAddFailedBatchUpdate(SpannerException e, Iterable updates) { - if (retryAbortsInternally) { - addRetryStatement(new FailedBatchUpdate(this, e, updates)); - } - } - - /** - * Adds a statement to the list of statements that should be retried if this transaction aborts. - */ - private void addRetryStatement(RetriableStatement statement) { - Preconditions.checkState( - retryAbortsInternally, "retryAbortsInternally is not enabled for this transaction"); - statements.add(statement); - } - - /** - * Handles an aborted exception by checking whether the transaction may be retried internally, and - * if so, does the retry. If retry is not allowed, or if the retry fails, the method will throw an - * {@link AbortedException}. - */ - private void handleAborted(AbortedException aborted) { - if (transactionRetryAttempts >= MAX_INTERNAL_RETRIES) { - // If the same statement in transaction keeps aborting, then we need to abort here. - throwAbortWithRetryAttemptsExceeded(); - } else if (retryAbortsInternally) { - logger.fine(toString() + ": Starting internal transaction retry"); - while (true) { - // First back off and then restart the transaction. - try { - Thread.sleep(aborted.getRetryDelayInMillis() / 1000); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.CANCELLED, "The statement was cancelled"); - } - try { - txContext = txManager.resetForRetry(); - // Inform listeners about the transaction retry that is about to start. - invokeTransactionRetryListenersOnStart(); - // Then retry all transaction statements. - transactionRetryAttempts++; - for (RetriableStatement statement : statements) { - statement.retry(aborted); - } - successfulRetries++; - invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_SUCCESSFUL); - logger.fine( - toString() - + ": Internal transaction retry succeeded. Starting retry of original statement."); - // Retry succeeded, return and continue the original transaction. - break; - } catch (AbortedDueToConcurrentModificationException e) { - // Retry failed because of a concurrent modification, we have to abort. - invokeTransactionRetryListenersOnFinish( - RetryResult.RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION); - logger.fine( - toString() + ": Internal transaction retry aborted due to a concurrent modification"); - // Try to rollback the new transaction and ignore any exceptions. - try { - txManager.rollback(); - } catch (Throwable t) { - // ignore - } - this.state = UnitOfWorkState.ABORTED; - throw e; - } catch (AbortedException e) { - // Retry aborted, do another retry of the transaction. - if (transactionRetryAttempts >= MAX_INTERNAL_RETRIES) { - throwAbortWithRetryAttemptsExceeded(); - } - invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_ABORTED_AND_RESTARTING); - logger.fine(toString() + ": Internal transaction retry aborted, trying again"); - } catch (SpannerException e) { - // unexpected exception - logger.log( - Level.FINE, - toString() + ": Internal transaction retry failed due to an unexpected exception", - e); - // Try to rollback the new transaction and ignore any exceptions. - try { - txManager.rollback(); - } catch (Throwable t) { - // ignore - } - // Set transaction state to aborted as the retry failed. - this.state = UnitOfWorkState.ABORTED; - // Re-throw underlying exception. - throw e; - } - } - } else { - try { - txManager.close(); - } catch (Throwable t) { - // ignore - } - // Internal retry is not enabled. - this.state = UnitOfWorkState.ABORTED; - throw aborted; - } - } - - private void throwAbortWithRetryAttemptsExceeded() throws SpannerException { - invokeTransactionRetryListenersOnFinish(RetryResult.RETRY_ABORTED_AND_MAX_ATTEMPTS_EXCEEDED); - logger.fine( - toString() - + ": Internal transaction retry aborted and max number of retry attempts has been exceeded"); - // Try to rollback the transaction and ignore any exceptions. - // Normally it should not be necessary to do this, but in order to be sure we never leak - // any sessions it is better to do so. - try { - txManager.rollback(); - } catch (Throwable t) { - // ignore - } - this.state = UnitOfWorkState.ABORTED; - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.ABORTED, MAX_INTERNAL_RETRIES_EXCEEDED); - } - - private void invokeTransactionRetryListenersOnStart() { - for (TransactionRetryListener listener : transactionRetryListeners) { - listener.retryStarting(transactionStarted, transactionId, transactionRetryAttempts); - } - } - - private void invokeTransactionRetryListenersOnFinish(RetryResult result) { - for (TransactionRetryListener listener : transactionRetryListeners) { - listener.retryFinished(transactionStarted, transactionId, transactionRetryAttempts, result); - } - } - - /** The {@link Statement} and {@link Callable} for rollbacks */ - private final ParsedStatement rollbackStatement = - StatementParser.INSTANCE.parse(Statement.of("ROLLBACK")); - - private final Callable rollbackCallable = - new Callable() { - @Override - public Void call() throws Exception { - txManager.rollback(); - return null; - } - }; - - @Override - public void rollback() { - ConnectionPreconditions.checkState( - state == UnitOfWorkState.STARTED, "This transaction has status " + state.name()); - try { - asyncExecuteStatement(rollbackStatement, rollbackCallable); - } finally { - // Whatever happens, we should always call close in order to return the underlying session to - // the session pool to avoid any session leaks. - try { - txManager.close(); - } catch (Throwable e) { - // ignore - } - this.state = UnitOfWorkState.ROLLED_BACK; - } - } - - /** - * A retriable statement is a query or DML statement during a read/write transaction that can be - * retried if the original transaction aborted. - */ - interface RetriableStatement { - /** - * Retry this statement in a new transaction. Throws an {@link - * AbortedDueToConcurrentModificationException} if the retry could not successfully be executed - * because of an actual concurrent modification of the underlying data. This {@link - * AbortedDueToConcurrentModificationException} cannot be retried. - */ - void retry(AbortedException aborted) throws AbortedException; - } - - /** Creates a {@link ChecksumResultSet} for this {@link ReadWriteTransaction}. */ - @VisibleForTesting - ChecksumResultSet createChecksumResultSet( - ResultSet delegate, - ParsedStatement statement, - AnalyzeMode analyzeMode, - QueryOption... options) { - return new ChecksumResultSet(this, delegate, statement, analyzeMode, options); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java deleted file mode 100644 index 0a72b36951c9..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSet.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2019 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.ByteArray; -import com.google.cloud.Date; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type; -import com.google.common.base.Preconditions; -import com.google.spanner.v1.ResultSetStats; -import java.util.List; - -/** - * Forwarding implementation of {@link ResultSet} that forwards all calls to a delegate that can be - * replaced. This is used by the JDBC Driver when a read/write transaction is successfully retried. - * Any {@link ResultSet} that is open during a transaction retry, must be replaced by a result set - * that is fetched using the new transaction. This is achieved by wrapping the returned result sets - * in a {@link ReplaceableForwardingResultSet} that replaces its delegate after a transaction retry. - */ -class ReplaceableForwardingResultSet implements ResultSet { - private ResultSet delegate; - private boolean closed; - - ReplaceableForwardingResultSet(ResultSet delegate) { - this.delegate = Preconditions.checkNotNull(delegate); - } - - /** Replace the underlying delegate {@link ResultSet} with a new one. */ - void replaceDelegate(ResultSet delegate) { - Preconditions.checkNotNull(delegate); - checkClosed(); - if (this.delegate != null) { - this.delegate.close(); - } - this.delegate = delegate; - } - - private void checkClosed() { - if (closed) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "This ResultSet is closed"); - } - } - - boolean isClosed() { - return closed; - } - - @Override - public boolean next() throws SpannerException { - checkClosed(); - return delegate.next(); - } - - @Override - public Struct getCurrentRowAsStruct() { - checkClosed(); - return delegate.getCurrentRowAsStruct(); - } - - @Override - public void close() { - if (delegate != null) { - delegate.close(); - delegate = null; - } - closed = true; - } - - @Override - public ResultSetStats getStats() { - checkClosed(); - return delegate.getStats(); - } - - @Override - public Type getType() { - checkClosed(); - return delegate.getType(); - } - - @Override - public int getColumnCount() { - checkClosed(); - return delegate.getColumnCount(); - } - - @Override - public int getColumnIndex(String columnName) { - checkClosed(); - return delegate.getColumnIndex(columnName); - } - - @Override - public Type getColumnType(int columnIndex) { - checkClosed(); - return delegate.getColumnType(columnIndex); - } - - @Override - public Type getColumnType(String columnName) { - checkClosed(); - return delegate.getColumnType(columnName); - } - - @Override - public boolean isNull(int columnIndex) { - checkClosed(); - return delegate.isNull(columnIndex); - } - - @Override - public boolean isNull(String columnName) { - checkClosed(); - return delegate.isNull(columnName); - } - - @Override - public boolean getBoolean(int columnIndex) { - checkClosed(); - return delegate.getBoolean(columnIndex); - } - - @Override - public boolean getBoolean(String columnName) { - checkClosed(); - return delegate.getBoolean(columnName); - } - - @Override - public long getLong(int columnIndex) { - checkClosed(); - return delegate.getLong(columnIndex); - } - - @Override - public long getLong(String columnName) { - checkClosed(); - return delegate.getLong(columnName); - } - - @Override - public double getDouble(int columnIndex) { - checkClosed(); - return delegate.getDouble(columnIndex); - } - - @Override - public double getDouble(String columnName) { - checkClosed(); - return delegate.getDouble(columnName); - } - - @Override - public String getString(int columnIndex) { - checkClosed(); - return delegate.getString(columnIndex); - } - - @Override - public String getString(String columnName) { - checkClosed(); - return delegate.getString(columnName); - } - - @Override - public ByteArray getBytes(int columnIndex) { - checkClosed(); - return delegate.getBytes(columnIndex); - } - - @Override - public ByteArray getBytes(String columnName) { - checkClosed(); - return delegate.getBytes(columnName); - } - - @Override - public Timestamp getTimestamp(int columnIndex) { - checkClosed(); - return delegate.getTimestamp(columnIndex); - } - - @Override - public Timestamp getTimestamp(String columnName) { - checkClosed(); - return delegate.getTimestamp(columnName); - } - - @Override - public Date getDate(int columnIndex) { - checkClosed(); - return delegate.getDate(columnIndex); - } - - @Override - public Date getDate(String columnName) { - checkClosed(); - return delegate.getDate(columnName); - } - - @Override - public boolean[] getBooleanArray(int columnIndex) { - checkClosed(); - return delegate.getBooleanArray(columnIndex); - } - - @Override - public boolean[] getBooleanArray(String columnName) { - checkClosed(); - return delegate.getBooleanArray(columnName); - } - - @Override - public List getBooleanList(int columnIndex) { - checkClosed(); - return delegate.getBooleanList(columnIndex); - } - - @Override - public List getBooleanList(String columnName) { - checkClosed(); - return delegate.getBooleanList(columnName); - } - - @Override - public long[] getLongArray(int columnIndex) { - checkClosed(); - return delegate.getLongArray(columnIndex); - } - - @Override - public long[] getLongArray(String columnName) { - checkClosed(); - return delegate.getLongArray(columnName); - } - - @Override - public List getLongList(int columnIndex) { - checkClosed(); - return delegate.getLongList(columnIndex); - } - - @Override - public List getLongList(String columnName) { - checkClosed(); - return delegate.getLongList(columnName); - } - - @Override - public double[] getDoubleArray(int columnIndex) { - checkClosed(); - return delegate.getDoubleArray(columnIndex); - } - - @Override - public double[] getDoubleArray(String columnName) { - checkClosed(); - return delegate.getDoubleArray(columnName); - } - - @Override - public List getDoubleList(int columnIndex) { - checkClosed(); - return delegate.getDoubleList(columnIndex); - } - - @Override - public List getDoubleList(String columnName) { - checkClosed(); - return delegate.getDoubleList(columnName); - } - - @Override - public List getStringList(int columnIndex) { - checkClosed(); - return delegate.getStringList(columnIndex); - } - - @Override - public List getStringList(String columnName) { - checkClosed(); - return delegate.getStringList(columnName); - } - - @Override - public List getBytesList(int columnIndex) { - checkClosed(); - return delegate.getBytesList(columnIndex); - } - - @Override - public List getBytesList(String columnName) { - checkClosed(); - return delegate.getBytesList(columnName); - } - - @Override - public List getTimestampList(int columnIndex) { - checkClosed(); - return delegate.getTimestampList(columnIndex); - } - - @Override - public List getTimestampList(String columnName) { - checkClosed(); - return delegate.getTimestampList(columnName); - } - - @Override - public List getDateList(int columnIndex) { - checkClosed(); - return delegate.getDateList(columnIndex); - } - - @Override - public List getDateList(String columnName) { - checkClosed(); - return delegate.getDateList(columnName); - } - - @Override - public List getStructList(int columnIndex) { - checkClosed(); - return delegate.getStructList(columnIndex); - } - - @Override - public List getStructList(String columnName) { - checkClosed(); - return delegate.getStructList(columnName); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java deleted file mode 100644 index 73609e8ba62f..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableBatchUpdate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019 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.AbortedException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.common.base.Preconditions; -import java.util.Arrays; - -/** - * Retriable batch of DML statements. The check whether the statements had the same effect during - * retry is done by comparing the number of records affected. - */ -final class RetriableBatchUpdate implements RetriableStatement { - private final ReadWriteTransaction transaction; - private final Iterable statements; - private final long[] updateCounts; - - RetriableBatchUpdate( - ReadWriteTransaction transaction, Iterable statements, long[] updateCounts) { - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(statements); - this.transaction = transaction; - this.statements = statements; - this.updateCounts = updateCounts; - } - - @Override - public void retry(AbortedException aborted) throws AbortedException { - long[] newCount = null; - try { - transaction - .getStatementExecutor() - .invokeInterceptors( - ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, - StatementExecutionStep.RETRY_STATEMENT, - transaction); - newCount = transaction.getReadContext().batchUpdate(statements); - } catch (AbortedException e) { - // Just re-throw the AbortedException and let the retry logic determine whether another try - // should be executed or not. - throw e; - } catch (SpannerException e) { - // Unexpected database error that is different from the original transaction. - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } - if (newCount == null || !Arrays.equals(updateCounts, newCount)) { - // The update counts do not match, we cannot retry the transaction. - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java deleted file mode 100644 index ac2b82422465..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/RetriableUpdate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 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.AbortedException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.jdbc.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; - -/** - * Retriable DML statement. The check whether the statement had the same effect during retry is done - * by comparing the number of records affected. - */ -final class RetriableUpdate implements RetriableStatement { - private final ReadWriteTransaction transaction; - private final ParsedStatement statement; - private final long updateCount; - - RetriableUpdate(ReadWriteTransaction transaction, ParsedStatement statement, long updateCount) { - Preconditions.checkNotNull(transaction); - Preconditions.checkNotNull(statement); - this.transaction = transaction; - this.statement = statement; - this.updateCount = updateCount; - } - - @Override - public void retry(AbortedException aborted) throws AbortedException { - long newCount = -1; - try { - transaction - .getStatementExecutor() - .invokeInterceptors(statement, StatementExecutionStep.RETRY_STATEMENT, transaction); - newCount = transaction.getReadContext().executeUpdate(statement.getStatement()); - } catch (AbortedException e) { - // Just re-throw the AbortedException and let the retry logic determine whether another try - // should be executed or not. - throw e; - } catch (SpannerException e) { - // Unexpected database error that is different from the original transaction. - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted, e); - } - if (newCount != updateCount) { - // The update counts do not match, we cannot retry the transaction. - throw SpannerExceptionFactory.newAbortedDueToConcurrentModificationException(aborted); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java deleted file mode 100644 index a5d61d5bd778..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SingleUseTransaction.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright 2019 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.api.gax.longrunning.OperationFuture; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadOnlyTransaction; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerBatchUpdateException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionRunner; -import com.google.cloud.spanner.TransactionRunner.TransactionCallable; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.common.base.Preconditions; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -/** - * Transaction that is used when a {@link Connection} is in autocommit mode. Each method on this - * transaction actually starts a new transaction on Spanner. The type of transaction that is started - * depends on the type of statement that is being executed. A {@link SingleUseTransaction} will - * always try to choose the most efficient type of one-time transaction that is available for the - * statement. - * - *

    A {@link SingleUseTransaction} can be used to execute any type of statement on Cloud Spanner: - * - *

      - *
    • Client side statements, e.g. SHOW VARIABLE AUTOCOMMIT - *
    • Queries, e.g. SELECT * FROM FOO - *
    • DML statements, e.g. UPDATE FOO SET BAR=1 - *
    • DDL statements, e.g. CREATE TABLE FOO (...) - *
    - */ -class SingleUseTransaction extends AbstractBaseUnitOfWork { - private final boolean readOnly; - private final DdlClient ddlClient; - private final DatabaseClient dbClient; - private final TimestampBound readOnlyStaleness; - private final AutocommitDmlMode autocommitDmlMode; - private Timestamp readTimestamp = null; - private volatile TransactionManager txManager; - private TransactionRunner writeTransaction; - private boolean used = false; - private UnitOfWorkState state = UnitOfWorkState.STARTED; - - static class Builder extends AbstractBaseUnitOfWork.Builder { - private DdlClient ddlClient; - private DatabaseClient dbClient; - private boolean readOnly; - private TimestampBound readOnlyStaleness; - private AutocommitDmlMode autocommitDmlMode; - - private Builder() {} - - Builder setDdlClient(DdlClient ddlClient) { - Preconditions.checkNotNull(ddlClient); - this.ddlClient = ddlClient; - return this; - } - - Builder setDatabaseClient(DatabaseClient client) { - Preconditions.checkNotNull(client); - this.dbClient = client; - return this; - } - - Builder setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - return this; - } - - Builder setReadOnlyStaleness(TimestampBound staleness) { - Preconditions.checkNotNull(staleness); - this.readOnlyStaleness = staleness; - return this; - } - - Builder setAutocommitDmlMode(AutocommitDmlMode dmlMode) { - Preconditions.checkNotNull(dmlMode); - this.autocommitDmlMode = dmlMode; - return this; - } - - @Override - SingleUseTransaction build() { - Preconditions.checkState(ddlClient != null, "No DDL client specified"); - Preconditions.checkState(dbClient != null, "No DatabaseClient client specified"); - Preconditions.checkState(readOnlyStaleness != null, "No read-only staleness specified"); - Preconditions.checkState(autocommitDmlMode != null, "No autocommit dml mode specified"); - return new SingleUseTransaction(this); - } - } - - static Builder newBuilder() { - return new Builder(); - } - - private SingleUseTransaction(Builder builder) { - super(builder); - this.ddlClient = builder.ddlClient; - this.dbClient = builder.dbClient; - this.readOnly = builder.readOnly; - this.readOnlyStaleness = builder.readOnlyStaleness; - this.autocommitDmlMode = builder.autocommitDmlMode; - } - - @Override - public Type getType() { - return Type.TRANSACTION; - } - - @Override - public UnitOfWorkState getState() { - return state; - } - - @Override - public boolean isActive() { - // Single-use transactions are never active as they can be used only once. - return false; - } - - @Override - public boolean isReadOnly() { - return readOnly; - } - - private void checkAndMarkUsed() { - Preconditions.checkState(!used, "This single-use transaction has already been used"); - used = true; - } - - @Override - public ResultSet executeQuery( - final ParsedStatement statement, - final AnalyzeMode analyzeMode, - final QueryOption... options) { - Preconditions.checkNotNull(statement); - Preconditions.checkArgument(statement.isQuery(), "Statement is not a query"); - checkAndMarkUsed(); - - final ReadOnlyTransaction currentTransaction = - dbClient.singleUseReadOnlyTransaction(readOnlyStaleness); - Callable callable = - new Callable() { - @Override - public ResultSet call() throws Exception { - try { - ResultSet rs; - if (analyzeMode == AnalyzeMode.NONE) { - rs = currentTransaction.executeQuery(statement.getStatement(), options); - } else { - rs = - currentTransaction.analyzeQuery( - statement.getStatement(), analyzeMode.getQueryAnalyzeMode()); - } - // Return a DirectExecuteResultSet, which will directly do a next() call in order to - // ensure that the query is actually sent to Spanner. - return DirectExecuteResultSet.ofResultSet(rs); - } finally { - currentTransaction.close(); - } - } - }; - try { - ResultSet res = asyncExecuteStatement(statement, callable); - readTimestamp = currentTransaction.getReadTimestamp(); - state = UnitOfWorkState.COMMITTED; - return res; - } catch (Throwable e) { - state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } finally { - currentTransaction.close(); - } - } - - @Override - public Timestamp getReadTimestamp() { - ConnectionPreconditions.checkState( - readTimestamp != null, "There is no read timestamp available for this transaction."); - return readTimestamp; - } - - @Override - public Timestamp getReadTimestampOrNull() { - return readTimestamp; - } - - private boolean hasCommitTimestamp() { - return writeTransaction != null - || (txManager != null - && txManager.getState() - == com.google.cloud.spanner.TransactionManager.TransactionState.COMMITTED); - } - - @Override - public Timestamp getCommitTimestamp() { - ConnectionPreconditions.checkState( - hasCommitTimestamp(), "There is no commit timestamp available for this transaction."); - return writeTransaction != null - ? writeTransaction.getCommitTimestamp() - : txManager.getCommitTimestamp(); - } - - @Override - public Timestamp getCommitTimestampOrNull() { - if (hasCommitTimestamp()) { - try { - return writeTransaction != null - ? writeTransaction.getCommitTimestamp() - : txManager.getCommitTimestamp(); - } catch (SpannerException e) { - // ignore - } - } - return null; - } - - @Override - public void executeDdl(final ParsedStatement ddl) { - Preconditions.checkNotNull(ddl); - Preconditions.checkArgument( - ddl.getType() == StatementType.DDL, "Statement is not a ddl statement"); - ConnectionPreconditions.checkState( - !isReadOnly(), "DDL statements are not allowed in read-only mode"); - checkAndMarkUsed(); - - try { - Callable callable = - new Callable() { - @Override - public Void call() throws Exception { - OperationFuture operation = - ddlClient.executeDdl(ddl.getSqlWithoutComments()); - return operation.get(); - } - }; - asyncExecuteStatement(ddl, callable); - state = UnitOfWorkState.COMMITTED; - } catch (Throwable e) { - state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } - } - - @Override - public long executeUpdate(final ParsedStatement update) { - Preconditions.checkNotNull(update); - Preconditions.checkArgument(update.isUpdate(), "Statement is not an update statement"); - ConnectionPreconditions.checkState( - !isReadOnly(), "Update statements are not allowed in read-only mode"); - checkAndMarkUsed(); - - long res; - try { - switch (autocommitDmlMode) { - case TRANSACTIONAL: - res = executeAsyncTransactionalUpdate(update, new TransactionalUpdateCallable(update)); - break; - case PARTITIONED_NON_ATOMIC: - res = executeAsyncPartitionedUpdate(update); - break; - default: - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Unknown dml mode: " + autocommitDmlMode); - } - } catch (Throwable e) { - state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } - state = UnitOfWorkState.COMMITTED; - return res; - } - - /** Execute an update statement as a partitioned DML statement. */ - private long executeAsyncPartitionedUpdate(final ParsedStatement update) { - Callable callable = - new Callable() { - @Override - public Long call() throws Exception { - return dbClient.executePartitionedUpdate(update.getStatement()); - } - }; - return asyncExecuteStatement(update, callable); - } - - private final ParsedStatement executeBatchUpdateStatement = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - - @Override - public long[] executeBatchUpdate(Iterable updates) { - Preconditions.checkNotNull(updates); - for (ParsedStatement update : updates) { - Preconditions.checkArgument( - update.isUpdate(), - "Statement is not an update statement: " + update.getSqlWithoutComments()); - } - ConnectionPreconditions.checkState( - !isReadOnly(), "Batch update statements are not allowed in read-only mode"); - checkAndMarkUsed(); - - long[] res; - try { - switch (autocommitDmlMode) { - case TRANSACTIONAL: - res = - executeAsyncTransactionalUpdate( - executeBatchUpdateStatement, new TransactionalBatchUpdateCallable(updates)); - break; - case PARTITIONED_NON_ATOMIC: - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "Batch updates are not allowed in " + autocommitDmlMode); - default: - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Unknown dml mode: " + autocommitDmlMode); - } - } catch (SpannerBatchUpdateException e) { - // Batch update exceptions does not cause a rollback. - state = UnitOfWorkState.COMMITTED; - throw e; - } catch (Throwable e) { - state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } - state = UnitOfWorkState.COMMITTED; - return res; - } - - /** Base class for executing DML updates (both single statements and batches). */ - private abstract class AbstractUpdateCallable implements Callable { - abstract T executeUpdate(TransactionContext txContext); - - @Override - public T call() throws Exception { - try { - txManager = dbClient.transactionManager(); - // Check the interrupted state after each (possible) round-trip to the db to allow the - // statement to be cancelled. - checkInterrupted(); - try (TransactionContext txContext = txManager.begin()) { - checkInterrupted(); - T res = executeUpdate(txContext); - checkInterrupted(); - txManager.commit(); - checkInterrupted(); - return res; - } - } finally { - if (txManager != null) { - // Calling txManager.close() will rollback the transaction if it is still active, i.e. if - // an error occurred before the commit() call returned successfully. - txManager.close(); - } - } - } - } - - /** {@link Callable} for a single update statement. */ - private final class TransactionalUpdateCallable extends AbstractUpdateCallable { - private final ParsedStatement update; - - private TransactionalUpdateCallable(ParsedStatement update) { - this.update = update; - } - - @Override - Long executeUpdate(TransactionContext txContext) { - return txContext.executeUpdate(update.getStatement()); - } - } - - /** {@link Callable} for a batch update. */ - private final class TransactionalBatchUpdateCallable extends AbstractUpdateCallable { - private final List updates; - - private TransactionalBatchUpdateCallable(Iterable updates) { - this.updates = new LinkedList<>(); - for (ParsedStatement update : updates) { - this.updates.add(update.getStatement()); - } - } - - @Override - long[] executeUpdate(TransactionContext txContext) { - return txContext.batchUpdate(updates); - } - } - - private T executeAsyncTransactionalUpdate( - final ParsedStatement update, final AbstractUpdateCallable callable) { - long startedTime = System.currentTimeMillis(); - // This method uses a TransactionManager instead of the TransactionRunner in order to be able to - // handle timeouts and canceling of a statement. - while (true) { - try { - return asyncExecuteStatement(update, callable); - } catch (AbortedException e) { - try { - Thread.sleep(e.getRetryDelayInMillis() / 1000); - } catch (InterruptedException e1) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.CANCELLED, "Statement execution was interrupted", e1); - } - // Check whether the timeout time has been exceeded. - long executionTime = System.currentTimeMillis() - startedTime; - if (getStatementTimeout().hasTimeout() - && executionTime > getStatementTimeout().getTimeoutValue(TimeUnit.MILLISECONDS)) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.DEADLINE_EXCEEDED, - "Statement execution timeout occurred for " + update.getSqlWithoutComments()); - } - } - } - } - - private void checkInterrupted() throws InterruptedException { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - } - - @Override - public void write(final Mutation mutation) { - write(Arrays.asList(mutation)); - } - - @Override - public void write(final Iterable mutations) { - Preconditions.checkNotNull(mutations); - ConnectionPreconditions.checkState( - !isReadOnly(), "Update statements are not allowed in read-only mode"); - checkAndMarkUsed(); - - writeTransaction = dbClient.readWriteTransaction(); - try { - writeTransaction.run( - new TransactionCallable() { - @Override - public Void run(TransactionContext transaction) throws Exception { - transaction.buffer(mutations); - return null; - } - }); - } catch (Throwable e) { - state = UnitOfWorkState.COMMIT_FAILED; - throw e; - } - state = UnitOfWorkState.COMMITTED; - } - - @Override - public void commit() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Commit is not supported for single-use transactions"); - } - - @Override - public void rollback() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Rollback is not supported for single-use transactions"); - } - - @Override - public long[] runBatch() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for single-use transactions"); - } - - @Override - public void abortBatch() { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "Run batch is not supported for single-use transactions"); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java index 771ad505c77f..8bcbcc1952c0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Google LLC + * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,413 +16,14 @@ package com.google.cloud.spanner.jdbc; -import com.google.api.core.ApiFunction; -import com.google.auth.Credentials; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.SpannerOptions; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.MoreObjects; -import com.google.common.base.Preconditions; -import io.grpc.ManagedChannelBuilder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.concurrent.GuardedBy; - -/** - * Pool for keeping track of {@link Spanner} instances needed by JDBC connections. - * - *

    When a JDBC connection is opened for a Google Cloud Spanner database, a {@link Spanner} object - * can be opened in the background. The {@link SpannerPool} keeps track of which {@link Spanner} - * objects have been opened by connections during the lifetime of the JVM, which connections are - * still opened and closed, and which {@link Spanner} objects could be closed. - * - *

    Call the method {@link SpannerPool#closeSpannerPool()} at the end of your application to - * gracefully shutdown all instances in the pool. - */ +/** @see com.google.cloud.spanner.connection.SpannerPool */ +@Deprecated public class SpannerPool { - private static final Logger logger = Logger.getLogger(SpannerPool.class.getName()); + private SpannerPool() {} - /** - * Closes the default {@link SpannerPool} and all {@link Spanner} instances that have been opened - * by connections and that are still open. Call this method at the end of your application to - * gracefully close all {@link Spanner} instances in the pool. Failing to call this method will - * keep your application running for 60 seconds after you close the last {@link - * java.sql.Connection} to Cloud Spanner, as this is the default timeout before the {@link - * SpannerPool} closes the unused {@link Spanner} instances. - */ + /** @see com.google.cloud.spanner.connection.SpannerPool#closeSpannerPool() */ + @Deprecated public static void closeSpannerPool() { - INSTANCE.checkAndCloseSpanners(); - } - - /** - * The minimum number of milliseconds a {@link Spanner} should not have been used for a connection - * before it is closed. - */ - private static final long DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED = 60000L; - - static final SpannerPool INSTANCE = - new SpannerPool(DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED); - - @VisibleForTesting - enum CheckAndCloseSpannersMode { - WARN, - ERROR; - } - - private final class CloseSpannerRunnable implements Runnable { - @Override - public void run() { - try { - checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); - } catch (Exception e) { - // ignore - } - } - } - - private final class CloseUnusedSpannersRunnable implements Runnable { - @Override - public void run() { - try { - closeUnusedSpanners(SpannerPool.this.closeSpannerAfterMillisecondsUnused); - } catch (Throwable e) { - logger.log(Level.FINE, "Scheduled call to closeUnusedSpanners failed", e); - } - } - } - - static class SpannerPoolKey { - private final String host; - private final String projectId; - private final Credentials credentials; - private final Integer numChannels; - private final boolean usePlainText; - private final String userAgent; - - private static SpannerPoolKey of(ConnectionOptions options) { - return new SpannerPoolKey(options); - } - - private SpannerPoolKey(ConnectionOptions options) { - this.host = options.getHost(); - this.projectId = options.getProjectId(); - this.credentials = options.getCredentials(); - this.numChannels = options.getNumChannels(); - this.usePlainText = options.isUsePlainText(); - this.userAgent = options.getUserAgent(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof SpannerPoolKey)) { - return false; - } - SpannerPoolKey other = (SpannerPoolKey) o; - return Objects.equals(this.host, other.host) - && Objects.equals(this.projectId, other.projectId) - && Objects.equals(this.credentials, other.credentials) - && Objects.equals(this.numChannels, other.numChannels) - && Objects.equals(this.usePlainText, other.usePlainText) - && Objects.equals(this.userAgent, other.userAgent); - } - - @Override - public int hashCode() { - return Objects.hash( - this.host, - this.projectId, - this.credentials, - this.numChannels, - this.usePlainText, - this.userAgent); - } - } - - /** - * The management threads of a {@link SpannerPool} are lazily initialized to prevent unnecessary - * threads to be created when the connection API is not used. - */ - private boolean initialized = false; - /** - * Thread that will be run as a shutdown hook on closing the application. This thread will close - * any Spanner instances opened by the Connection API that are still open. - */ - private Thread shutdownThread = null; - - /** - * Keep unused {@link Spanner} instances open and in the pool for this duration after all its - * {@link Connection}s have been closed. This prevents unnecessary opening and closing of {@link - * Spanner} instances. - */ - private final long closeSpannerAfterMillisecondsUnused; - - /** - * This scheduled task will close all {@link Spanner} objects that have not been used for an open - * connection for at least {@link SpannerPool#DEFAULT_CLOSE_SPANNER_AFTER_MILLISECONDS_UNUSED} - * milliseconds. - */ - private ScheduledExecutorService closerService; - - @GuardedBy("this") - private final Map spanners = new HashMap<>(); - - @GuardedBy("this") - private final Map> connections = new HashMap<>(); - - /** - * Keep track of the moment that the last connection for a specific {@link SpannerPoolKey} was - * closed, so that we can use this to determine whether a {@link Spanner} instance should be - * closed and removed from the pool. As {@link Spanner} instances are expensive to create and - * close, we do not want to do that unnecessarily. By adding a delay between the moment the last - * {@link Connection} for a {@link Spanner} was closed and the moment we close the {@link Spanner} - * instance, we prevent applications that open one or more connections for a process and close all - * these connections at the end of the process from getting a severe performance penalty from - * opening and closing {@link Spanner} instances all the time. - * - *

    {@link Spanner} instances are closed and removed from the pool when the last connection was - * closed more than {@link #closeSpannerAfterMillisecondsUnused} milliseconds ago. - */ - @GuardedBy("this") - private final Map lastConnectionClosedAt = new HashMap<>(); - - @VisibleForTesting - SpannerPool() { - this(0L); - } - - @VisibleForTesting - SpannerPool(long closeSpannerAfterMillisecondsUnused) { - this.closeSpannerAfterMillisecondsUnused = closeSpannerAfterMillisecondsUnused; - } - - /** - * Gets a Spanner object for a connection with the properties specified in the {@link - * ConnectionOptions} object. The {@link SpannerPool} will manage a pool of opened Spanner objects - * for the different connections, and reuse Spanner objects whenever possible. Spanner objects - * will also be closed down when the application is closing. - * - * @param options The specification of the Spanner database to connect to. - * @param connection The {@link ConnectionImpl} that will be created. This {@link ConnectionImpl} - * will be tracked by the pool to know when a {@link Spanner} object can be closed. - * @return an opened {@link Spanner} object that can be used by a connection to communicate with - * the Spanner database. - */ - Spanner getSpanner(ConnectionOptions options, ConnectionImpl connection) { - Preconditions.checkNotNull(options); - Preconditions.checkNotNull(connection); - SpannerPoolKey key = SpannerPoolKey.of(options); - Spanner spanner; - synchronized (this) { - if (!initialized) { - initialize(); - } - if (spanners.get(key) != null) { - spanner = spanners.get(key); - } else { - spanner = createSpanner(key); - spanners.put(key, spanner); - } - List registeredConnectionsForSpanner = connections.get(key); - if (registeredConnectionsForSpanner == null) { - registeredConnectionsForSpanner = new ArrayList<>(); - connections.put(key, registeredConnectionsForSpanner); - } - registeredConnectionsForSpanner.add(connection); - lastConnectionClosedAt.remove(key); - return spanner; - } - } - - private void initialize() { - shutdownThread = new Thread(new CloseSpannerRunnable(), "SpannerPool shutdown hook"); - Runtime.getRuntime().addShutdownHook(shutdownThread); - if (this.closeSpannerAfterMillisecondsUnused > 0) { - this.closerService = - Executors.newSingleThreadScheduledExecutor( - new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "close-unused-spanners-worker"); - thread.setDaemon(true); - return thread; - } - }); - this.closerService.scheduleAtFixedRate( - new CloseUnusedSpannersRunnable(), - this.closeSpannerAfterMillisecondsUnused, - this.closeSpannerAfterMillisecondsUnused, - TimeUnit.MILLISECONDS); - } - initialized = true; - } - - @SuppressWarnings("rawtypes") - @VisibleForTesting - Spanner createSpanner(SpannerPoolKey key) { - SpannerOptions.Builder builder = SpannerOptions.newBuilder(); - builder - .setClientLibToken(MoreObjects.firstNonNull(key.userAgent, JdbcDriver.getClientLibToken())) - .setHost(key.host) - .setProjectId(key.projectId) - .setCredentials(key.credentials); - if (key.numChannels != null) { - builder.setNumChannels(key.numChannels); - } - if (key.usePlainText) { - // Credentials may not be sent over a plain text channel. - builder.setCredentials(NoCredentials.getInstance()); - // Set a custom channel configurator to allow http instead of https. - builder.setChannelConfigurator( - new ApiFunction() { - @Override - public ManagedChannelBuilder apply(ManagedChannelBuilder input) { - input.usePlaintext(); - return input; - } - }); - } - return builder.build().getService(); - } - - /** - * Remove the given {@link ConnectionImpl} from the list of connections that should be monitored - * by this pool. - * - * @param options The {@link ConnectionOptions} that were used to create the connection. - * @param connection The {@link ConnectionImpl} to remove from this pool.. - */ - void removeConnection(ConnectionOptions options, ConnectionImpl connection) { - Preconditions.checkNotNull(options); - Preconditions.checkNotNull(connection); - SpannerPoolKey key = SpannerPoolKey.of(options); - synchronized (this) { - if (spanners.containsKey(key) && connections.containsKey(key)) { - List registeredConnections = connections.get(key); - // Remove the connection from the pool. - if (registeredConnections == null || !registeredConnections.remove(connection)) { - logger.log( - Level.WARNING, - "There are no connections registered for ConnectionOptions " + options.toString()); - } else { - // Check if this was the last connection for this spanner key. - if (registeredConnections.isEmpty()) { - // Register the moment the last connection for this Spanner key was removed, so we know - // which Spanner objects we could close. - lastConnectionClosedAt.put(key, System.currentTimeMillis()); - } - } - } else { - logger.log( - Level.WARNING, - "There is no Spanner registered for ConnectionOptions " + options.toString()); - } - } - } - - /** - * Checks that there are no {@link Connection}s that have been created by this {@link SpannerPool} - * that are still open, and then closes all {@link Spanner} instances in the pool. If there is at - * least one unclosed {@link Connection} left in the pool, the method will throw a {@link - * SpannerException} and no {@link Spanner} instances will be closed. - */ - void checkAndCloseSpanners() { - checkAndCloseSpanners(CheckAndCloseSpannersMode.ERROR); - } - - @VisibleForTesting - void checkAndCloseSpanners(CheckAndCloseSpannersMode mode) { - List keysStillInUse = new ArrayList<>(); - synchronized (this) { - for (Entry entry : spanners.entrySet()) { - if (!lastConnectionClosedAt.containsKey(entry.getKey())) { - keysStillInUse.add(entry.getKey()); - } - } - if (keysStillInUse.isEmpty() || mode == CheckAndCloseSpannersMode.WARN) { - if (!keysStillInUse.isEmpty()) { - logLeakedConnections(keysStillInUse); - logger.log( - Level.WARNING, - "There is/are " - + keysStillInUse.size() - + " connection(s) still open." - + " Close all connections before stopping the application"); - } - // Force close all Spanner instances by passing in a value that will always be less than the - // difference between the current time and the close time of a connection. - closeUnusedSpanners(Long.MIN_VALUE); - } else { - logLeakedConnections(keysStillInUse); - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "There is/are " - + keysStillInUse.size() - + " connection(s) still open. Close all connections before calling closeSpanner()"); - } - } - } - - private void logLeakedConnections(List keysStillInUse) { - synchronized (this) { - for (SpannerPoolKey key : keysStillInUse) { - for (ConnectionImpl con : connections.get(key)) { - if (!con.isClosed() && con.getLeakedException() != null) { - logger.log(Level.WARNING, "Leaked connection", con.getLeakedException()); - } - } - } - } - } - - /** - * Closes Spanner objects that are no longer in use by connections, and where the last connection - * that used it was closed more than closeSpannerAfterMillisecondsUnused seconds ago. - * The delay ensures that Spanner objects are not closed unless there's a good reason for it. - * - * @param closeSpannerAfterMillisecondsUnused The number of milliseconds a {@link Spanner} object - * should not have been used for a {@link Connection} before it is closed by this method. - */ - @VisibleForTesting - void closeUnusedSpanners(long closeSpannerAfterMillisecondsUnused) { - List keysToBeRemoved = new ArrayList<>(); - synchronized (this) { - for (Entry entry : lastConnectionClosedAt.entrySet()) { - Long closedAt = entry.getValue(); - // Check whether the last connection was closed more than - // closeSpannerAfterMillisecondsUnused milliseconds ago. - if (closedAt != null - && ((System.currentTimeMillis() - closedAt.longValue())) - > closeSpannerAfterMillisecondsUnused) { - Spanner spanner = spanners.get(entry.getKey()); - if (spanner != null) { - try { - spanner.close(); - } finally { - // Even if the close operation failed, we should remove the spanner object as it is no - // longer valid. - spanners.remove(entry.getKey()); - keysToBeRemoved.add(entry.getKey()); - } - } - } - } - for (SpannerPoolKey key : keysToBeRemoved) { - lastConnectionClosedAt.remove(key); - } - } + com.google.cloud.spanner.connection.SpannerPool.closeSpannerPool(); } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java deleted file mode 100644 index 227bc62961c8..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutionInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019 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.ResultSet; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; - -/** Interface for interceptors that are invoked before a statement is executed. */ -interface StatementExecutionInterceptor { - void intercept(ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction); -} - -/** - * Enum passed in to a {@link StatementExecutionInterceptor} to determine what/why a statement is - * being executed. - */ -enum StatementExecutionStep { - /** The initial execution of a statement (DML/Query). */ - EXECUTE_STATEMENT, - /** A call to {@link ResultSet#next()}. */ - CALL_NEXT_ON_RESULT_SET, - /** Execution of the statement during an internal transaction retry. */ - RETRY_STATEMENT, - /** A call to {@link ResultSet#next()} during internal transaction retry. */ - RETRY_NEXT_ON_RESULT_SET; -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java deleted file mode 100644 index 994c4c44d994..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementExecutor.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2019 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.jdbc.ReadOnlyStalenessUtil.DurationValueGetter; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.protobuf.Duration; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * {@link StatementExecutor} is responsible for executing statements on a {@link Connection}. - * Statements are executed using a separate executor to allow timeouts and cancellation of - * statements. - */ -class StatementExecutor { - - /** Simple holder class for statement timeout that allows us to pass the value by reference. */ - static class StatementTimeout { - /** - * Only {@link TimeUnit#NANOSECONDS}, {@link TimeUnit#MICROSECONDS}, {@link - * TimeUnit#MILLISECONDS} and {@link TimeUnit#SECONDS} may be used to specify a statement - * timeout. - */ - static boolean isValidTimeoutUnit(TimeUnit unit) { - return unit == TimeUnit.NANOSECONDS - || unit == TimeUnit.MICROSECONDS - || unit == TimeUnit.MILLISECONDS - || unit == TimeUnit.SECONDS; - } - - /** The statement timeout. */ - private Duration duration = null; - - /** Creates a {@link StatementTimeout} that will never timeout. */ - @VisibleForTesting - static StatementTimeout nullTimeout() { - return new StatementTimeout(); - } - - /** Creates a {@link StatementTimeout} with the given duration. */ - @VisibleForTesting - static StatementTimeout of(long timeout, TimeUnit unit) { - Preconditions.checkArgument(timeout > 0L); - Preconditions.checkArgument(isValidTimeoutUnit(unit)); - StatementTimeout res = new StatementTimeout(); - res.duration = ReadOnlyStalenessUtil.createDuration(timeout, unit); - return res; - } - - /** - * Does this {@link StatementTimeout} have an actual timeout (i.e. it will eventually timeout). - */ - boolean hasTimeout() { - return duration != null; - } - - void clearTimeoutValue() { - this.duration = null; - } - - void setTimeoutValue(long timeout, TimeUnit unit) { - Preconditions.checkArgument(timeout > 0L); - Preconditions.checkArgument(isValidTimeoutUnit(unit)); - this.duration = ReadOnlyStalenessUtil.createDuration(timeout, unit); - } - - long getTimeoutValue(TimeUnit unit) { - Preconditions.checkArgument(isValidTimeoutUnit(unit)); - return duration == null ? 0L : ReadOnlyStalenessUtil.durationToUnits(duration, unit); - } - - /** - * Returns the {@link TimeUnit} with the least precision that could be used to represent this - * {@link StatementTimeout} without loss of precision. - */ - TimeUnit getAppropriateTimeUnit() { - ConnectionPreconditions.checkState( - duration != null, "This StatementTimeout has no timeout value"); - return ReadOnlyStalenessUtil.getAppropriateTimeUnit( - new DurationValueGetter() { - @Override - public long getDuration(TimeUnit unit) { - return StatementTimeout.this.getTimeoutValue(unit); - } - - @Override - public boolean hasDuration() { - return StatementTimeout.this.hasTimeout(); - } - }); - } - } - - /** - * Use a {@link ThreadFactory} that produces daemon threads and sets recognizable name on the - * threads. - */ - private static final ThreadFactory THREAD_FACTORY = - new ThreadFactoryBuilder() - .setDaemon(true) - .setNameFormat("connection-executor-%d") - .setThreadFactory(MoreExecutors.platformThreadFactory()) - .build(); - - /** Creates an {@link ExecutorService} for a {@link StatementExecutor}. */ - private static ExecutorService createExecutorService() { - return new ThreadPoolExecutor( - 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), THREAD_FACTORY); - } - - private ExecutorService executor = createExecutorService(); - - /** - * Interceptors that should be invoked before or after a statement is executed can be registered - * for a connection. This are added to this list. The interceptors are intended for test usage. - */ - private final List interceptors; - - @VisibleForTesting - StatementExecutor() { - this.interceptors = Collections.emptyList(); - } - - StatementExecutor(List interceptors) { - this.interceptors = Collections.unmodifiableList(interceptors); - } - - /** - * Recreates this {@link StatementExecutor} and its {@link ExecutorService}. This can be necessary - * if a statement times out or is cancelled, and it cannot be guaranteed that the statement - * execution can be terminated. In order to prevent the single threaded {@link ExecutorService} to - * continue to block on the timed out/cancelled statement, a new {@link ExecutorService} is - * created. - */ - void recreate() { - executor.shutdown(); - executor = createExecutorService(); - } - - /** - * Shutdown this executor now and do not wait for any statement that is being executed to finish. - */ - List shutdownNow() { - return executor.shutdownNow(); - } - - /** Execute a statement on this {@link StatementExecutor}. */ - Future submit(Callable callable) { - return executor.submit(callable); - } - - /** - * Invoke the interceptors that have been registered for this {@link StatementExecutor} for the - * given step. - */ - void invokeInterceptors( - ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction) { - for (StatementExecutionInterceptor interceptor : interceptors) { - interceptor.intercept(statement, step, transaction); - } - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java deleted file mode 100644 index e3e998a275f7..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementParser.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; - -/** - * Internal class for the Spanner Connection API. - * - *

    Parses {@link ClientSideStatement}s and normal SQL statements. The parser is able to recognize - * the type of statement, allowing the connection API to know which method on Spanner should be - * called. The parser does not validate the validity of statements, except for {@link - * ClientSideStatement}s. This means that an invalid DML statement could be accepted by the {@link - * StatementParser} and sent to Spanner, and Spanner will then reject it with some error message. - */ -class StatementParser { - /** Singleton instance of {@link StatementParser}. */ - public static final StatementParser INSTANCE = new StatementParser(); - - /** The type of statement that has been recognized by the parser. */ - enum StatementType { - CLIENT_SIDE, - DDL, - QUERY, - UPDATE, - UNKNOWN; - } - - /** A statement that has been parsed */ - static class ParsedStatement { - private final StatementType type; - private final ClientSideStatementImpl clientSideStatement; - private final Statement statement; - private final String sqlWithoutComments; - - private static ParsedStatement clientSideStatement( - ClientSideStatementImpl clientSideStatement, - Statement statement, - String sqlWithoutComments) { - return new ParsedStatement(clientSideStatement, statement, sqlWithoutComments); - } - - private static ParsedStatement ddl(Statement statement, String sqlWithoutComments) { - return new ParsedStatement(StatementType.DDL, statement, sqlWithoutComments); - } - - private static ParsedStatement query( - Statement statement, String sqlWithoutComments, QueryOptions defaultQueryOptions) { - return new ParsedStatement( - StatementType.QUERY, statement, sqlWithoutComments, defaultQueryOptions); - } - - private static ParsedStatement update(Statement statement, String sqlWithoutComments) { - return new ParsedStatement(StatementType.UPDATE, statement, sqlWithoutComments); - } - - private static ParsedStatement unknown(Statement statement, String sqlWithoutComments) { - return new ParsedStatement(StatementType.UNKNOWN, statement, sqlWithoutComments); - } - - private ParsedStatement( - ClientSideStatementImpl clientSideStatement, - Statement statement, - String sqlWithoutComments) { - Preconditions.checkNotNull(clientSideStatement); - Preconditions.checkNotNull(statement); - this.type = StatementType.CLIENT_SIDE; - this.clientSideStatement = clientSideStatement; - this.statement = statement; - this.sqlWithoutComments = sqlWithoutComments; - } - - private ParsedStatement(StatementType type, Statement statement, String sqlWithoutComments) { - this(type, statement, sqlWithoutComments, null); - } - - private ParsedStatement( - StatementType type, - Statement statement, - String sqlWithoutComments, - QueryOptions defaultQueryOptions) { - Preconditions.checkNotNull(type); - Preconditions.checkNotNull(statement); - this.type = type; - this.clientSideStatement = null; - this.statement = mergeQueryOptions(statement, defaultQueryOptions); - this.sqlWithoutComments = sqlWithoutComments; - } - - @Override - public int hashCode() { - return Objects.hash( - this.type, this.clientSideStatement, this.statement, this.sqlWithoutComments); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof ParsedStatement)) { - return false; - } - ParsedStatement o = (ParsedStatement) other; - return Objects.equals(this.type, o.type) - && Objects.equals(this.clientSideStatement, o.clientSideStatement) - && Objects.equals(this.statement, o.statement) - && Objects.equals(this.sqlWithoutComments, o.sqlWithoutComments); - } - - StatementType getType() { - return type; - } - - boolean isQuery() { - switch (type) { - case CLIENT_SIDE: - return getClientSideStatement().isQuery(); - case QUERY: - return true; - case UPDATE: - case DDL: - case UNKNOWN: - default: - } - return false; - } - - boolean isUpdate() { - switch (type) { - case CLIENT_SIDE: - return getClientSideStatement().isUpdate(); - case UPDATE: - return true; - case QUERY: - case DDL: - case UNKNOWN: - default: - } - return false; - } - - boolean isDdl() { - switch (type) { - case DDL: - return true; - case CLIENT_SIDE: - case UPDATE: - case QUERY: - case UNKNOWN: - default: - } - return false; - } - - Statement getStatement() { - return statement; - } - - /** - * Merges the {@link QueryOptions} of the {@link Statement} with the current {@link - * QueryOptions} of this connection. The {@link QueryOptions} that are already present on the - * statement take precedence above the connection {@link QueryOptions}. - */ - Statement mergeQueryOptions(Statement statement, QueryOptions defaultQueryOptions) { - if (defaultQueryOptions == null - || defaultQueryOptions.equals(QueryOptions.getDefaultInstance())) { - return statement; - } - if (statement.getQueryOptions() == null) { - return statement.toBuilder().withQueryOptions(defaultQueryOptions).build(); - } - return statement - .toBuilder() - .withQueryOptions( - defaultQueryOptions.toBuilder().mergeFrom(statement.getQueryOptions()).build()) - .build(); - } - - String getSqlWithoutComments() { - return sqlWithoutComments; - } - - ClientSideStatement getClientSideStatement() { - Preconditions.checkState( - clientSideStatement != null, - "This ParsedStatement does not contain a ClientSideStatement"); - return clientSideStatement; - } - } - - private final Set ddlStatements = ImmutableSet.of("CREATE", "DROP", "ALTER"); - private final Set selectStatements = ImmutableSet.of("SELECT", "WITH"); - private final Set dmlStatements = ImmutableSet.of("INSERT", "UPDATE", "DELETE"); - private final Set statements; - - /** Private constructor for singleton instance. */ - private StatementParser() { - try { - statements = - Collections.unmodifiableSet(ClientSideStatements.INSTANCE.getCompiledStatements()); - } catch (CompileException e) { - throw new RuntimeException(e); - } - } - - /** - * Parses the given statement and categorizes it as one of the possible {@link StatementType}s. - * The validity of the statement is not checked, unless it is a client-side statement. - * - * @param statement The statement to parse. - * @return the parsed and categorized statement. - */ - ParsedStatement parse(Statement statement) { - return parse(statement, null); - } - - ParsedStatement parse(Statement statement, QueryOptions defaultQueryOptions) { - String sql = removeCommentsAndTrim(statement.getSql()); - ClientSideStatementImpl client = parseClientSideStatement(sql); - if (client != null) { - return ParsedStatement.clientSideStatement(client, statement, sql); - } else if (isQuery(sql)) { - return ParsedStatement.query(statement, sql, defaultQueryOptions); - } else if (isUpdateStatement(sql)) { - return ParsedStatement.update(statement, sql); - } else if (isDdlStatement(sql)) { - return ParsedStatement.ddl(statement, sql); - } - return ParsedStatement.unknown(statement, sql); - } - - /** - * Parses the given statement as a client-side statement. Client-side statements are statements - * that are never sent to Cloud Spanner, but that are interpreted by the Connection API and then - * translated into some action, such as for example starting a transaction or getting the last - * commit timestamp. - * - * @param sql The statement to try to parse as a client-side statement (without any comments). - * @return a valid {@link ClientSideStatement} or null if the statement is not a client-side - * statement. - */ - @VisibleForTesting - ClientSideStatementImpl parseClientSideStatement(String sql) { - for (ClientSideStatementImpl css : statements) { - if (css.matches(sql)) { - return css; - } - } - return null; - } - - /** - * Checks whether the given statement is (probably) a DDL statement. The method does not check the - * validity of the statement, only if it is a DDL statement based on the first word in the - * statement. - * - * @param sql The statement to check (without any comments). - * @return true if the statement is a DDL statement (i.e. starts with 'CREATE', - * 'ALTER' or 'DROP'). - */ - boolean isDdlStatement(String sql) { - return statementStartsWith(sql, ddlStatements); - } - - /** - * Checks whether the given statement is (probably) a SELECT query. The method does not check the - * validity of the statement, only if it is a SELECT statement based on the first word in the - * statement. - * - * @param sql The statement to check (without any comments). - * @return true if the statement is a SELECT statement (i.e. starts with 'SELECT'). - */ - boolean isQuery(String sql) { - // Skip any query hints at the beginning of the query. - if (sql.startsWith("@")) { - sql = removeStatementHint(sql); - } - return statementStartsWith(sql, selectStatements); - } - - /** - * Checks whether the given statement is (probably) an update statement. The method does not check - * the validity of the statement, only if it is an update statement based on the first word in the - * statement. - * - * @param sql The statement to check (without any comments). - * @return true if the statement is a DML update statement (i.e. starts with - * 'INSERT', 'UPDATE' or 'DELETE'). - */ - boolean isUpdateStatement(String sql) { - return statementStartsWith(sql, dmlStatements); - } - - private boolean statementStartsWith(String sql, Iterable checkStatements) { - Preconditions.checkNotNull(sql); - String[] tokens = sql.split("\\s+", 2); - if (tokens.length > 0) { - for (String check : checkStatements) { - if (tokens[0].equalsIgnoreCase(check)) { - return true; - } - } - } - return false; - } - - /** - * Removes comments from and trims the given sql statement. Spanner supports three types of - * comments: - * - *

      - *
    • Single line comments starting with '--' - *
    • Single line comments starting with '#' - *
    • Multi line comments between '/*' and '*/' - *
    - * - * Reference: https://cloud.google.com/spanner/docs/lexical#comments - * - * @param sql The sql statement to remove comments from and to trim. - * @return the sql statement without the comments and leading and trailing spaces. - */ - static String removeCommentsAndTrim(String sql) { - Preconditions.checkNotNull(sql); - final char SINGLE_QUOTE = '\''; - final char DOUBLE_QUOTE = '"'; - final char BACKTICK_QUOTE = '`'; - final char HYPHEN = '-'; - final char DASH = '#'; - final char SLASH = '/'; - final char ASTERIKS = '*'; - boolean isInQuoted = false; - boolean isInSingleLineComment = false; - boolean isInMultiLineComment = false; - char startQuote = 0; - boolean lastCharWasEscapeChar = false; - boolean isTripleQuoted = false; - StringBuilder res = new StringBuilder(sql.length()); - int index = 0; - while (index < sql.length()) { - char c = sql.charAt(index); - if (isInQuoted) { - if ((c == '\n' || c == '\r') && !isTripleQuoted) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); - } else if (c == startQuote) { - if (lastCharWasEscapeChar) { - lastCharWasEscapeChar = false; - } else if (isTripleQuoted) { - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isInQuoted = false; - startQuote = 0; - isTripleQuoted = false; - res.append(c).append(c); - index += 2; - } - } else { - isInQuoted = false; - startQuote = 0; - } - } else if (c == '\\') { - lastCharWasEscapeChar = true; - } else { - lastCharWasEscapeChar = false; - } - res.append(c); - } else { - // We are not in a quoted string. - if (isInSingleLineComment) { - if (c == '\n') { - isInSingleLineComment = false; - // Include the line feed in the result. - res.append(c); - } - } else if (isInMultiLineComment) { - if (sql.length() > index + 1 && c == ASTERIKS && sql.charAt(index + 1) == SLASH) { - isInMultiLineComment = false; - index++; - } - } else { - if (c == DASH - || (sql.length() > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN)) { - // This is a single line comment. - isInSingleLineComment = true; - } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERIKS) { - isInMultiLineComment = true; - index++; - } else { - if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { - isInQuoted = true; - startQuote = c; - // Check whether it is a triple-quote. - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isTripleQuoted = true; - res.append(c).append(c); - index += 2; - } - } - res.append(c); - } - } - } - index++; - } - if (isInQuoted) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); - } - if (res.length() > 0 && res.charAt(res.length() - 1) == ';') { - res.deleteCharAt(res.length() - 1); - } - return res.toString().trim(); - } - - /** Removes any statement hints at the beginning of the statement. */ - static String removeStatementHint(String sql) { - // Valid statement hints at the beginning of a SQL statement can only contain a fixed set of - // possible values. Although it is possible to add a @{FORCE_INDEX=...} as a statement hint, the - // only allowed value is _BASE_TABLE. This means that we can safely assume that the statement - // hint will not contain any special characters, for example a closing curly brace, and - // that we can keep the check simple by just searching for the first occurrence of a closing - // curly brace at the end of the statement hint. - int startStatementHintIndex = sql.indexOf('{'); - int endStatementHintIndex = sql.indexOf('}'); - if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex) { - // Looks like an invalid statement hint. Just ignore at this point and let the caller handle - // the invalid query. - return sql; - } - return removeCommentsAndTrim(sql.substring(endStatementHintIndex + 1)); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java deleted file mode 100644 index 9820716a441f..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResult.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2019 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.ResultSet; - -/** - * A result of the execution of a statement. Statements that are executed by the {@link - * Connection#execute(com.google.cloud.spanner.Statement)} method could have different types of - * return values. These are wrapped in a {@link StatementResult}. - */ -interface StatementResult { - - /** - * Enum indicating the type of result that was returned by {@link - * Connection#execute(com.google.cloud.spanner.Statement)} - */ - enum ResultType { - /** - * A result set either returned by a query on Cloud Spanner or a local result set generated by a - * client side statement. - */ - RESULT_SET, - /** An update count returned by Cloud Spanner. */ - UPDATE_COUNT, - /** - * DDL statements and client side statements that set the state of a connection return no - * result. - */ - NO_RESULT; - } - - /** The type of client side statement that was executed. */ - enum ClientSideStatementType { - SHOW_AUTOCOMMIT, - SET_AUTOCOMMIT, - SHOW_READONLY, - SET_READONLY, - SHOW_RETRY_ABORTS_INTERNALLY, - SET_RETRY_ABORTS_INTERNALLY, - SHOW_AUTOCOMMIT_DML_MODE, - SET_AUTOCOMMIT_DML_MODE, - SHOW_STATEMENT_TIMEOUT, - SET_STATEMENT_TIMEOUT, - SHOW_READ_TIMESTAMP, - SHOW_COMMIT_TIMESTAMP, - SHOW_READ_ONLY_STALENESS, - SET_READ_ONLY_STALENESS, - SHOW_OPTIMIZER_VERSION, - SET_OPTIMIZER_VERSION, - BEGIN, - COMMIT, - ROLLBACK, - SET_TRANSACTION_MODE, - START_BATCH_DDL, - START_BATCH_DML, - RUN_BATCH, - ABORT_BATCH; - } - - /** - * Returns the {@link ResultType} of this result. - * - * @return the result type. - */ - ResultType getResultType(); - - /** - * @return the {@link ClientSideStatementType} that was executed, or null if no such statement was - * executed. - */ - ClientSideStatementType getClientSideStatementType(); - - /** - * Returns the {@link ResultSet} held by this result. May only be called if the type of this - * result is {@link ResultType#RESULT_SET}. - * - * @return the {@link ResultSet} held by this result. - */ - ResultSet getResultSet(); - - /** - * Returns the update count held by this result. May only be called if the type of this result is - * {@link ResultType#UPDATE_COUNT}. - * - * @return the update count held by this result. - */ - Long getUpdateCount(); -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java deleted file mode 100644 index 6748311e5582..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/StatementResultImpl.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2019 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.Timestamp; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.ResultSets; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.Type.StructField; -import java.util.Arrays; - -/** Implementation of {@link StatementResult} */ -class StatementResultImpl implements StatementResult { - - /** {@link StatementResult} containing a {@link ResultSet} returned by Cloud Spanner. */ - static StatementResult of(ResultSet resultSet) { - return new StatementResultImpl(resultSet, null); - } - - /** - * {@link StatementResult} containing a {@link ResultSet} created by a {@link - * ClientSideStatement}. - */ - static StatementResult of(ResultSet resultSet, ClientSideStatementType clientSideStatementType) { - return new StatementResultImpl(resultSet, clientSideStatementType); - } - - /** {@link StatementResult} containing an update count returned by Cloud Spanner. */ - static StatementResult of(Long updateCount) { - return new StatementResultImpl(updateCount); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one BOOL column and one row that is created by a {@link ClientSideStatement}. - */ - static StatementResult resultSet( - String name, Boolean value, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.bool())), - Arrays.asList(Struct.newBuilder().set(name).to(value).build())), - clientSideStatementType); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one INT64 column and one row that is created by a {@link ClientSideStatement}. - */ - static StatementResult resultSet( - String name, Long value, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.int64())), - Arrays.asList(Struct.newBuilder().set(name).to(value).build())), - clientSideStatementType); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one ARRAY column and one row that is created by a {@link ClientSideStatement}. - */ - static StatementResult resultSet( - String name, long[] values, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.array(Type.int64()))), - Arrays.asList(Struct.newBuilder().set(name).toInt64Array(values).build())), - clientSideStatementType); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one STRING column and one row that is created by a {@link ClientSideStatement}. - */ - static StatementResult resultSet( - String name, String value, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.string())), - Arrays.asList(Struct.newBuilder().set(name).to(value).build())), - clientSideStatementType); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one STRING column containing an {@link Enum} value and one row that is created by a {@link - * ClientSideStatement}. - */ - static StatementResult resultSet( - String name, Enum value, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.string())), - Arrays.asList(Struct.newBuilder().set(name).to(value.toString()).build())), - clientSideStatementType); - } - - /** - * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with - * one TIMESTAMP column and one row that is created by a {@link ClientSideStatement}. - */ - static StatementResult resultSet( - String name, Timestamp value, ClientSideStatementType clientSideStatementType) { - return of( - ResultSets.forRows( - Type.struct(StructField.of(name, Type.timestamp())), - Arrays.asList(Struct.newBuilder().set(name).to(value).build())), - clientSideStatementType); - } - - /** {@link StatementResult} containing no results. */ - static StatementResult noResult() { - return new StatementResultImpl((ClientSideStatementType) null); - } - - /** {@link StatementResult} containing no results created by a {@link ClientSideStatement}. */ - static StatementResult noResult(ClientSideStatementType clientSideStatementType) { - return new StatementResultImpl(clientSideStatementType); - } - - private final ResultType type; - private final ClientSideStatementType clientSideStatementType; - private final ResultSet resultSet; - private final Long updateCount; - - private StatementResultImpl( - ResultSet resultSet, ClientSideStatementType clientSideStatementType) { - this.type = ResultType.RESULT_SET; - this.clientSideStatementType = clientSideStatementType; - this.resultSet = resultSet; - this.updateCount = null; - } - - private StatementResultImpl(Long updateCount) { - this.type = ResultType.UPDATE_COUNT; - this.clientSideStatementType = null; - this.resultSet = null; - this.updateCount = updateCount; - } - - private StatementResultImpl(ClientSideStatementType clientSideStatementType) { - this.type = ResultType.NO_RESULT; - this.clientSideStatementType = clientSideStatementType; - this.resultSet = null; - this.updateCount = null; - } - - @Override - public ResultType getResultType() { - return type; - } - - @Override - public ClientSideStatementType getClientSideStatementType() { - return clientSideStatementType; - } - - @Override - public ResultSet getResultSet() { - ConnectionPreconditions.checkState( - resultSet != null, "This result does not contain a ResultSet"); - return resultSet; - } - - @Override - public Long getUpdateCount() { - ConnectionPreconditions.checkState( - updateCount != null, "This result does not contain an update count"); - return updateCount; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java deleted file mode 100644 index ae98118c1391..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionMode.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 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; - -/** Enum used to define the transaction type of a {@link Connection} */ -enum TransactionMode { - READ_ONLY_TRANSACTION("READ ONLY"), - READ_WRITE_TRANSACTION("READ WRITE"); - - private final String statementString; - - private TransactionMode(String statement) { - this.statementString = statement; - } - - /** - * Use this method to get the correct format for use in a SQL statement. The SQL statement for - * setting the mode to read-only should for example be without the underscore: - * SET TRANSACTION READ ONLY - * - * @return a string representation of this {@link TransactionMode} that can be used in a SQL - * statement to set the transaction mode. - */ - public String getStatementString() { - return statementString; - } - - @Override - public String toString() { - return statementString; - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java index 546cd4f27d9c..6d85dc7c0c8f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java @@ -16,24 +16,18 @@ package com.google.cloud.spanner.jdbc; +import com.google.api.core.InternalApi; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; import com.google.cloud.spanner.AbortedException; -/** - * Cloud Spanner can abort any read/write transaction because of potential deadlocks or other - * internal reasons. When a transaction is aborted, the entire transaction should be retried. A - * {@link Connection} can automatically retry a transaction internally and check whether the results - * that are returned during a retry attempt are equal to the results during the original - * transaction. This is done by keeping track of a SHA-256 checksum of all the results that are - * returned by Spanner during both transactions. - * - *

    This listener class for internal transaction retries allow client applications to do - * additional testing or logging of transaction retries. Transaction retry listeners of a {@link - * Connection} can be added using {@link - * Connection#addTransactionRetryListener(TransactionRetryListener)}. - */ +/** Use {@link com.google.cloud.spanner.connection.TransactionRetryListener} */ +@InternalApi +@Deprecated public interface TransactionRetryListener { - /** The result of a retry. */ + /** Use {@link com.google.cloud.spanner.connection.TransactionRetryListener.RetryResult} */ + @InternalApi + @Deprecated public enum RetryResult { /** The retry executed successfully and the transaction will continue. */ RETRY_SUCCESSFUL, diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java deleted file mode 100644 index 4287981dfce5..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UnitOfWork.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2019 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.api.core.InternalApi; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadContext; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.spanner.v1.ResultSetStats; - -/** Internal interface for transactions and batches on {@link Connection}s. */ -@InternalApi -interface UnitOfWork { - - /** A unit of work can be either a transaction or a DDL/DML batch. */ - enum Type { - TRANSACTION, - BATCH; - } - - enum UnitOfWorkState { - STARTED, - COMMITTED, - COMMIT_FAILED, - ROLLED_BACK, - RAN, - RUN_FAILED, - ABORTED; - - public boolean isActive() { - return this == STARTED; - } - } - - /** Cancel the currently running statement (if any and the statement may be cancelled). */ - void cancel(); - - /** @return the type of unit of work. */ - Type getType(); - - /** @return the current state of this unit of work. */ - UnitOfWorkState getState(); - - /** @return true if this unit of work is still active. */ - boolean isActive(); - - /** - * Commits the changes in this unit of work to the database. For read-only transactions, this only - * closes the {@link ReadContext}. This method will throw a {@link SpannerException} if called for - * a {@link Type#BATCH}. - */ - void commit(); - - /** - * Rollbacks any changes in this unit of work. For read-only transactions, this only closes the - * {@link ReadContext}. This method will throw a {@link SpannerException} if called for a {@link - * Type#BATCH}. - */ - void rollback(); - - /** - * Sends the currently buffered statements in this unit of work to the database and ends the - * batch. This method will throw a {@link SpannerException} if called for a {@link - * Type#TRANSACTION}. - * - * @return the update counts in case of a DML batch. Returns an array containing 1 for each - * successful statement and 0 for each failed statement or statement that was not executed DDL - * in case of a DDL batch. - */ - long[] runBatch(); - - /** - * Clears the currently buffered statements in this unit of work and ends the batch. This method - * will throw a {@link SpannerException} if called for a {@link Type#TRANSACTION}. - */ - void abortBatch(); - - /** @return true if this unit of work is read-only. */ - boolean isReadOnly(); - - /** - * Executes a query with the given options. If {@link AnalyzeMode} is set to {@link - * AnalyzeMode#PLAN} or {@link AnalyzeMode#PROFILE}, the returned {@link ResultSet} will include - * {@link ResultSetStats}. - * - * @param statement The statement to execute. - * @param analyzeMode Indicates whether to include {@link ResultSetStats} in the returned {@link - * ResultSet} or not. Cannot be used in combination with {@link QueryOption}s. - * @param options the options to configure the query. May only be set if analyzeMode is set to - * {@link AnalyzeMode#NONE}. - * @return a {@link ResultSet} with the results of the query. - * @throws SpannerException if the query is not allowed on this {@link UnitOfWork}, or if a - * database error occurs. - */ - ResultSet executeQuery( - ParsedStatement statement, AnalyzeMode analyzeMode, QueryOption... options); - - /** - * @return the read timestamp of this transaction. Will throw a {@link SpannerException} if there - * is no read timestamp. - */ - Timestamp getReadTimestamp(); - - /** @return the read timestamp of this transaction or null if there is no read timestamp. */ - Timestamp getReadTimestampOrNull(); - - /** - * @return the commit timestamp of this transaction. Will throw a {@link SpannerException} if - * there is no commit timestamp. - */ - Timestamp getCommitTimestamp(); - - /** @return the commit timestamp of this transaction or null if there is no commit timestamp. */ - Timestamp getCommitTimestampOrNull(); - - /** - * Executes the specified DDL statements in this unit of work. For DDL batches, this will mean - * that the statements are buffered locally and will be sent to Spanner when {@link - * UnitOfWork#commit()} is called. For {@link SingleUseTransaction}s, this will execute the DDL - * statement directly on Spanner. - * - * @param ddl The DDL statement to execute. - */ - void executeDdl(ParsedStatement ddl); - - /** - * Execute a DML statement on Spanner. - * - * @param update The DML statement to execute. - * @return the number of records that were inserted/updated/deleted by this statement. - */ - long executeUpdate(ParsedStatement update); - - /** - * Execute a batch of DML statements on Spanner. - * - * @param updates The DML statements to execute. - * @return an array containing the number of records that were inserted/updated/deleted per - * statement. - * @see TransactionContext#batchUpdate(Iterable) - */ - long[] executeBatchUpdate(Iterable updates); - - /** - * Writes a {@link Mutation} to Spanner. For {@link ReadWriteTransaction}s, this means buffering - * the {@link Mutation} locally and writing the {@link Mutation} to Spanner upon {@link - * UnitOfWork#commit()}. For {@link SingleUseTransaction}s, the {@link Mutation} will be sent - * directly to Spanner. - * - * @param mutation The mutation to write. - */ - void write(Mutation mutation); - - /** - * Writes a batch of {@link Mutation}s to Spanner. For {@link ReadWriteTransaction}s, this means - * buffering the {@link Mutation}s locally and writing the {@link Mutation}s to Spanner upon - * {@link UnitOfWork#commit()}. For {@link SingleUseTransaction}s, the {@link Mutation}s will be - * sent directly to Spanner. - * - * @param mutations The mutations to write. - */ - void write(Iterable mutations); -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java deleted file mode 100644 index d10508bba6eb..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbortedTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.AbortInterceptor; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.ITConnection; -import com.google.cloud.spanner.jdbc.it.ITTransactionRetryTest.CountTransactionRetryListener; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class AbortedTest extends AbstractMockServerTest { - - @Test - public void testCommitAborted() { - // Do two iterations to ensure that each iteration gets its own transaction, and that each - // transaction is the most recent transaction of that session. - for (int i = 0; i < 2; i++) { - mockSpanner.putStatementResult( - StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); - mockSpanner.putStatementResult(StatementResult.update(INSERT_STATEMENT, UPDATE_COUNT)); - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // do an insert - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // do a commit that will first abort, and then on retry will succeed - connection.commit(); - mockSpanner.putStatementResult( - StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_AFTER_INSERT)); - // verify that the insert succeeded - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java deleted file mode 100644 index f12f5e889d32..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractConnectionImplTest.java +++ /dev/null @@ -1,963 +0,0 @@ -/* - * Copyright 2019 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 com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.getTimeUnitAbbreviation; -import static com.google.cloud.spanner.jdbc.SpannerExceptionMatcher.matchCode; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This test class and all its subclasses are used to generate the file - * ConnectionImplGeneratedSqlScriptTest.sql. - */ -@RunWith(JUnit4.class) -public abstract class AbstractConnectionImplTest { - public static final String UPDATE = "UPDATE foo SET bar=1"; - public static final String SELECT = "SELECT 1 AS TEST"; - public static final String DDL = - "CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id)"; - - static interface ConnectionConsumer { - void accept(Connection connection); - } - - @Rule public ExpectedException exception = ExpectedException.none(); - - /** - * This test class can generate a large sql file that represents all the statements and - * verifications that are executed by this test class. This file can be fed into other test cases - * (in other programming languages) to execute the same tests as the tests covered by all the - * subclasses of {@link AbstractConnectionImplTest}. - */ - private static final String LOG_FILE = - "src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql"; - - private static final String DO_LOG_PROPERTY = "do_log_statements"; - private static boolean doLog; - private static PrintWriter writer; - - abstract Connection getConnection(); - - static void expectSpannerException( - String reason, ConnectionConsumer consumer, Connection connection) { - expectSpannerException(reason, consumer, connection, ErrorCode.FAILED_PRECONDITION); - } - - static void expectSpannerException( - String reason, ConnectionConsumer consumer, Connection connection, ErrorCode errorCode) { - SpannerException exception = null; - try { - consumer.accept(connection); - } catch (SpannerException e) { - exception = e; - } - assertThat(reason, exception, is(notNullValue())); - assertThat(reason, exception.getErrorCode(), is(equalTo(errorCode))); - } - - AbstractConnectionImplTest() {} - - /** Makes an empty test script. Can be called before a new script is to be generated. */ - static void emptyScript() { - openLog(false); - closeLog(); - } - - void log(String statement) { - if (doLog) { - writer.println(statement); - } - } - - @BeforeClass - public static void openLog() { - doLog = Boolean.valueOf(System.getProperty(DO_LOG_PROPERTY, "false")); - if (doLog) { - openLog(true); - } else { - writer = null; - } - } - - private static void openLog(boolean append) { - try { - writer = - new PrintWriter( - new OutputStreamWriter(new FileOutputStream(LOG_FILE, append), "UTF8"), true); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @AfterClass - public static void closeLog() { - if (writer != null) { - writer.close(); - } - } - - @Test - public void testClose() { - getConnection().close(); - } - - @Test - public void testIsClosed() { - Connection connection = getConnection(); - assertThat(connection.isClosed(), is(false)); - connection.close(); - assertThat(connection.isClosed(), is(true)); - } - - abstract boolean isSetAutocommitAllowed(); - - @Test - public void testSetAutocommit() { - try (Connection connection = getConnection()) { - if (isSetAutocommitAllowed()) { - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - - log("@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE"); - log("SHOW VARIABLE AUTOCOMMIT;"); - assertThat(connection.isAutocommit(), is(false)); - - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - - log("@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE"); - log("SHOW VARIABLE AUTOCOMMIT;"); - assertThat(connection.isAutocommit(), is(true)); - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SET AUTOCOMMIT=" + (connection.isAutocommit() ? "FALSE;" : "TRUE;")); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.setAutocommit(!connection.isAutocommit()); - } - } - } - - abstract boolean isSetReadOnlyAllowed(); - - @Test - public void testSetReadOnly() { - try (Connection connection = getConnection()) { - if (isSetReadOnlyAllowed()) { - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - - log("@EXPECT RESULT_SET 'READONLY',FALSE"); - log("SHOW VARIABLE READONLY;"); - assertThat(connection.isReadOnly(), is(false)); - - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - - log("@EXPECT RESULT_SET 'READONLY',TRUE"); - log("SHOW VARIABLE READONLY;"); - assertThat(connection.isReadOnly(), is(true)); - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SET READONLY=" + (connection.isAutocommit() ? "FALSE;" : "TRUE;")); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.setReadOnly(!connection.isReadOnly()); - } - } - } - - @Test - public void testSetStatementTimeout() { - try (Connection connection = getConnection()) { - for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { - log(String.format("SET STATEMENT_TIMEOUT='1%s';", getTimeUnitAbbreviation(unit))); - connection.setStatementTimeout(1L, unit); - - log( - String.format( - "@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1%s'", getTimeUnitAbbreviation(unit))); - log("SHOW VARIABLE STATEMENT_TIMEOUT;"); - assertThat(connection.getStatementTimeout(unit), is(equalTo(1L))); - - log("SET STATEMENT_TIMEOUT=null;"); - connection.clearStatementTimeout(); - - log("@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null"); - log("SHOW VARIABLE STATEMENT_TIMEOUT;"); - assertThat(connection.getStatementTimeout(unit), is(equalTo(0L))); - assertThat(connection.hasStatementTimeout(), is(false)); - boolean gotException = false; - try { - log("@EXPECT EXCEPTION INVALID_ARGUMENT"); - log(String.format("SET STATEMENT_TIMEOUT='0%s';", getTimeUnitAbbreviation(unit))); - connection.setStatementTimeout(0L, unit); - } catch (IllegalArgumentException e) { - gotException = true; - } - assertThat(gotException, is(true)); - log("@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null"); - log("SHOW VARIABLE STATEMENT_TIMEOUT;"); - assertThat(connection.getStatementTimeout(unit), is(equalTo(0L))); - assertThat(connection.hasStatementTimeout(), is(false)); - } - } - } - - abstract boolean isStartBatchDmlAllowed(); - - @Test - public void testStartBatchDml() { - try (Connection connection = getConnection()) { - if (isStartBatchDmlAllowed()) { - assertThat(connection.isReadOnly(), is(false)); - assertThat(connection.isDdlBatchActive() || connection.isDmlBatchActive(), is(false)); - - log("START BATCH DML;"); - connection.startBatchDml(); - assertThat(connection.isDmlBatchActive(), is(true)); - - expectSpannerException( - "Select should not be allowed after startBatchDml()", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(SELECT + ";"); - t.execute(Statement.of(SELECT)); - } - }, - connection); - expectSpannerException( - "DDL should not be allowed after startBatchDml()", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(DDL + ";"); - t.execute(Statement.of(DDL)); - } - }, - connection); - log(UPDATE + ";"); - connection.execute(Statement.of(UPDATE)); - assertThat(connection.isDmlBatchActive(), is(true)); - } - // startBatchDml is not allowed as a batch has already been started. - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("START BATCH DML;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.startBatchDml(); - } - } - - abstract boolean isStartBatchDdlAllowed(); - - @Test - public void testStartBatchDdl() { - try (Connection connection = getConnection()) { - if (isStartBatchDdlAllowed()) { - assertThat(connection.isTransactionStarted(), is(false)); - assertThat(connection.isInTransaction(), is(equalTo(!connection.isAutocommit()))); - assertThat(connection.isDdlBatchActive() || connection.isDmlBatchActive(), is(false)); - - log("START BATCH DDL;"); - connection.startBatchDdl(); - assertThat(connection.isTransactionStarted(), is(false)); - assertThat(connection.isInTransaction(), is(false)); - assertThat(connection.isDdlBatchActive(), is(true)); - - expectSpannerException( - "Select should not be allowed after startBatchDdl()", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(SELECT + ";"); - t.execute(Statement.of(SELECT)); - } - }, - connection); - expectSpannerException( - "Update should not be allowed after startBatchDdl()", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(UPDATE + ";"); - t.execute(Statement.of(UPDATE)); - } - }, - connection); - log(DDL + ";"); - connection.execute(Statement.of(DDL)); - assertThat(connection.isTransactionStarted(), is(false)); - assertThat(connection.isDdlBatchActive(), is(true)); - } - // startBatchDdl is no longer allowed as a batch has already been started - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("START BATCH DDL;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.startBatchDdl(); - } - } - - abstract boolean isRunBatchAllowed(); - - @Test - public void testRunBatch() { - try (Connection connection = getConnection()) { - if (!isRunBatchAllowed()) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - log("RUN BATCH;"); - connection.runBatch(); - } - } - - abstract boolean isAbortBatchAllowed(); - - @Test - public void testAbortBatch() { - try (Connection connection = getConnection()) { - if (!isAbortBatchAllowed()) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - log("ABORT BATCH;"); - connection.abortBatch(); - } - } - - abstract boolean isBeginTransactionAllowed(); - - abstract boolean isSelectAllowedAfterBeginTransaction(); - - abstract boolean isDmlAllowedAfterBeginTransaction(); - - abstract boolean isDdlAllowedAfterBeginTransaction(); - - @Test - public void testBeginTransaction() { - try (Connection connection = getConnection()) { - if (isBeginTransactionAllowed()) { - assertThat(connection.isTransactionStarted(), is(false)); - assertThat(connection.isInTransaction(), is(equalTo(!connection.isAutocommit()))); - - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - assertThat(connection.isTransactionStarted(), is(false)); - assertThat(connection.isInTransaction(), is(true)); - - if (isSelectAllowedAfterBeginTransaction()) { - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)); - } else { - expectSpannerException( - "Select should not be allowed after beginTransaction", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(SELECT + ";"); - t.execute(Statement.of(SELECT)); - } - }, - connection); - } - if (isDmlAllowedAfterBeginTransaction()) { - log(UPDATE + ";"); - connection.execute(Statement.of(UPDATE)); - } else { - expectSpannerException( - "Update should not be allowed after beginTransaction", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(UPDATE + ";"); - t.execute(Statement.of(UPDATE)); - } - }, - connection); - } - if (isDdlAllowedAfterBeginTransaction()) { - log(DDL + ";"); - connection.execute(Statement.of(DDL)); - } else { - expectSpannerException( - "DDL should not be allowed after beginTransaction", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(DDL + ";"); - t.execute(Statement.of(DDL)); - } - }, - connection); - } - assertThat(connection.isTransactionStarted(), is(true)); - } - // beginTransaction is no longer allowed as the transaction has already started - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("BEGIN TRANSACTION;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.beginTransaction(); - } - } - - abstract boolean isSetTransactionModeAllowed(TransactionMode mode); - - @Test - public void testSetTransactionMode() { - for (TransactionMode mode : TransactionMode.values()) { - testSetTransactionMode(mode); - } - } - - private void testSetTransactionMode(final TransactionMode mode) { - try (Connection connection = getConnection()) { - if (isSetTransactionModeAllowed(mode)) { - log("SET TRANSACTION " + mode.toString() + ";"); - connection.setTransactionMode(mode); - assertThat(connection.getTransactionMode(), is(equalTo(mode))); - } else { - expectSpannerException( - mode + " should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SET TRANSACTION " + mode.getStatementString() + ";"); - t.setTransactionMode(mode); - } - }, - connection); - } - } - } - - abstract boolean isGetTransactionModeAllowed(); - - @Test - public void testGetTransactionMode() { - try (Connection connection = getConnection()) { - if (isGetTransactionModeAllowed()) { - assertThat(connection.getTransactionMode(), is(notNullValue())); - } else { - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getTransactionMode(); - } - } - } - - abstract boolean isSetAutocommitDmlModeAllowed(); - - @Test - public void testSetAutocommitDmlMode() { - try (Connection connection = getConnection()) { - if (isSetAutocommitDmlModeAllowed()) { - for (AutocommitDmlMode mode : AutocommitDmlMode.values()) { - log("SET AUTOCOMMIT_DML_MODE='" + mode.toString() + "';"); - connection.setAutocommitDmlMode(mode); - - log("@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','" + mode.toString() + "'"); - log("SHOW VARIABLE AUTOCOMMIT_DML_MODE;"); - assertThat(connection.getAutocommitDmlMode(), is(equalTo(mode))); - } - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log( - "SET AUTOCOMMIT_DML_MODE='" - + AutocommitDmlMode.PARTITIONED_NON_ATOMIC.toString() - + "';"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - } - } - } - - abstract boolean isGetAutocommitDmlModeAllowed(); - - @Test - public void testGetAutocommitDmlMode() { - try (Connection connection = getConnection()) { - if (isGetAutocommitDmlModeAllowed()) { - log("@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE'"); - log("SHOW VARIABLE AUTOCOMMIT_DML_MODE;"); - assertThat(connection.getAutocommitDmlMode(), is(notNullValue())); - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SHOW VARIABLE AUTOCOMMIT_DML_MODE;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getAutocommitDmlMode(); - } - } - } - - abstract boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode); - - @Test - public void testSetReadOnlyStaleness() { - for (TimestampBound staleness : getTestTimestampBounds()) { - testSetReadOnlyStaleness(staleness); - } - } - - private List getTestTimestampBounds() { - return Arrays.asList( - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(Timestamp.now()), - TimestampBound.ofMinReadTimestamp(Timestamp.now()), - TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), - TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS), - TimestampBound.ofExactStaleness(100L, TimeUnit.MICROSECONDS)); - } - - private void testSetReadOnlyStaleness(final TimestampBound staleness) { - try (Connection connection = getConnection()) { - if (isSetReadOnlyStalenessAllowed(staleness.getMode())) { - log( - "SET READ_ONLY_STALENESS='" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "';"); - connection.setReadOnlyStaleness(staleness); - - log( - "@EXPECT RESULT_SET 'READ_ONLY_STALENESS','" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "'"); - log("SHOW VARIABLE READ_ONLY_STALENESS;"); - assertThat(connection.getReadOnlyStaleness(), is(equalTo(staleness))); - } else { - expectSpannerException( - staleness.getMode() + " should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log( - "SET READ_ONLY_STALENESS='" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "';"); - t.setReadOnlyStaleness(staleness); - } - }, - connection); - } - } - } - - abstract boolean isGetReadOnlyStalenessAllowed(); - - @Test - public void testGetReadOnlyStaleness() { - try (Connection connection = getConnection()) { - if (isGetReadOnlyStalenessAllowed()) { - log("@EXPECT RESULT_SET 'READ_ONLY_STALENESS'"); - log("SHOW VARIABLE READ_ONLY_STALENESS;"); - assertThat(connection.getReadOnlyStaleness(), is(notNullValue())); - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SHOW VARIABLE READ_ONLY_STALENESS;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getReadOnlyStaleness(); - } - } - } - - boolean isSetOptimizerVersionAllowed() { - return !getConnection().isClosed(); - } - - @Test - public void testSetOptimizerVersion() { - try (Connection connection = getConnection()) { - if (isSetOptimizerVersionAllowed()) { - for (String version : new String[] {"1", "2", "latest", ""}) { - log("SET OPTIMIZER_VERSION='" + version + "';"); - connection.setOptimizerVersion(version); - - log("@EXPECT RESULT_SET 'OPTIMIZER_VERSION','" + version + "'"); - log("SHOW VARIABLE OPTIMIZER_VERSION;"); - assertThat(connection.getOptimizerVersion(), is(equalTo(version))); - } - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SET OPTIMIZER_VERSION='1';"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.setOptimizerVersion("1"); - } - } - } - - boolean isGetOptimizerVersionAllowed() { - return !getConnection().isClosed(); - } - - @Test - public void testGetOptimizerVersion() { - try (Connection connection = getConnection()) { - if (isGetOptimizerVersionAllowed()) { - log("@EXPECT RESULT_SET 'OPTIMIZER_VERSION'"); - log("SHOW VARIABLE OPTIMIZER_VERSION;"); - assertThat(connection.getOptimizerVersion(), is(notNullValue())); - } else { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log("SHOW VARIABLE OPTIMIZER_VERSION;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getOptimizerVersion(); - } - } - } - - abstract boolean isCommitAllowed(); - - @Test - public void testCommit() { - try (Connection connection = getConnection()) { - if (!isCommitAllowed()) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - log("COMMIT;"); - connection.commit(); - } - } - - abstract boolean isRollbackAllowed(); - - @Test - public void testRollback() { - try (Connection connection = getConnection()) { - if (!isRollbackAllowed()) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - log("ROLLBACK;"); - connection.rollback(); - } - } - - abstract boolean expectedIsInTransaction(); - - @Test - public void testIsInTransaction() { - try (Connection connection = getConnection()) { - assertThat(connection.isInTransaction(), is(expectedIsInTransaction())); - } - } - - abstract boolean expectedIsTransactionStarted(); - - @Test - public void testIsTransactionStarted() { - try (Connection connection = getConnection()) { - assertThat(connection.isTransactionStarted(), is(expectedIsTransactionStarted())); - } - } - - abstract boolean isGetReadTimestampAllowed(); - - @Test - public void testGetReadTimestamp() { - try (Connection connection = getConnection()) { - if (isGetReadTimestampAllowed()) { - log("@EXPECT RESULT_SET 'READ_TIMESTAMP'"); - log("SHOW VARIABLE READ_TIMESTAMP;"); - assertThat(connection.getReadTimestamp(), is(notNullValue())); - } else { - log("@EXPECT RESULT_SET 'READ_TIMESTAMP',null"); - log("SHOW VARIABLE READ_TIMESTAMP;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getReadTimestamp(); - } - } - } - - abstract boolean isGetCommitTimestampAllowed(); - - @Test - public void testGetCommitTimestamp() { - try (Connection connection = getConnection()) { - if (isGetCommitTimestampAllowed()) { - log("@EXPECT RESULT_SET 'COMMIT_TIMESTAMP'"); - log("SHOW VARIABLE COMMIT_TIMESTAMP;"); - assertThat(connection.getCommitTimestamp(), is(notNullValue())); - } else { - log("@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null"); - log("SHOW VARIABLE COMMIT_TIMESTAMP;"); - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.getCommitTimestamp(); - } - } - } - - abstract boolean isExecuteAllowed(StatementType type); - - @Test - public void testExecute() { - for (StatementType type : - new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { - testExecute(type); - } - } - - private void testExecute(final StatementType type) { - try (Connection connection = getConnection()) { - if (isExecuteAllowed(type)) { - log(getTestStatement(type).getSql() + ";"); - assertThat(connection.execute(getTestStatement(type)), is(notNullValue())); - } else { - expectSpannerException( - type + " should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(getTestStatement(type).getSql() + ";"); - t.execute(getTestStatement(type)); - } - }, - connection); - } - } - } - - private Statement getTestStatement(StatementType type) { - switch (type) { - case QUERY: - return Statement.of(SELECT); - case UPDATE: - return Statement.of(UPDATE); - case DDL: - return Statement.of(DDL); - case CLIENT_SIDE: - case UNKNOWN: - default: - throw new IllegalArgumentException("Unsupported type: " + type); - } - } - - @Test - public void testExecuteQuery() { - for (StatementType type : - new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { - testExecuteQuery(type); - } - } - - private void testExecuteQuery(final StatementType type) { - try (Connection connection = getConnection()) { - if (type == StatementType.QUERY && isExecuteAllowed(StatementType.QUERY)) { - log("@EXPECT RESULT_SET 'TEST',1"); - log(getTestStatement(type).getSql() + ";"); - ResultSet rs = connection.executeQuery(getTestStatement(type)); - assertThat(rs, is(notNullValue())); - assertThat(rs.getStats(), is(nullValue())); - } else if (type == StatementType.QUERY) { - // it is a query, but queries are not allowed for this connection state - expectSpannerException( - type + " should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(getTestStatement(type).getSql() + ";"); - t.executeQuery(getTestStatement(type)); - } - }, - connection, - ErrorCode.FAILED_PRECONDITION); - } else { - expectSpannerException( - type + " should be an invalid argument", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.executeQuery(getTestStatement(type)); - } - }, - connection, - ErrorCode.INVALID_ARGUMENT); - } - } - } - - @Test - public void testAnalyzeQuery() { - for (StatementType type : - new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { - testAnalyzeQuery(type); - } - } - - private void testAnalyzeQuery(final StatementType type) { - // TODO: add log statements when ANALYZE ... sql statements are supported - try (Connection connection = getConnection()) { - for (QueryAnalyzeMode mode : QueryAnalyzeMode.values()) { - final QueryAnalyzeMode currentMode = mode; - if (type == StatementType.QUERY && isExecuteAllowed(StatementType.QUERY)) { - ResultSet rs = connection.analyzeQuery(getTestStatement(type), currentMode); - assertThat(rs, is(notNullValue())); - while (rs.next()) {} - assertThat(rs.getStats(), is(notNullValue())); - } else if (type == StatementType.QUERY) { - // it is a query, but queries are not allowed for this connection state - expectSpannerException( - type + " should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.analyzeQuery(getTestStatement(type), currentMode); - } - }, - connection, - ErrorCode.FAILED_PRECONDITION); - } else { - expectSpannerException( - type + " should be an invalid argument", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.analyzeQuery(getTestStatement(type), currentMode); - } - }, - connection, - ErrorCode.INVALID_ARGUMENT); - } - } - } - } - - @Test - public void testExecuteUpdate() { - for (StatementType type : - new StatementType[] {StatementType.QUERY, StatementType.UPDATE, StatementType.DDL}) { - testExecuteUpdate(type); - } - } - - private void testExecuteUpdate(final StatementType type) { - try (Connection connection = getConnection()) { - if (type == StatementType.UPDATE && isExecuteAllowed(StatementType.UPDATE)) { - log("@EXPECT UPDATE_COUNT 1"); - log(getTestStatement(type).getSql() + ";"); - assertThat(connection.executeUpdate(getTestStatement(type)), is(notNullValue())); - } else if (type == StatementType.UPDATE) { - // it is an update statement, but updates are not allowed for this connection state - expectSpannerException( - type + "should not be allowed", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - log("@EXPECT EXCEPTION FAILED_PRECONDITION"); - log(getTestStatement(type).getSql() + ";"); - t.executeUpdate(getTestStatement(type)); - } - }, - connection, - ErrorCode.FAILED_PRECONDITION); - } else { - expectSpannerException( - type + " should be an invalid argument", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.executeUpdate(getTestStatement(type)); - } - }, - connection, - ErrorCode.INVALID_ARGUMENT); - } - } - } - - abstract boolean isWriteAllowed(); - - @Test - public void testWrite() { - try (Connection connection = getConnection()) { - if (!isWriteAllowed() || !connection.isAutocommit()) { - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - connection.write(createTestMutation()); - } - } - - @Test - public void testWriteIterable() { - try (Connection connection = getConnection()) { - if (!isWriteAllowed() || !connection.isAutocommit()) { - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - connection.write(Arrays.asList(createTestMutation())); - } - } - - @Test - public void testBufferedWrite() { - try (Connection connection = getConnection()) { - if (!isWriteAllowed() || connection.isAutocommit()) { - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - connection.bufferedWrite(createTestMutation()); - } - } - - @Test - public void testBufferedWriteIterable() { - try (Connection connection = getConnection()) { - if (!isWriteAllowed() || connection.isAutocommit()) { - exception.expect(matchCode(ErrorCode.FAILED_PRECONDITION)); - } - connection.bufferedWrite(Arrays.asList(createTestMutation())); - } - } - - private Mutation createTestMutation() { - return Mutation.newInsertBuilder("foo").set("id").to(1L).set("name").to("bar").build(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java deleted file mode 100644 index 4117eed29ae7..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractMockServerTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2020 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.MockSpannerServiceImpl; -import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; -import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.AbortInterceptor; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest.ITConnection; -import com.google.protobuf.AbstractMessage; -import com.google.protobuf.ListValue; -import com.google.protobuf.Value; -import com.google.spanner.v1.ExecuteSqlRequest; -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 io.grpc.Server; -import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public abstract class AbstractMockServerTest { - static final long COUNT_BEFORE_INSERT = 0L; - static final long COUNT_AFTER_INSERT = 1L; - static final Statement SELECT_COUNT_STATEMENT = - Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"); - private static final ResultSetMetadata SELECT_COUNT_METADATA = - ResultSetMetadata.newBuilder() - .setRowType( - StructType.newBuilder() - .addFields( - Field.newBuilder() - .setName("C") - .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) - .build()) - .build()) - .build(); - static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_BEFORE_INSERT = - com.google.spanner.v1.ResultSet.newBuilder() - .addRows( - ListValue.newBuilder() - .addValues( - Value.newBuilder() - .setStringValue(String.valueOf(COUNT_BEFORE_INSERT)) - .build()) - .build()) - .setMetadata(SELECT_COUNT_METADATA) - .build(); - static final com.google.spanner.v1.ResultSet SELECT_COUNT_RESULTSET_AFTER_INSERT = - com.google.spanner.v1.ResultSet.newBuilder() - .addRows( - ListValue.newBuilder() - .addValues( - Value.newBuilder().setStringValue(String.valueOf(COUNT_AFTER_INSERT)).build()) - .build()) - .setMetadata(SELECT_COUNT_METADATA) - .build(); - static final Statement INSERT_STATEMENT = - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"); - static final int UPDATE_COUNT = 1; - - static MockSpannerServiceImpl mockSpanner; - static MockInstanceAdminImpl mockInstanceAdmin; - static MockDatabaseAdminImpl mockDatabaseAdmin; - private static Server server; - private static InetSocketAddress address; - - @BeforeClass - public static void startStaticServer() throws IOException { - mockSpanner = new MockSpannerServiceImpl(); - mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. - mockInstanceAdmin = new MockInstanceAdminImpl(); - mockDatabaseAdmin = new MockDatabaseAdminImpl(); - address = new InetSocketAddress("localhost", 0); - server = - NettyServerBuilder.forAddress(address) - .addService(mockSpanner) - .addService(mockInstanceAdmin) - .addService(mockDatabaseAdmin) - .build() - .start(); - mockSpanner.putStatementResult( - StatementResult.query(SELECT_COUNT_STATEMENT, SELECT_COUNT_RESULTSET_BEFORE_INSERT)); - mockSpanner.putStatementResult(StatementResult.update(INSERT_STATEMENT, UPDATE_COUNT)); - } - - @AfterClass - public static void stopServer() throws Exception { - SpannerPool.closeSpannerPool(); - server.shutdown(); - server.awaitTermination(); - } - - @Before - public void setupResults() { - mockSpanner.reset(); - } - - @After - public void closeSpannerPool() { - SpannerPool.closeSpannerPool(); - } - - java.sql.Connection createJdbcConnection() throws SQLException { - return DriverManager.getConnection("jdbc:" + getBaseUrl()); - } - - ITConnection createConnection() { - return createConnection( - Collections.emptyList(), - Collections.emptyList()); - } - - ITConnection createConnection( - AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { - return createConnection( - Arrays.asList(interceptor), - Arrays.asList(transactionRetryListener)); - } - - ITConnection createConnection( - List interceptors, - List transactionRetryListeners) { - StringBuilder url = new StringBuilder(getBaseUrl()); - ConnectionOptions.Builder builder = - ConnectionOptions.newBuilder() - .setUri(url.toString()) - .setStatementExecutionInterceptors(interceptors); - ConnectionOptions options = builder.build(); - ITConnection connection = createITConnection(options); - for (TransactionRetryListener listener : transactionRetryListeners) { - connection.addTransactionRetryListener(listener); - } - return connection; - } - - String getBaseUrl() { - return String.format( - "cloudspanner://localhost:%d/projects/proj/instances/inst/databases/db?usePlainText=true;autocommit=false;retryAbortsInternally=true", - server.getPort()); - } - - ExecuteSqlRequest getLastExecuteSqlRequest() { - List requests = mockSpanner.getRequests(); - for (int i = requests.size() - 1; i >= 0; i--) { - if (requests.get(i) instanceof ExecuteSqlRequest) { - return (ExecuteSqlRequest) requests.get(i); - } - } - throw new IllegalStateException("No ExecuteSqlRequest found in requests"); - } - - private ITConnection createITConnection(ConnectionOptions options) { - return new ITConnectionImpl(options); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java deleted file mode 100644 index 3e854d3e16cb..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractSqlScriptVerifier.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Base class for SQL Script verifiers for both the generic Connection API and JDBC connections - * - *

    Simple parser/verifier for sql statements. This verifier is able to parse additional @EXPECT - * statements that defines the expected behavior of a sql statement. Possible uses are: - * - *

      - *
    • @EXPECT NO_RESULT: The following statement should not return a result (no {@link ResultSet} - * and no update count) - *
    • @EXPECT UPDATE_COUNT count: The following statement should return the specified - * update count - *
    • @EXPECT RESULT_SET: The following statement should return a {@link ResultSet} with two - * columns with the names ACTUAL and EXPECTED and containing at least one row. For each row, - * the values of ACTUAL and EXPECTED must be equal - *
    • @EXPECT RESULT_SET 'columnName': The following statement should return a {@link ResultSet} - * with a column with the specified name and containing at least one row (additional columns - * in the {@link ResultSet} are allowed). For each row, the value of the column must be not - * null - *
    • @EXPECT RESULT_SET 'columnName',value: The following statement should return a {@link - * ResultSet} with a column with the specified name and containing at least one row - * (additional columns in the {@link ResultSet} are allowed). For each row, the value of the - * column must be equal to the specified value - *
    • @EXPECT EXCEPTION code ['messagePrefix']: The following statement should throw a {@link - * SpannerException} with the specified code and starting with the (optional) message prefix - *
    • @EXPECT EQUAL 'variable1','variable2': The values of the two given variables should be - * equal. The value of a variable can be set using a @PUT statement. - *
    - * - * The parser can set a temporary variable value using a @PUT statement: - * @PUT 'variable_name'\nSQL statement The SQL statement must be a statement that returns a - * {@link ResultSet} containing exactly one row and one column. - * - *

    In addition the verifier can create new connections if the script contains NEW_CONNECTION; - * statements and the verifier has been created with a {@link GenericConnectionProvider}. See {@link - * ConnectionImplGeneratedSqlScriptTest} for an example for this. - */ -public abstract class AbstractSqlScriptVerifier { - private static final Pattern VERIFY_PATTERN = - Pattern.compile( - "(?is)\\s*(?:@EXPECT)\\s+" - + "(?NO_RESULT" - + "|RESULT_SET\\s*(?'.*?'(?,.*?)?)?" - + "|UPDATE_COUNT\\s*(?-?\\d{1,19})" - + "|EXCEPTION\\s*(?(?CANCELLED|UNKNOWN|INVALID_ARGUMENT|DEADLINE_EXCEEDED|NOT_FOUND|ALREADY_EXISTS|PERMISSION_DENIED|UNAUTHENTICATED|RESOURCE_EXHAUSTED|FAILED_PRECONDITION|ABORTED|OUT_OF_RANGE|UNIMPLEMENTED|INTERNAL|UNAVAILABLE|DATA_LOSS)(?:\\s*)(?'.*?')?)" - + "|EQUAL\\s+(?'.+?')\\s*,\\s*(?'.+?')" - + ")" - + "(\\n(?.*))?"); - - private static final String PUT_CONDITION = - "@PUT can only be used in combination with a statement that returns a" - + " result set containing exactly one row and one column"; - private static final Pattern PUT_PATTERN = - Pattern.compile("(?is)\\s*(?:@PUT)\\s+(?'.*?')" + "\\n(?.*)"); - - protected enum ExpectedResultType { - RESULT_SET, - UPDATE_COUNT, - NO_RESULT, - EXCEPTION, - EQUAL; - - StatementResult.ResultType getStatementResultType() { - switch (this) { - case NO_RESULT: - return StatementResult.ResultType.NO_RESULT; - case RESULT_SET: - return StatementResult.ResultType.RESULT_SET; - case UPDATE_COUNT: - return StatementResult.ResultType.UPDATE_COUNT; - case EXCEPTION: - case EQUAL: - default: - throw new IllegalArgumentException("not supported"); - } - } - } - - /** Result of an executed statement */ - protected abstract static class GenericStatementResult { - protected abstract StatementResult.ResultType getResultType(); - - protected abstract GenericResultSet getResultSet(); - - protected abstract long getUpdateCount(); - } - - /** - * Generic wrapper around a connection to a database. The underlying connection could be a Spanner - * {@link com.google.cloud.spanner.jdbc.Connection} or a JDBC {@link java.sql.Connection} - */ - public abstract static class GenericConnection implements AutoCloseable { - protected abstract GenericStatementResult execute(String sql) throws Exception; - - @Override - public abstract void close() throws Exception; - } - - /** - * Generic wrapper around a result set. The underlying result set could be a Spanner {@link - * ResultSet} or a JDBC {@link java.sql.ResultSet} - */ - protected abstract static class GenericResultSet { - protected abstract boolean next() throws Exception; - - protected abstract Object getValue(String col) throws Exception; - - protected abstract int getColumnCount() throws Exception; - - protected abstract Object getFirstValue() throws Exception; - } - - public static interface GenericConnectionProvider { - public GenericConnection getConnection(); - } - - /** Reads SQL statements from a file. Any copyright header in the file will be stripped away. */ - public static List readStatementsFromFile(String filename, Class resourceClass) { - File file = new File(resourceClass.getResource(filename).getFile()); - StringBuilder builder = new StringBuilder(); - try (Scanner scanner = new Scanner(file)) { - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - builder.append(line).append("\n"); - } - scanner.close(); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - String script = builder.toString().replaceAll(StatementParserTest.COPYRIGHT_PATTERN, ""); - String[] array = script.split(";"); - List res = new ArrayList<>(array.length); - for (String statement : array) { - if (statement != null && statement.trim().length() > 0) { - res.add(statement); - } - } - return res; - } - - private final GenericConnectionProvider connectionProvider; - - private final Map variables = new HashMap<>(); - - private final boolean logStatements; - - /** - * Constructor for a verifier that will take a {@link GenericConnection} as a parameter to the - * {@link AbstractSqlScriptVerifier#verifyStatementsInFile(GenericConnection, String, Class, - * boolean)} - */ - public AbstractSqlScriptVerifier() { - this(null); - } - - /** Constructor for a verifier that will use a connection provider for connections */ - public AbstractSqlScriptVerifier(GenericConnectionProvider provider) { - this.connectionProvider = provider; - this.logStatements = Boolean.parseBoolean(System.getProperty("log_sql_statements", "false")); - } - - /** - * Reads sql statements from the specified file name and executes and verifies these. Statements - * that are preceeded by an @EXPECT statement are verified against the @EXPECT specification. - * Statements without an @EXPECT statement will be executed and its result will be ignored, unless - * the statement throws an exception, which will fail the test case. - * - *

    The {@link com.google.cloud.spanner.jdbc.Connection}s that the statements are executed on - * must be created by a {@link GenericConnectionProvider} - * - * @param filename The file name containing the statements. Statements must be separated by a - * semicolon (;) - * @param resourceClass The class that should be used to locate the resource specified by the file - * name - * @throws Exception - */ - public void verifyStatementsInFile(String filename, Class resourceClass) throws Exception { - verifyStatementsInFile(connectionProvider.getConnection(), filename, resourceClass); - } - - /** - * Reads sql statements from the specified file name and executes and verifies these. Statements - * that are preceeded by an @EXPECT statement are verified against the @EXPECT specification. - * Statements without an @EXPECT statement will be executed and its result will be ignored, unless - * the statement throws an exception, which will fail the test case. - * - * @param connection The {@link com.google.cloud.spanner.jdbc.Connection} to execute the - * statements against - * @param filename The file name containing the statements. Statements must be separated by a - * semicolon (;) - * @param resourceClass The class that defines the package where to find the input file - */ - public void verifyStatementsInFile( - GenericConnection connection, String filename, Class resourceClass) throws Exception { - try { - List statements = readStatementsFromFile(filename, resourceClass); - for (String statement : statements) { - String sql = statement.trim(); - if (logStatements) { - System.out.println( - "\n------------------------------------------------------\n" - + new Date() - + " ---- verifying statement:"); - System.out.println(sql); - } - if (sql.equalsIgnoreCase("NEW_CONNECTION")) { - connection.close(); - connection = connectionProvider.getConnection(); - variables.clear(); - } else { - verifyStatement(connection, sql); - } - } - } finally { - if (connection != null) { - connection.close(); - } - } - } - - private void verifyStatement(GenericConnection connection, String statement) throws Exception { - statement = replaceVariables(statement); - String statementWithoutComments = StatementParser.removeCommentsAndTrim(statement); - Matcher verifyMatcher = VERIFY_PATTERN.matcher(statementWithoutComments); - Matcher putMatcher = PUT_PATTERN.matcher(statementWithoutComments); - if (verifyMatcher.matches()) { - String sql = verifyMatcher.group("statement"); - String typeName = verifyMatcher.group("type"); - int endIndex = getFirstSpaceChar(typeName); - ExpectedResultType type = ExpectedResultType.valueOf(typeName.substring(0, endIndex)); - if (type == ExpectedResultType.EXCEPTION) { - String code = verifyMatcher.group("code"); - String messagePrefix = verifyMatcher.group("messagePrefix"); - try { - connection.execute(sql); - fail("expected exception: " + sql); - } catch (Exception e) { - verifyExpectedException(statementWithoutComments, e, code, messagePrefix); - } - } else if (type == ExpectedResultType.EQUAL) { - String variable1 = verifyMatcher.group("variable1"); - String variable2 = verifyMatcher.group("variable2"); - // get rid of the single quotes - variable1 = variable1.substring(1, variable1.length() - 1); - variable2 = variable2.substring(1, variable2.length() - 1); - assertThat( - "No variable with name " + variable1, variables.containsKey(variable1), is(true)); - assertThat( - "No variable with name " + variable2, variables.containsKey(variable2), is(true)); - Object value1 = variables.get(variable1); - Object value2 = variables.get(variable2); - if ((value1 instanceof Timestamp) && (value2 instanceof Timestamp)) { - // read timestamps are rounded - Timestamp ts1 = (Timestamp) value1; - Timestamp ts2 = (Timestamp) value2; - value1 = - Timestamp.ofTimeSecondsAndNanos(ts1.getSeconds(), (ts1.getNanos() / 1000) * 1000); - value2 = - Timestamp.ofTimeSecondsAndNanos(ts2.getSeconds(), (ts2.getNanos() / 1000) * 1000); - } - assertThat(value1, is(equalTo(value2))); - } else { - GenericStatementResult result = connection.execute(sql); - assertThat(statement, result.getResultType(), is(equalTo(type.getStatementResultType()))); - switch (type.getStatementResultType()) { - case NO_RESULT: - break; - case RESULT_SET: - String column = verifyMatcher.group("column"); - if (column == null) { - verifyActualVsExpectedResultSet(statement, result.getResultSet()); - } else { - String value = verifyMatcher.group("value"); - if (value != null) { - String parts[] = column.split(",", 2); - column = parts[0].trim(); - value = parts[1].trim(); - column = column.substring(1, column.length() - 1); - verifyResultSetValue(statement, result.getResultSet(), column, parseValue(value)); - } else { - // get rid of the quotation marks - column = column.substring(1, column.length() - 1); - verifyResultSetColumnNotNull(statement, result.getResultSet(), column); - } - } - break; - case UPDATE_COUNT: - long expectedUpdateCount = Long.valueOf(verifyMatcher.group("count").trim()); - assertThat(statement, result.getUpdateCount(), is(equalTo(expectedUpdateCount))); - break; - } - } - } else if (putMatcher.matches()) { - String sql = putMatcher.group("statement"); - String variable = putMatcher.group("variable"); - // get rid of the single quotes - variable = variable.substring(1, variable.length() - 1); - GenericStatementResult result = connection.execute(sql); - assertThat( - PUT_CONDITION, - result.getResultType(), - is(equalTo(com.google.cloud.spanner.jdbc.StatementResult.ResultType.RESULT_SET))); - GenericResultSet rs = result.getResultSet(); - assertThat(PUT_CONDITION, rs.next(), is(true)); - assertThat(PUT_CONDITION, rs.getColumnCount(), is(equalTo(1))); - variables.put(variable, rs.getFirstValue()); - assertThat(PUT_CONDITION, rs.next(), is(false)); - } else { - // just execute the statement - connection.execute(statement); - } - } - - private String replaceVariables(String sql) { - for (String key : variables.keySet()) { - sql = sql.replaceAll("%%" + key + "%%", variables.get(key).toString()); - } - return sql; - } - - protected abstract void verifyExpectedException( - String statement, Exception e, String code, String messagePrefix); - - private static final Pattern INT64_PATTERN = Pattern.compile("\\d{1,19}"); - private static final Pattern ARRAY_INT64_PATTERN = - Pattern.compile("\\[\\s*\\d{1,19}(\\s*,\\s*\\d{1,19})*\\s*\\]"); - private static final Pattern FLOAT64_PATTERN = Pattern.compile("\\d{1,19}.\\d{1,19}"); - private static final String TS_PREFIX = "ts'"; - private static final String TS_SUFFIX = "'"; - private static final Pattern BOOLEAN_PATTERN = Pattern.compile("(?is)true|false"); - - private Object parseValue(String valueString) { - if (valueString == null || "".equals(valueString) || "null".equalsIgnoreCase(valueString)) { - return null; - } - if (valueString.startsWith("'") && valueString.endsWith("'")) { - return valueString.substring(1, valueString.length() - 1); - } - if (INT64_PATTERN.matcher(valueString).matches()) { - return Long.valueOf(valueString); - } - if (ARRAY_INT64_PATTERN.matcher(valueString).matches()) { - String[] stringArray = valueString.substring(1, valueString.length() - 1).split(","); - List res = new ArrayList<>(); - for (int i = 0; i < stringArray.length; i++) { - res.add(Long.valueOf(stringArray[i])); - } - return res; - } - if (FLOAT64_PATTERN.matcher(valueString).matches()) { - return Double.valueOf(valueString); - } - if (valueString.startsWith(TS_PREFIX) && valueString.endsWith(TS_SUFFIX)) { - try { - return ReadOnlyStalenessUtil.parseRfc3339( - valueString.substring(TS_PREFIX.length(), valueString.length() - TS_SUFFIX.length())); - } catch (IllegalArgumentException e) { - // ignore, apparently not a valid a timestamp after all. - } - } - if (BOOLEAN_PATTERN.matcher(valueString).matches()) { - return Boolean.valueOf(valueString); - } - return valueString; - } - - private int getFirstSpaceChar(String input) { - for (int index = 0; index < input.length(); index++) { - if (Character.isWhitespace(input.charAt(index))) { - return index; - } - } - return input.length(); - } - - private void verifyResultSetColumnNotNull(String statement, GenericResultSet rs, String column) - throws Exception { - int count = 0; - while (rs.next()) { - assertThat(statement, getValue(rs, column), is(notNullValue())); - count++; - } - assertThat(count, is(not(equalTo(0)))); - } - - private void verifyResultSetValue( - String statement, GenericResultSet rs, String column, Object value) throws Exception { - int count = 0; - while (rs.next()) { - if (value == null) { - assertThat(statement, getValue(rs, column), is(nullValue())); - } else { - assertEquals(statement, getValue(rs, column), value); - } - count++; - } - assertThat(count, is(not(equalTo(0)))); - } - - private void verifyActualVsExpectedResultSet(String statement, GenericResultSet rs) - throws Exception { - int count = 0; - while (rs.next()) { - assertThat(statement, getValue(rs, "ACTUAL"), is(equalTo(getValue(rs, "EXPECTED")))); - count++; - } - assertThat(count, is(not(equalTo(0)))); - } - - private Object getValue(GenericResultSet rs, String col) throws Exception { - return rs.getValue(col); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java deleted file mode 100644 index 4dcbd410e28e..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeConverterTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.AutocommitDmlModeConverter; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class AutocommitDmlModeConverterTest { - - @Test - public void testConvert() throws CompileException { - String allowedValues = - ReadOnlyStalenessConverterTest.getAllowedValues(AutocommitDmlModeConverter.class); - assertThat(allowedValues, is(notNullValue())); - AutocommitDmlModeConverter converter = new AutocommitDmlModeConverter(allowedValues); - assertThat(converter.convert("transactional"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - assertThat(converter.convert("TRANSACTIONAL"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - assertThat(converter.convert("Transactional"), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - - assertThat( - converter.convert("partitioned_non_atomic"), - is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); - assertThat( - converter.convert("Partitioned_Non_Atomic"), - is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); - assertThat( - converter.convert("PARTITIONED_NON_ATOMIC"), - is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); - - assertThat(converter.convert(""), is(nullValue())); - assertThat(converter.convert(" "), is(nullValue())); - assertThat(converter.convert("random string"), is(nullValue())); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java deleted file mode 100644 index bf350419d241..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutocommitDmlModeTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionRunner; -import com.google.cloud.spanner.TransactionRunner.TransactionCallable; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class AutocommitDmlModeTest { - private static final String UPDATE = "UPDATE foo SET bar=1"; - private static final String URI = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - - private DatabaseClient dbClient; - private TransactionContext txContext; - - @SuppressWarnings("unchecked") - private ConnectionImpl createConnection(ConnectionOptions options) { - dbClient = mock(DatabaseClient.class); - txContext = mock(TransactionContext.class); - Spanner spanner = mock(Spanner.class); - SpannerPool spannerPool = mock(SpannerPool.class); - when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) - .thenReturn(spanner); - DdlClient ddlClient = mock(DdlClient.class); - TransactionRunner txRunner = mock(TransactionRunner.class); - when(dbClient.readWriteTransaction()).thenReturn(txRunner); - when(txRunner.run(any(TransactionCallable.class))) - .thenAnswer( - new Answer() { - @Override - public Long answer(InvocationOnMock invocation) throws Throwable { - TransactionCallable callable = - (TransactionCallable) invocation.getArguments()[0]; - return callable.run(txContext); - } - }); - - TransactionManager txManager = mock(TransactionManager.class); - when(txManager.begin()).thenReturn(txContext); - when(dbClient.transactionManager()).thenReturn(txManager); - - return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); - } - - @Test - public void testAutocommitDmlModeTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(connection.isAutocommit(), is(true)); - assertThat(connection.isReadOnly(), is(false)); - assertThat(connection.getAutocommitDmlMode(), is(AutocommitDmlMode.TRANSACTIONAL)); - - connection.execute(Statement.of(UPDATE)); - verify(txContext).executeUpdate(Statement.of(UPDATE)); - verify(dbClient, never()).executePartitionedUpdate(Statement.of(UPDATE)); - } - } - - @Test - public void testAutocommitDmlModePartitioned() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(connection.isAutocommit(), is(true)); - assertThat(connection.isReadOnly(), is(false)); - connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - assertThat(connection.getAutocommitDmlMode(), is(AutocommitDmlMode.PARTITIONED_NON_ATOMIC)); - - connection.execute(Statement.of(UPDATE)); - verify(txContext, never()).executeUpdate(Statement.of(UPDATE)); - verify(dbClient).executePartitionedUpdate(Statement.of(UPDATE)); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java deleted file mode 100644 index f86295be65ca..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BooleanConverterTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.BooleanConverter; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class BooleanConverterTest { - - @Test - public void testConvert() throws CompileException { - String allowedValues = ReadOnlyStalenessConverterTest.getAllowedValues(BooleanConverter.class); - assertThat(allowedValues, is(notNullValue())); - BooleanConverter converter = new BooleanConverter(allowedValues); - assertThat(converter.convert("true"), is(equalTo(Boolean.TRUE))); - assertThat(converter.convert("TRUE"), is(equalTo(Boolean.TRUE))); - assertThat(converter.convert("True"), is(equalTo(Boolean.TRUE))); - - assertThat(converter.convert("false"), is(equalTo(Boolean.FALSE))); - assertThat(converter.convert("FALSE"), is(equalTo(Boolean.FALSE))); - assertThat(converter.convert("False"), is(equalTo(Boolean.FALSE))); - - assertThat(converter.convert(""), is(nullValue())); - assertThat(converter.convert(" "), is(nullValue())); - assertThat(converter.convert("random string"), is(nullValue())); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java deleted file mode 100644 index 4ba2cb7a0fb4..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Test that runs a pre-generated sql script for {@link ClientSideStatement}s. The sql script can be - * generated by running mvn -P generate-test-sql-scripts compile It is only necessary - * to generate a new test script if a new {@link ClientSideStatement} has been added, or the - * behavior of an existing {@link ClientSideStatement} has changed. - * - *

    This class does not need to be implemented for the client libraries of other programming - * languages. All test cases are covered by the sql file ClientSideStatementsTest.sql. - */ -@RunWith(JUnit4.class) -public class ClientSideStatementsTest { - - @Test - public void testExecuteClientSideStatementsScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("ClientSideStatementsTest.sql", getClass()); - } - - private static final String SCRIPT_FILE = - "src/test/resources/com/google/cloud/spanner/jdbc/ClientSideStatementsTest.sql"; - private static PrintWriter writer; - - /** Generates the test script file */ - static void generateTestScript() throws Exception { - try { - openLog(); - ClientSideStatements statements = ClientSideStatements.INSTANCE; - for (ClientSideStatementImpl statement : statements.getCompiledStatements()) { - generateTestStatements(statement); - } - } finally { - closeLog(); - } - } - - /** Writes the prerequisite statements + the given sql statement to a script file */ - private static void log(List pre, String sql) { - writeLog("NEW_CONNECTION"); - for (String prerequisite : pre) { - writeLog(prerequisite); - } - writeLog(sql); - } - - /** - * Writes the prerequisite statements + the given sql statement to a script file preceded by - * an @EXPECT EXCEPTION error statement - */ - private static void log(List pre, String statement, ErrorCode error) { - log(pre, "@EXPECT EXCEPTION " + error.name() + "\n" + statement); - } - - /** Writes the actual statement to the script file */ - private static void writeLog(String statement) { - writer.println(statement + ";"); - } - - private static void openLog() { - try { - writer = - new PrintWriter( - new OutputStreamWriter(new FileOutputStream(SCRIPT_FILE, false), "UTF8"), true); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @AfterClass - public static void closeLog() { - if (writer != null) { - writer.close(); - } - } - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } - - /** Generates test statements for all {@link ClientSideStatement}s */ - private static void generateTestStatements(ClientSideStatementImpl statement) { - for (String sql : statement.getExampleStatements()) { - log(statement.getExamplePrerequisiteStatements(), sql); - log(statement.getExamplePrerequisiteStatements(), upper(sql)); - log(statement.getExamplePrerequisiteStatements(), lower(sql)); - log(statement.getExamplePrerequisiteStatements(), withLeadingSpaces(sql)); - log(statement.getExamplePrerequisiteStatements(), withLeadingTabs(sql)); - log(statement.getExamplePrerequisiteStatements(), withLeadingLinefeeds(sql)); - log(statement.getExamplePrerequisiteStatements(), withTrailingSpaces(sql)); - log(statement.getExamplePrerequisiteStatements(), withTrailingTabs(sql)); - log(statement.getExamplePrerequisiteStatements(), withTrailingLinefeeds(sql)); - log(statement.getExamplePrerequisiteStatements(), withSpaces(sql)); - log(statement.getExamplePrerequisiteStatements(), withTabs(sql)); - log(statement.getExamplePrerequisiteStatements(), withLinefeeds(sql)); - - log( - statement.getExamplePrerequisiteStatements(), - withInvalidPrefix(sql), - ErrorCode.INVALID_ARGUMENT); - log( - statement.getExamplePrerequisiteStatements(), - withInvalidSuffix(sql), - ErrorCode.INVALID_ARGUMENT); - - final String[] replacements = { - "%", "_", "&", "$", "@", "!", "*", "(", ")", "-", "+", "-#", "/", "\\", "?", "-/", "/#", - "/-" - }; - for (String replacement : replacements) { - log( - statement.getExamplePrerequisiteStatements(), - withPrefix(replacement, sql), - ErrorCode.INVALID_ARGUMENT); - log( - statement.getExamplePrerequisiteStatements(), - withSuffix(replacement, sql), - ErrorCode.INVALID_ARGUMENT); - log( - statement.getExamplePrerequisiteStatements(), - replaceLastSpaceWith(replacement, sql), - ErrorCode.INVALID_ARGUMENT); - } - } - } - - private static String upper(String statement) { - return statement.toUpperCase(); - } - - private static String lower(String statement) { - return statement.toLowerCase(); - } - - private static String withLeadingSpaces(String statement) { - return " " + statement; - } - - private static String withLeadingTabs(String statement) { - return "\t\t\t" + statement; - } - - private static String withLeadingLinefeeds(String statement) { - return "\n\n\n" + statement; - } - - private static String withTrailingSpaces(String statement) { - return statement + " "; - } - - private static String withTrailingTabs(String statement) { - return statement + "\t\t"; - } - - private static String withTrailingLinefeeds(String statement) { - return statement + "\n\n"; - } - - private static String withSpaces(String statement) { - return statement.replaceAll(" ", " "); - } - - private static String withTabs(String statement) { - return statement.replaceAll(" ", "\t"); - } - - private static String withLinefeeds(String statement) { - // Do not replace spaces inside quotes - Matcher matcher = Pattern.compile("(.*)('.*')").matcher(statement); - if (matcher.matches()) { - return matcher.group(1).replaceAll(" ", "\n") + matcher.group(2); - } - return statement.replaceAll(" ", "\n"); - } - - private static String withInvalidPrefix(String statement) { - return "foo " + statement; - } - - private static String withInvalidSuffix(String statement) { - return statement + " bar"; - } - - private static String withPrefix(String prefix, String statement) { - return prefix + statement; - } - - private static String withSuffix(String suffix, String statement) { - return statement + suffix; - } - - private static String replaceLastSpaceWith(String replacement, String statement) { - if (statement.lastIndexOf(' ') > -1) { - return statement.substring(0, statement.lastIndexOf(' ')) - + replacement - + statement.substring(statement.lastIndexOf(' ') + 1); - } - return statement + replacement; - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java deleted file mode 100644 index 3cfd42d7e100..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadOnlyTest.java +++ /dev/null @@ -1,914 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import java.util.concurrent.TimeUnit; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -/** - * The tests in this class do not need to be implemented for client libraries in other programming - * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql - */ -@RunWith(Enclosed.class) -public class ConnectionImplAutocommitReadOnlyTest { - - public static class ConnectionImplAutocommitReadOnlyNoActionsTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query has been executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadOnlyAfterSelectTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - // no call to next() on ResultSet - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last statement was a query, next() has not yet been called, but as the connection api - // returns a directly executed resultset, the read timestamp is already available - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadOnlyAfterSelectAndResultSetNextTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)).next(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last statement was a query - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadOnlyAfterBeginTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // connection is in read-only mode - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // in a transaction, only exact allowed - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadOnlyAfterTemporaryTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - // readonly - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last action was a transaction that ended with a select query - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadOnlyAfterSetReadOnlyMaxStalenessTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - TimestampBound staleness = TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS); - log( - "SET READ_ONLY_STALENESS='" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "';"); - connection.setReadOnlyStaleness(staleness); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - // readonly - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java deleted file mode 100644 index 304bf8f539d7..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplAutocommitReadWriteTest.java +++ /dev/null @@ -1,1325 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -/** - * The tests in this class do not need to be implemented for client libraries in other programming - * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql - */ -@RunWith(Enclosed.class) -public class ConnectionImplAutocommitReadWriteTest { - - public static class ConnectionImplAutocommitReadWriteNoActionsTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query has been executed - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterSelectTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - // no next() called - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last statement was a query, next() has not yet been called, but as the connection api - // returns a directly executed resultset, the read timestamp is already available - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterSelectAndResultSetNextTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - // the @expect ensures next() is called - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // the last action was a query that has retrieved data - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterUpdateTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log(UPDATE + ";"); - connection.execute(Statement.of(UPDATE)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return true; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterDdlTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log(DDL + ";"); - connection.execute(Statement.of(DDL)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // there is no transaction - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterBeginTransactionTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // in temporary transaction - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - // default is a read-write transaction - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterTemporaryTransactionTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log(UPDATE + ";"); - connection.execute(Statement.of(UPDATE)); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return true; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return true; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return true; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterBeginReadOnlyTransactionTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log("SET TRANSACTION READ ONLY;"); - connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // in temporary transaction - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - // it's a read-only transaction - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplAutocommitReadWriteAfterStartDdlBatchTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=TRUE;"); - connection.setAutocommit(true); - log("START BATCH DDL;"); - connection.startBatchDdl(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return false; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - // it's a DDL batch - return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return true; - } - - @Override - boolean isAbortBatchAllowed() { - return true; - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java deleted file mode 100644 index fff50fa89821..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import com.google.common.collect.ImmutableSet; -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ClassInfo; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; -import org.junit.Test; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This test executes a SQL script that has been generated from the log of all the subclasses of - * {@link AbstractConnectionImplTest} and covers the same test cases. Its aim is to verify that the - * connection reacts correctly in all possible states (i.e. DML statements should not be allowed - * when the connection is in read-only mode, or when a read-only transaction has started etc.) - * - *

    A new test script can be generated by running: mvn -P generate-test-sql-scripts compile - * It is only necessary to generate a new test script if the behavior of {@link - * com.google.cloud.spanner.jdbc.Connection} has changed (for example calling COMMIT is currently - * not allowed in AUTOCOMMIT mode, but this has changed to be a no-op). A new test script must also - * be generated if additional test cases have been added to {@link AbstractConnectionImplTest}. - */ -@RunWith(JUnit4.class) -public class ConnectionImplGeneratedSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } - - @Test - public void testGeneratedScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("ConnectionImplGeneratedSqlScriptTest.sql", getClass()); - } - - /** - * Generates the test SQL script. It should be noted that running this method multiple times - * without having changed anything in the underlying code, could still yield different script - * files, as the script is generated by running a number of JUnit test cases. The order in which - * these test cases are run is non-deterministic. That means that the generated sql script will - * still contain exactly the same test cases after each generation, but the order of the test - * cases in the script file is equal to the order in which the test cases were run the last time - * the script was generated. It is therefore also not recommended to include this generation in an - * automatic build, but to generate the script only when there has been some fundamental change in - * the code. - * - *

    The sql test scripts can be generated by running - * mvn -P generate-test-sql-scripts compile - */ - static void generateTestScript() throws ClassNotFoundException, IOException { - // first make the current script file empty - AbstractConnectionImplTest.emptyScript(); - JUnitCore junit = new JUnitCore(); - Class[] testClasses = getAbstractConnectionImplTestSubclasses(); - Result result = junit.run(testClasses); - if (!result.wasSuccessful()) { - throw new RuntimeException("Generating test script failed!"); - } - } - - private static Class[] getAbstractConnectionImplTestSubclasses() - throws IOException, ClassNotFoundException { - List> list = new ArrayList<>(); - ClassPath cp = ClassPath.from(ConnectionImplGeneratedSqlScriptTest.class.getClassLoader()); - ImmutableSet classes = - cp.getTopLevelClassesRecursive( - ConnectionImplGeneratedSqlScriptTest.class.getPackage().getName()); - for (ClassInfo c : classes) { - Class clazz = - ConnectionImplGeneratedSqlScriptTest.class.getClassLoader().loadClass(c.getName()); - addAbstractConnectionImplTestSubclassesToList(list, clazz); - } - Class[] res = new Class[list.size()]; - for (int i = 0; i < list.size(); i++) { - res[i] = list.get(i); - } - return res; - } - - private static void addAbstractConnectionImplTestSubclassesToList( - List> list, Class clazz) { - for (Class innerClass : clazz.getDeclaredClasses()) { - addAbstractConnectionImplTestSubclassesToList(list, innerClass); - } - if (!clazz.isInterface() - && !Modifier.isAbstract(clazz.getModifiers()) - && AbstractConnectionImplTest.class.isAssignableFrom(clazz)) { - list.add(clazz); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java deleted file mode 100644 index 2c2cb964f09b..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTest.java +++ /dev/null @@ -1,1261 +0,0 @@ -/* - * Copyright 2019 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 com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.DDL; -import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.SELECT; -import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.UPDATE; -import static com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.expectSpannerException; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.NoCredentials; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ForwardingResultSet; -import com.google.cloud.spanner.Options; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ReadOnlyTransaction; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionRunner; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.ConnectionConsumer; -import com.google.cloud.spanner.jdbc.ConnectionImpl.UnitOfWorkType; -import com.google.cloud.spanner.jdbc.ConnectionStatementExecutorImpl.StatementTimeoutGetter; -import com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.GetExactStaleness; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import com.google.spanner.v1.ResultSetStats; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Matchers; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class ConnectionImplTest { - public static final String URI = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - - static class SimpleTransactionManager implements TransactionManager { - private TransactionState state; - private Timestamp commitTimestamp; - private TransactionContext txContext; - - private SimpleTransactionManager(TransactionContext txContext) { - this.txContext = txContext; - } - - @Override - public TransactionContext begin() { - state = TransactionState.STARTED; - return txContext; - } - - @Override - public void commit() { - commitTimestamp = Timestamp.now(); - state = TransactionState.COMMITTED; - } - - @Override - public void rollback() { - state = TransactionState.ROLLED_BACK; - } - - @Override - public TransactionContext resetForRetry() { - return txContext; - } - - @Override - public Timestamp getCommitTimestamp() { - return commitTimestamp; - } - - @Override - public TransactionState getState() { - return state; - } - - @Override - public void close() { - if (state != TransactionState.COMMITTED) { - state = TransactionState.ROLLED_BACK; - } - } - } - - private static class SimpleResultSet extends ForwardingResultSet { - private boolean nextCalled = false; - private boolean onValidRow = false; - private boolean hasNextReturnedFalse = false; - - SimpleResultSet(ResultSet delegate) { - super(delegate); - } - - @Override - public boolean next() { - nextCalled = true; - onValidRow = super.next(); - hasNextReturnedFalse = !onValidRow; - return onValidRow; - } - - boolean isNextCalled() { - return nextCalled; - } - - @Override - public ResultSetStats getStats() { - if (hasNextReturnedFalse) { - return super.getStats(); - } - return null; - } - - @Override - public long getLong(int columnIndex) { - if (onValidRow) { - return super.getLong(columnIndex); - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "ResultSet is not positioned on a valid row"); - } - } - - private static ResultSet createSelect1MockResultSet() { - ResultSet mockResultSet = mock(ResultSet.class); - when(mockResultSet.next()).thenReturn(true, false); - when(mockResultSet.getLong(0)).thenReturn(1L); - when(mockResultSet.getLong("TEST")).thenReturn(1L); - when(mockResultSet.getColumnType(0)).thenReturn(Type.int64()); - when(mockResultSet.getColumnType("TEST")).thenReturn(Type.int64()); - return mockResultSet; - } - - private static DdlClient createDefaultMockDdlClient() { - try { - DdlClient ddlClient = mock(DdlClient.class); - @SuppressWarnings("unchecked") - final OperationFuture operation = - mock(OperationFuture.class); - when(operation.get()).thenReturn(null); - UpdateDatabaseDdlMetadata metadata = UpdateDatabaseDdlMetadata.getDefaultInstance(); - ApiFuture futureMetadata = ApiFutures.immediateFuture(metadata); - when(operation.getMetadata()).thenReturn(futureMetadata); - when(ddlClient.executeDdl(anyString())).thenCallRealMethod(); - when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); - return ddlClient; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static ConnectionImpl createConnection(ConnectionOptions options) { - Spanner spanner = mock(Spanner.class); - SpannerPool spannerPool = mock(SpannerPool.class); - when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) - .thenReturn(spanner); - DdlClient ddlClient = createDefaultMockDdlClient(); - DatabaseClient dbClient = mock(DatabaseClient.class); - ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); - - ResultSet mockResultSetWithStats = createSelect1MockResultSet(); - when(mockResultSetWithStats.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); - - final SimpleResultSet select1ResultSet = new SimpleResultSet(createSelect1MockResultSet()); - final SimpleResultSet select1ResultSetWithStats = new SimpleResultSet(mockResultSetWithStats); - when(singleUseReadOnlyTx.executeQuery(Statement.of(SELECT))) - .thenAnswer( - new Answer() { - @Override - public ResultSet answer(InvocationOnMock invocation) throws Throwable { - if (select1ResultSet.nextCalled) { - // create a new mock - return new SimpleResultSet(createSelect1MockResultSet()); - } - return select1ResultSet; - } - }); - when(singleUseReadOnlyTx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) - .thenReturn(select1ResultSetWithStats); - when(singleUseReadOnlyTx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) - .thenReturn(select1ResultSetWithStats); - when(singleUseReadOnlyTx.getReadTimestamp()) - .then( - new Answer() { - @Override - public Timestamp answer(InvocationOnMock invocation) throws Throwable { - if (select1ResultSet.isNextCalled() || select1ResultSetWithStats.isNextCalled()) { - return Timestamp.now(); - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, "No query has returned with any data yet"); - } - }); - when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) - .thenReturn(singleUseReadOnlyTx); - - when(dbClient.transactionManager()) - .thenAnswer( - new Answer() { - @Override - public TransactionManager answer(InvocationOnMock invocation) throws Throwable { - TransactionContext txContext = mock(TransactionContext.class); - when(txContext.executeQuery(Statement.of(SELECT))) - .thenAnswer( - new Answer() { - @Override - public ResultSet answer(InvocationOnMock invocation) throws Throwable { - if (select1ResultSet.nextCalled) { - // create a new mock - return new SimpleResultSet(createSelect1MockResultSet()); - } - return select1ResultSet; - } - }); - when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) - .thenReturn(select1ResultSetWithStats); - when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) - .thenReturn(select1ResultSetWithStats); - when(txContext.executeUpdate(Statement.of(UPDATE))).thenReturn(1L); - return new SimpleTransactionManager(txContext); - } - }); - - when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))) - .thenAnswer( - new Answer() { - @Override - public ReadOnlyTransaction answer(InvocationOnMock invocation) throws Throwable { - ReadOnlyTransaction tx = mock(ReadOnlyTransaction.class); - when(tx.executeQuery(Statement.of(SELECT))) - .thenAnswer( - new Answer() { - @Override - public ResultSet answer(InvocationOnMock invocation) throws Throwable { - if (select1ResultSet.nextCalled) { - // create a new mock - return new SimpleResultSet(createSelect1MockResultSet()); - } - return select1ResultSet; - } - }); - when(tx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) - .thenReturn(select1ResultSetWithStats); - when(tx.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) - .thenReturn(select1ResultSetWithStats); - when(tx.getReadTimestamp()) - .then( - new Answer() { - @Override - public Timestamp answer(InvocationOnMock invocation) throws Throwable { - if (select1ResultSet.isNextCalled() - || select1ResultSetWithStats.isNextCalled()) { - return Timestamp.now(); - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.FAILED_PRECONDITION, - "No query has returned with any data yet"); - } - }); - return tx; - } - }); - - when(dbClient.readWriteTransaction()) - .thenAnswer( - new Answer() { - @Override - public TransactionRunner answer(InvocationOnMock invocation) throws Throwable { - TransactionRunner runner = - new TransactionRunner() { - private Timestamp commitTimestamp; - - @SuppressWarnings("unchecked") - @Override - public T run(TransactionCallable callable) { - this.commitTimestamp = Timestamp.now(); - return (T) Long.valueOf(1L); - } - - @Override - public Timestamp getCommitTimestamp() { - return commitTimestamp; - } - - @Override - public TransactionRunner allowNestedTransaction() { - return this; - } - }; - return runner; - } - }); - return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); - } - - @Test - public void testExecuteSetAutocommitOn() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI + ";autocommit=false") - .build())) { - assertThat(subject.isAutocommit(), is(false)); - - StatementResult res = subject.execute(Statement.of("set autocommit = true")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isAutocommit(), is(true)); - } - } - - @Test - public void testExecuteSetAutocommitOff() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - - StatementResult res = subject.execute(Statement.of("set autocommit = false")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isAutocommit(), is(false)); - } - } - - @Test - public void testExecuteGetAutocommit() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - - // assert that autocommit is true (default) - assertThat(subject.isAutocommit(), is(true)); - StatementResult res = subject.execute(Statement.of("show variable autocommit")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getBoolean("AUTOCOMMIT"), is(true)); - - // set autocommit to false and assert that autocommit is false - res = subject.execute(Statement.of("set autocommit = false")); - assertThat(subject.isAutocommit(), is(false)); - res = subject.execute(Statement.of("show variable autocommit")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getBoolean("AUTOCOMMIT"), is(false)); - } - } - - @Test - public void testExecuteSetReadOnlyOn() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isReadOnly(), is(false)); - - StatementResult res = subject.execute(Statement.of("set readonly = true")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isReadOnly(), is(true)); - } - } - - @Test - public void testExecuteSetReadOnlyOff() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI + ";readonly=true") - .build())) { - assertThat(subject.isReadOnly(), is(true)); - - StatementResult res = subject.execute(Statement.of("set readonly = false")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isReadOnly(), is(false)); - } - } - - @Test - public void testExecuteGetReadOnly() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - - // assert that read only is false (default) - assertThat(subject.isReadOnly(), is(false)); - StatementResult res = subject.execute(Statement.of("show variable readonly")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getBoolean("READONLY"), is(false)); - - // set read only to true and assert that read only is true - res = subject.execute(Statement.of("set readonly = true")); - assertThat(subject.isReadOnly(), is(true)); - res = subject.execute(Statement.of("show variable readonly")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getBoolean("READONLY"), is(true)); - } - } - - @Test - public void testExecuteSetAutocommitDmlMode() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - - StatementResult res = - subject.execute(Statement.of("set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat( - subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC))); - - res = subject.execute(Statement.of("set autocommit_dml_mode='TRANSACTIONAL'")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - } - } - - @Test - public void testExecuteSetAutocommitDmlModeInvalidValue() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - - ErrorCode expected = null; - try { - subject.execute(Statement.of("set autocommit_dml_mode='NON_EXISTENT_VALUE'")); - } catch (SpannerException e) { - expected = e.getErrorCode(); - } - assertThat(expected, is(equalTo(ErrorCode.INVALID_ARGUMENT))); - } - } - - @Test - public void testExecuteGetAutocommitDmlMode() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - assertThat(subject.getAutocommitDmlMode(), is(equalTo(AutocommitDmlMode.TRANSACTIONAL))); - - StatementResult res = subject.execute(Statement.of("show variable autocommit_dml_mode")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat( - res.getResultSet().getString("AUTOCOMMIT_DML_MODE"), - is(equalTo(AutocommitDmlMode.TRANSACTIONAL.toString()))); - - subject.execute(Statement.of("set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'")); - res = subject.execute(Statement.of("show variable autocommit_dml_mode")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat( - res.getResultSet().getString("AUTOCOMMIT_DML_MODE"), - is(equalTo(AutocommitDmlMode.PARTITIONED_NON_ATOMIC.toString()))); - } - } - - @Test - public void testExecuteSetOptimizerVersion() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getOptimizerVersion(), is(equalTo(""))); - - StatementResult res = subject.execute(Statement.of("set optimizer_version='1'")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getOptimizerVersion(), is(equalTo("1"))); - - res = subject.execute(Statement.of("set optimizer_version='1000'")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getOptimizerVersion(), is(equalTo("1000"))); - - res = subject.execute(Statement.of("set optimizer_version='latest'")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getOptimizerVersion(), is(equalTo("latest"))); - - res = subject.execute(Statement.of("set optimizer_version=''")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getOptimizerVersion(), is(equalTo(""))); - } - } - - @Test - public void testExecuteSetOptimizerVersionInvalidValue() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getOptimizerVersion(), is(equalTo(""))); - - try { - subject.execute(Statement.of("set optimizer_version='NOT_A_VERSION'")); - fail("Missing expected exception"); - } catch (SpannerException e) { - assertThat(e.getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); - } - } - } - - @Test - public void testExecuteGetOptimizerVersion() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getOptimizerVersion(), is(equalTo(""))); - - StatementResult res = subject.execute(Statement.of("show variable optimizer_version")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getString("OPTIMIZER_VERSION"), is(equalTo(""))); - - subject.execute(Statement.of("set optimizer_version='1'")); - res = subject.execute(Statement.of("show variable optimizer_version")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getString("OPTIMIZER_VERSION"), is(equalTo("1"))); - } - } - - @Test - public void testExecuteSetStatementTimeout() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); - - for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { - for (Long timeout : new Long[] {1L, 100L, 10000L, 315576000000L}) { - StatementResult res = - subject.execute( - Statement.of( - String.format( - "set statement_timeout='%d%s'", - timeout, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getStatementTimeout(unit), is(equalTo(timeout))); - assertThat(subject.hasStatementTimeout(), is(true)); - - StatementResult resNoTimeout = - subject.execute(Statement.of("set statement_timeout=null")); - assertThat(resNoTimeout.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getStatementTimeout(unit), is(equalTo(0L))); - assertThat(subject.hasStatementTimeout(), is(false)); - } - } - } - } - - @Test - public void testExecuteSetStatementTimeoutInvalidValue() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); - - ErrorCode expected = null; - try { - subject.execute(Statement.of("set statement_timeout=-1")); - } catch (SpannerException e) { - expected = e.getErrorCode(); - } - assertThat(expected, is(equalTo(ErrorCode.INVALID_ARGUMENT))); - } - } - - @Test - public void testExecuteGetStatementTimeout() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getStatementTimeout(TimeUnit.MILLISECONDS), is(equalTo(0L))); - - for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { - for (Long timeout : new Long[] {1L, 100L, 10000L, 315576000000L}) { - subject.execute( - Statement.of( - String.format( - "set statement_timeout='%d%s'", - timeout, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); - StatementResult res = subject.execute(Statement.of("show variable statement_timeout")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - TimeUnit appropriateUnit = - ReadOnlyStalenessUtil.getAppropriateTimeUnit(new StatementTimeoutGetter(subject)); - assertThat( - res.getResultSet().getString("STATEMENT_TIMEOUT"), - is( - equalTo( - subject.getStatementTimeout(appropriateUnit) - + ReadOnlyStalenessUtil.getTimeUnitAbbreviation(appropriateUnit)))); - - subject.execute(Statement.of("set statement_timeout=null")); - StatementResult resNoTimeout = - subject.execute(Statement.of("show variable statement_timeout")); - assertThat(resNoTimeout.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(resNoTimeout.getResultSet().next(), is(true)); - assertThat(resNoTimeout.getResultSet().isNull("STATEMENT_TIMEOUT"), is(true)); - } - } - } - } - - @Test - public void testExecuteGetReadTimestamp() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.beginTransaction(); - subject.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - subject.executeQuery(Statement.of(AbstractConnectionImplTest.SELECT)); - StatementResult res = subject.execute(Statement.of("show variable read_timestamp")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getTimestamp("READ_TIMESTAMP"), is(notNullValue())); - subject.commit(); - } - } - - @Test - public void testExecuteGetCommitTimestamp() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.beginTransaction(); - subject.executeQuery(Statement.of(AbstractConnectionImplTest.SELECT)).next(); - subject.commit(); - StatementResult res = subject.execute(Statement.of("show variable commit_timestamp")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat(res.getResultSet().getTimestamp("COMMIT_TIMESTAMP"), is(notNullValue())); - } - } - - private static final class StalenessDuration { - private final long duration; - private final TimeUnit unit; - - private StalenessDuration(long duration, TimeUnit unit) { - this.duration = duration; - this.unit = unit; - } - - @Override - public String toString() { - GetExactStaleness getExactStalenessFunction = - new GetExactStaleness(TimestampBound.ofExactStaleness(duration, unit)); - return ReadOnlyStalenessUtil.durationToString(getExactStalenessFunction); - } - } - - @Test - public void testExecuteGetReadOnlyStaleness() { - Map timestamps = new HashMap<>(); - timestamps.put(Mode.READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:05:10Z")); - timestamps.put( - Mode.MIN_READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:05:10.12345Z")); - Map durations = new HashMap<>(); - durations.put(Mode.EXACT_STALENESS, new StalenessDuration(1000L, TimeUnit.MILLISECONDS)); - durations.put(Mode.MAX_STALENESS, new StalenessDuration(1234567L, TimeUnit.MICROSECONDS)); - List stalenesses = - Arrays.asList( - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(timestamps.get(Mode.READ_TIMESTAMP)), - TimestampBound.ofMinReadTimestamp(timestamps.get(Mode.MIN_READ_TIMESTAMP)), - TimestampBound.ofExactStaleness( - durations.get(Mode.EXACT_STALENESS).duration, - durations.get(Mode.EXACT_STALENESS).unit), - TimestampBound.ofMaxStaleness( - durations.get(Mode.MAX_STALENESS).duration, - durations.get(Mode.MAX_STALENESS).unit)); - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - for (TimestampBound staleness : stalenesses) { - subject.setReadOnlyStaleness(staleness); - StatementResult res = subject.execute(Statement.of("show variable read_only_staleness")); - assertThat(res.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(res.getResultSet().next(), is(true)); - assertThat( - res.getResultSet().getString("READ_ONLY_STALENESS"), - is(equalTo(ReadOnlyStalenessUtil.timestampBoundToString(staleness)))); - } - } - } - - @Test - public void testExecuteSetReadOnlyStaleness() { - Map timestamps = new HashMap<>(); - timestamps.put(Mode.READ_TIMESTAMP, ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T12:13:14Z")); - timestamps.put( - Mode.MIN_READ_TIMESTAMP, - ReadOnlyStalenessUtil.parseRfc3339("2018-10-08T14:13:14.1234+02:00")); - Map durations = new HashMap<>(); - durations.put(Mode.EXACT_STALENESS, new StalenessDuration(1000L, TimeUnit.MILLISECONDS)); - durations.put(Mode.MAX_STALENESS, new StalenessDuration(1234567L, TimeUnit.MICROSECONDS)); - List stalenesses = - Arrays.asList( - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(timestamps.get(Mode.READ_TIMESTAMP)), - TimestampBound.ofMinReadTimestamp(timestamps.get(Mode.MIN_READ_TIMESTAMP)), - TimestampBound.ofExactStaleness( - durations.get(Mode.EXACT_STALENESS).duration, - durations.get(Mode.EXACT_STALENESS).unit), - TimestampBound.ofMaxStaleness( - durations.get(Mode.MAX_STALENESS).duration, - durations.get(Mode.MAX_STALENESS).unit)); - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - for (TimestampBound staleness : stalenesses) { - StatementResult res = - subject.execute( - Statement.of( - String.format( - "set read_only_staleness='%s'", - ReadOnlyStalenessUtil.timestampBoundToString(staleness)))); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getReadOnlyStaleness(), is(equalTo(staleness))); - } - } - } - - @Test - public void testExecuteBeginTransaction() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isInTransaction(), is(false)); - - StatementResult res = subject.execute(Statement.of("begin transaction")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isInTransaction(), is(true)); - } - } - - @Test - public void testExecuteCommitTransaction() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.execute(Statement.of("begin transaction")); - assertThat(subject.isInTransaction(), is(true)); - - StatementResult res = subject.execute(Statement.of("commit")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isInTransaction(), is(false)); - } - } - - @Test - public void testExecuteRollbackTransaction() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.execute(Statement.of("begin")); - assertThat(subject.isInTransaction(), is(true)); - - StatementResult res = subject.execute(Statement.of("rollback")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.isInTransaction(), is(false)); - } - } - - @Test - public void testExecuteSetTransactionReadOnly() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.execute(Statement.of("begin")); - assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat(subject.isInTransaction(), is(true)); - - StatementResult res = subject.execute(Statement.of("set transaction read only")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - } - } - - @Test - public void testExecuteSetTransactionReadWrite() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI + ";readonly=true") - .build())) { - subject.execute(Statement.of("begin")); - assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat(subject.isInTransaction(), is(true)); - - // end the current temporary transaction and turn off read-only mode - subject.execute(Statement.of("commit")); - subject.execute(Statement.of("set readonly = false")); - - subject.execute(Statement.of("begin")); - StatementResult res = subject.execute(Statement.of("set transaction read only")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - res = subject.execute(Statement.of("set transaction read write")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - } - } - - @Test - public void testExecuteStartDdlBatch() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - StatementResult res = subject.execute(Statement.of("start batch ddl")); - assertThat(res.getResultType(), is(equalTo(ResultType.NO_RESULT))); - assertThat(subject.getUnitOfWorkType(), is(equalTo(UnitOfWorkType.DDL_BATCH))); - assertThat(subject.isInTransaction(), is(false)); - } - } - - @Test - public void testDefaultIsAutocommit() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - assertThat(subject.isInTransaction(), is(false)); - } - } - - @Test - public void testDefaultIsReadWrite() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isReadOnly(), is(false)); - } - } - - @Test - public void testDefaultTransactionIsReadWrite() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - for (boolean autocommit : new Boolean[] {true, false}) { - subject.setAutocommit(autocommit); - subject.execute(Statement.of("begin")); - assertThat( - subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - subject.commit(); - - subject.execute(Statement.of("begin")); - subject.execute(Statement.of("set transaction read only")); - assertThat( - subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - subject.commit(); - - subject.execute(Statement.of("begin")); - assertThat( - subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - subject.commit(); - - subject.execute(Statement.of("start batch ddl")); - assertThat(subject.getUnitOfWorkType(), is(equalTo(UnitOfWorkType.DDL_BATCH))); - subject.runBatch(); - - subject.execute(Statement.of("begin")); - assertThat( - subject.getTransactionMode(), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - subject.commit(); - } - } - } - - @Test - public void testDefaultTransactionIsReadOnly() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI + ";readOnly=true") - .build())) { - for (boolean autocommit : new Boolean[] {true, false}) { - subject.setAutocommit(autocommit); - subject.execute(Statement.of("begin")); - assertThat( - subject.getTransactionMode(), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - subject.commit(); - } - } - } - - /** - * ReadOnlyStaleness is a session setting for a connection. However, certain settings are only - * allowed when the connection is in autocommit mode. The setting therefore must be reset to its - * default {@link TimestampBound#strong()} when the current setting is not compatible with - * transactional mode. - */ - @Test - public void testResetReadOnlyStaleness() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.isAutocommit(), is(true)); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - - // the following values are always allowed - subject.setReadOnlyStaleness(TimestampBound.strong()); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - subject.setAutocommit(false); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - subject.setAutocommit(true); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - - subject.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)); - subject.setAutocommit(false); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)))); - subject.setAutocommit(true); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofReadTimestamp(Timestamp.MAX_VALUE)))); - - subject.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - subject.setAutocommit(false); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); - subject.setAutocommit(true); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); - - // the following values are only allowed in autocommit mode. Turning off autocommit will - // return the setting to its default - subject.setReadOnlyStaleness(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)))); - subject.setAutocommit(false); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - subject.setAutocommit(true); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - - subject.setReadOnlyStaleness(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)); - assertThat( - subject.getReadOnlyStaleness(), - is(equalTo(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)))); - subject.setAutocommit(false); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - subject.setAutocommit(true); - assertThat(subject.getReadOnlyStaleness().getMode(), is(equalTo(TimestampBound.Mode.STRONG))); - } - } - - @Test - public void testChangeReadOnlyModeInAutocommit() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.execute(Statement.of(UPDATE)); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - - // change to read-only - subject.setReadOnly(true); - expectSpannerException( - "Updates should not be allowed in read-only mode", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.execute(Statement.of(UPDATE)); - } - }, - subject); - assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); - - // change back to read-write - subject.setReadOnly(false); - subject.execute(Statement.of(UPDATE)); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - - // and back to read-only - subject.setReadOnly(true); - expectSpannerException( - "DDL should not be allowed in read-only mode", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.execute(Statement.of(DDL)); - } - }, - subject); - assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); - } - } - - @Test - public void testChangeReadOnlyModeInTransactionalMode() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - subject.setAutocommit(false); - - subject.execute(Statement.of(UPDATE)); - subject.commit(); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - - // change to read-only - subject.setReadOnly(true); - expectSpannerException( - "Updates should not be allowed in read-only mode", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.execute(Statement.of(UPDATE)); - } - }, - subject); - assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); - subject.commit(); - - // change back to read-write - subject.setReadOnly(false); - subject.execute(Statement.of(UPDATE)); - subject.commit(); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - - // and back to read-only - subject.setReadOnly(true); - expectSpannerException( - "DDL should not be allowed in read-only mode", - new ConnectionConsumer() { - @Override - public void accept(Connection t) { - t.execute(Statement.of(DDL)); - } - }, - subject); - assertThat(subject.executeQuery(Statement.of(SELECT)), is(notNullValue())); - } - } - - @Test - public void testAddRemoveTransactionRetryListener() { - try (ConnectionImpl subject = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(subject.getTransactionRetryListeners().hasNext(), is(false)); - TransactionRetryListener listener = mock(TransactionRetryListener.class); - subject.addTransactionRetryListener(listener); - assertThat(subject.getTransactionRetryListeners().hasNext(), is(true)); - assertThat(subject.removeTransactionRetryListener(listener), is(true)); - assertThat(subject.getTransactionRetryListeners().hasNext(), is(false)); - assertThat(subject.removeTransactionRetryListener(listener), is(false)); - } - } - - @Test - public void testMergeQueryOptions() { - ConnectionOptions connectionOptions = mock(ConnectionOptions.class); - SpannerPool spannerPool = mock(SpannerPool.class); - DdlClient ddlClient = mock(DdlClient.class); - DatabaseClient dbClient = mock(DatabaseClient.class); - final UnitOfWork unitOfWork = mock(UnitOfWork.class); - try (ConnectionImpl impl = - new ConnectionImpl(connectionOptions, spannerPool, ddlClient, dbClient) { - @Override - UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { - return unitOfWork; - } - }) { - // Execute query with an optimizer version set on the connection. - impl.setOptimizerVersion("1"); - impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); - verify(unitOfWork) - .executeQuery( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("1").build()) - .build()), - AnalyzeMode.NONE); - - // Execute query with an optimizer version set on the connection. - impl.setOptimizerVersion("2"); - impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); - verify(unitOfWork) - .executeQuery( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("2").build()) - .build()), - AnalyzeMode.NONE); - - // Execute query with an optimizer version set on the connection and PrefetchChunks query - // option specified for the query. - QueryOption prefetchOption = Options.prefetchChunks(100); - impl.setOptimizerVersion("3"); - impl.executeQuery(Statement.of("SELECT FOO FROM BAR"), prefetchOption); - verify(unitOfWork) - .executeQuery( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("3").build()) - .build()), - AnalyzeMode.NONE, - prefetchOption); - - // Execute query with an optimizer version set on the connection, and the same options also - // passed in to the query. The specific options passed in to the query should take precedence. - impl.setOptimizerVersion("4"); - impl.executeQuery( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("5").build()) - .build(), - prefetchOption); - verify(unitOfWork) - .executeQuery( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions(QueryOptions.newBuilder().setOptimizerVersion("5").build()) - .build()), - AnalyzeMode.NONE, - prefetchOption); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java deleted file mode 100644 index 99c959083cd3..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadOnlyTest.java +++ /dev/null @@ -1,1204 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import java.util.concurrent.TimeUnit; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -/** - * The tests in this class do not need to be implemented for client libraries in other programming - * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql - */ -@RunWith(Enclosed.class) -public class ConnectionImplTransactionalReadOnlyTest { - - public static class ConnectionImplTransactionalReadOnlyNoActionsTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query has been executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterSelectTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - // no call to next() on ResultSet - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // transaction has started - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return true; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last statement was a query, next() has not yet been called, but as the connection api - // returns a directly executed resultset, the read timestamp is already available - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterSelectAndResultSetNextTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)).next(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // transaction is running - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // transaction has started - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return true; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last statement was a query - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterBeginTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // connection is in read-only mode - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // in a transaction, only exact allowed - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last action was a transaction that ended with a select query - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterRollbackTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("ROLLBACK;"); - connection.rollback(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // transaction was rolled back - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterSetReadOnlyMaxStalenessTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - TimestampBound staleness = TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS); - log( - "SET READ_ONLY_STALENESS='" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "';"); - connection.setReadOnlyStaleness(staleness); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadOnlyAfterEmptyCommitTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=TRUE;"); - connection.setReadOnly(true); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return mode == TransactionMode.READ_ONLY_TRANSACTION; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last commit was empty - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // read-only - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java deleted file mode 100644 index ff58828eae3d..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionImplTransactionalReadWriteTest.java +++ /dev/null @@ -1,1945 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import java.util.concurrent.TimeUnit; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -/** - * The tests in this class do not need to be implemented for client libraries in other programming - * languages, as all test cases are covered by the file ConnectionImplGeneratedSqlScriptTest.sql - */ -@RunWith(Enclosed.class) -public class ConnectionImplTransactionalReadWriteTest { - - public static class ConnectionImplTransactionalReadWriteNoActionsTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query has been executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterSelectTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - // no call to next() on ResultSet - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // transaction has started - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return true; - } - - @Override - boolean isGetReadTimestampAllowed() { - // read-write transactions never have a read-timestamp - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterSelectAndResultSetNextTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.executeQuery(Statement.of(SELECT)).next(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - // transaction is running - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // transaction has started - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return true; - } - - @Override - boolean isGetReadTimestampAllowed() { - // read-write transactions never have a read-timestamp - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterBeginTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalArgumentException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - // in a transaction, only exact allowed - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // read-write transaction never have a read-timestamp - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // last action was a read-write transaction - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return true; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterRollbackTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("BEGIN TRANSACTION;"); - connection.beginTransaction(); - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("ROLLBACK;"); - connection.rollback(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // transaction was rolled back - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterSetReadOnlyMaxStalenessTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - TimestampBound staleness = TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS); - log( - "SET READ_ONLY_STALENESS='" - + ReadOnlyStalenessUtil.timestampBoundToString(staleness) - + "';"); - connection.setReadOnlyStaleness(staleness); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterSetTransactionReadOnlyTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("SET TRANSACTION READ ONLY;"); - connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.QUERY; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterCommittedReadOnlyTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("SET TRANSACTION READ ONLY;"); - connection.setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - // ensure there will be a read-timestamp available by calling next() - log("@EXPECT RESULT_SET 'TEST',1"); - log(SELECT + ";"); - connection.execute(Statement.of(SELECT)).getResultSet().next(); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return true; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // last transaction was a read-only transaction - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterStartDdlBatchTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("START BATCH DDL;"); - connection.startBatchDdl(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return false; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // no commit yet - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return true; - } - - @Override - boolean isAbortBatchAllowed() { - return true; - } - } - - public static class ConnectionImplTransactionalReadWriteInDdlBatchTransactionTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("START BATCH DDL;"); - connection.startBatchDdl(); - log(DDL + ";"); - connection.execute(Statement.of(DDL)); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - throw new IllegalStateException(); - } - - @Override - boolean isSetAutocommitAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyAllowed() { - return false; - } - - @Override - boolean isBeginTransactionAllowed() { - return false; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return false; - } - - @Override - boolean isGetTransactionModeAllowed() { - return false; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return false; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return false; - } - - @Override - boolean isCommitAllowed() { - return false; - } - - @Override - boolean isRollbackAllowed() { - return false; - } - - @Override - boolean expectedIsInTransaction() { - return false; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE || type == StatementType.DDL; - } - - @Override - boolean isWriteAllowed() { - return false; - } - - @Override - boolean isStartBatchDmlAllowed() { - return false; - } - - @Override - boolean isStartBatchDdlAllowed() { - return false; - } - - @Override - boolean isRunBatchAllowed() { - return true; - } - - @Override - boolean isAbortBatchAllowed() { - return true; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterRanDdlBatchTest - extends AbstractConnectionImplTest { - - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("START BATCH DDL;"); - connection.startBatchDdl(); - log(DDL + ";"); - connection.execute(Statement.of(DDL)); - log("RUN BATCH;"); - connection.runBatch(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // ddl-batch has no commit timestamp - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } - - public static class ConnectionImplTransactionalReadWriteAfterEmptyCommitTest - extends AbstractConnectionImplTest { - @Override - Connection getConnection() { - log("NEW_CONNECTION;"); - Connection connection = - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build()); - log("SET READONLY=FALSE;"); - connection.setReadOnly(false); - log("SET AUTOCOMMIT=FALSE;"); - connection.setAutocommit(false); - log("COMMIT;"); - connection.commit(); - return connection; - } - - @Override - boolean isSelectAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDmlAllowedAfterBeginTransaction() { - return true; - } - - @Override - boolean isDdlAllowedAfterBeginTransaction() { - return false; - } - - @Override - boolean isSetAutocommitAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyAllowed() { - return true; - } - - @Override - boolean isBeginTransactionAllowed() { - return true; - } - - @Override - boolean isSetTransactionModeAllowed(TransactionMode mode) { - return true; - } - - @Override - boolean isGetTransactionModeAllowed() { - return true; - } - - @Override - boolean isSetAutocommitDmlModeAllowed() { - return false; - } - - @Override - boolean isGetAutocommitDmlModeAllowed() { - return true; - } - - @Override - boolean isSetReadOnlyStalenessAllowed(TimestampBound.Mode mode) { - return mode == Mode.STRONG || mode == Mode.EXACT_STALENESS || mode == Mode.READ_TIMESTAMP; - } - - @Override - boolean isGetReadOnlyStalenessAllowed() { - return true; - } - - @Override - boolean isCommitAllowed() { - return true; - } - - @Override - boolean isRollbackAllowed() { - return true; - } - - @Override - boolean expectedIsInTransaction() { - return true; - } - - @Override - boolean expectedIsTransactionStarted() { - return false; - } - - @Override - boolean isGetReadTimestampAllowed() { - // no query has been executed yet - return false; - } - - @Override - boolean isGetCommitTimestampAllowed() { - // empty commit - return false; - } - - @Override - boolean isExecuteAllowed(StatementType type) { - return type == StatementType.CLIENT_SIDE - || type == StatementType.QUERY - || type == StatementType.UPDATE; - } - - @Override - boolean isWriteAllowed() { - return true; - } - - @Override - boolean isStartBatchDmlAllowed() { - return true; - } - - @Override - boolean isStartBatchDdlAllowed() { - return true; - } - - @Override - boolean isRunBatchAllowed() { - return false; - } - - @Override - boolean isAbortBatchAllowed() { - return false; - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java deleted file mode 100644 index 8eacbbf3a737..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionOptionsTest.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2019 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 com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; - -import com.google.auth.oauth2.GoogleCredentials; -import com.google.auth.oauth2.ServiceAccountCredentials; -import com.google.cloud.spanner.SpannerOptions; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ConnectionOptionsTest { - private static final String FILE_TEST_PATH = - ConnectionOptionsTest.class.getResource("test-key.json").getFile(); - private static final String DEFAULT_HOST = "https://spanner.googleapis.com"; - - @Test - public void testBuildWithURIWithDots() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner:/projects/some-company.com:test-project-123/instances/test-instance-123/databases/test-database-123"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); - assertThat(options.getProjectId()).isEqualTo("some-company.com:test-project-123"); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); - assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); - } - - @Test - public void testBuildWithValidURIAndCredentialsFileURL() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); - assertThat(options.getProjectId()).isEqualTo("test-project-123"); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); - assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); - } - - @Test - public void testBuildWithValidURIAndProperties() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance-123/databases/test-database-123?autocommit=false;readonly=true"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); - assertThat(options.getProjectId()).isEqualTo("test-project-123"); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(false); - assertThat(options.isReadOnly()).isEqualTo(true); - } - - @Test - public void testBuildWithHostAndValidURI() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner://test-spanner.googleapis.com/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo("https://test-spanner.googleapis.com"); - assertThat(options.getProjectId()).isEqualTo("test-project-123"); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); - assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); - } - - @Test - public void testBuildWithLocalhostPortAndValidURI() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner://localhost:8443/projects/test-project-123/instances/test-instance-123/databases/test-database-123"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo("https://localhost:8443"); - assertThat(options.getProjectId()).isEqualTo("test-project-123"); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); - assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); - } - - @Test - public void testBuildWithDefaultProjectPlaceholder() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - builder.setUri( - "cloudspanner:/projects/default_project_id/instances/test-instance-123/databases/test-database-123"); - builder.setCredentialsUrl(FILE_TEST_PATH); - ConnectionOptions options = builder.build(); - assertThat(options.getHost()).isEqualTo(DEFAULT_HOST); - String projectId = SpannerOptions.getDefaultProjectId(); - if (projectId == null) { - projectId = - ((ServiceAccountCredentials) new CredentialsService().createCredentials(FILE_TEST_PATH)) - .getProjectId(); - } - assertThat(options.getProjectId()).isEqualTo(projectId); - assertThat(options.getInstanceId()).isEqualTo("test-instance-123"); - assertThat(options.getDatabaseName()).isEqualTo("test-database-123"); - assertThat(options.getCredentials()) - .isEqualTo(new CredentialsService().createCredentials(FILE_TEST_PATH)); - assertThat(options.isAutocommit()).isEqualTo(ConnectionOptions.DEFAULT_AUTOCOMMIT); - assertThat(options.isReadOnly()).isEqualTo(ConnectionOptions.DEFAULT_READONLY); - } - - @Test - public void testBuilderSetUri() { - ConnectionOptions.Builder builder = ConnectionOptions.newBuilder(); - - // set valid uri's - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"); - builder.setUri("cloudspanner:/projects/test-project-123/instances/test-instance"); - builder.setUri("cloudspanner:/projects/test-project-123"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance"); - builder.setUri("cloudspanner://spanner.googleapis.com/projects/test-project-123"); - - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true"); - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance?autocommit=true"); - builder.setUri("cloudspanner:/projects/test-project-123?autocommit=true"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance?autocommit=true"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123?autocommit=true"); - - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true;readonly=false"); - builder.setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance?autocommit=true;readonly=false"); - builder.setUri("cloudspanner:/projects/test-project-123?autocommit=true;readonly=false"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database?autocommit=true;readonly=false"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123/instances/test-instance?autocommit=true;readonly=false"); - builder.setUri( - "cloudspanner://spanner.googleapis.com/projects/test-project-123?autocommit=true;readonly=false"); - - // set invalid uri's - setInvalidUri( - builder, "/projects/test-project-123/instances/test-instance/databases/test-database"); - setInvalidUri(builder, "cloudspanner:/test-project-123/test-instance/test-database"); - setInvalidUri( - builder, - "cloudspanner:spanner.googleapis.com/projects/test-project-123/instances/test-instance/databases/test-database"); - setInvalidUri( - builder, - "cloudspanner://spanner.googleapis.com/projects/test-project-$$$/instances/test-instance/databases/test-database"); - setInvalidUri( - builder, - "cloudspanner://spanner.googleapis.com/projects/test-project-123/databases/test-database"); - setInvalidUri( - builder, - "cloudspanner:/projects/test_project_123/instances/test-instance/databases/test-database"); - - // Set URI's that are valid, but that contain unknown properties. - setInvalidProperty( - builder, - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false", - "read"); - setInvalidProperty( - builder, - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false;autocommit=true", - "read"); - setInvalidProperty( - builder, - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?read=false;auto=true", - "read, auto"); - } - - private void setInvalidUri(ConnectionOptions.Builder builder, String uri) { - try { - builder.setUri(uri); - fail(uri + " should be considered an invalid uri"); - } catch (IllegalArgumentException e) { - } - } - - private void setInvalidProperty( - ConnectionOptions.Builder builder, String uri, String expectedInvalidProperties) { - try { - builder.setUri(uri); - fail("missing expected exception"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(expectedInvalidProperties); - } - } - - @Test - public void testParseUriProperty() { - final String baseUri = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - - assertThat(ConnectionOptions.parseUriProperty(baseUri, "autocommit")).isNull(); - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true", "autocommit")) - .isEqualTo("true"); - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false", "autocommit")) - .isEqualTo("false"); - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=true;", "autocommit")) - .isEqualTo("true"); - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?autocommit=false;", "autocommit")) - .isEqualTo("false"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=true;readOnly=false", "autocommit")) - .isEqualTo("true"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=false;readOnly=false", "autocommit")) - .isEqualTo("false"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=true", "autocommit")) - .isEqualTo("true"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=false", "autocommit")) - .isEqualTo("false"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=true;foo=bar", "autocommit")) - .isEqualTo("true"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?readOnly=false;autocommit=false;foo=bar", "autocommit")) - .isEqualTo("false"); - - // case insensitive - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=true", "autocommit")) - .isEqualTo("true"); - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?AutoCommit=false", "autocommit")) - .isEqualTo("false"); - - // ; instead of ? before the properties is ok - assertThat(ConnectionOptions.parseUriProperty(baseUri + ";autocommit=true", "autocommit")) - .isEqualTo("true"); - - // forgot the ? or ; before the properties - assertThat(ConnectionOptions.parseUriProperty(baseUri + "autocommit=true", "autocommit")) - .isNull(); - // substring is not ok - assertThat(ConnectionOptions.parseUriProperty(baseUri + "?isautocommit=true", "autocommit")) - .isNull(); - } - - @Test - public void testParseProperties() { - final String baseUri = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true")) - .isEqualTo(Arrays.asList("autocommit")); - assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true;readonly=false")) - .isEqualTo(Arrays.asList("autocommit", "readonly")); - assertThat(ConnectionOptions.parseProperties(baseUri + "?autocommit=true;READONLY=false")) - .isEqualTo(Arrays.asList("autocommit", "READONLY")); - assertThat(ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false")) - .isEqualTo(Arrays.asList("autocommit", "readonly")); - assertThat(ConnectionOptions.parseProperties(baseUri + ";autocommit=true;readonly=false;")) - .isEqualTo(Arrays.asList("autocommit", "readonly")); - } - - @Test - public void testParsePropertiesSpecifiedMultipleTimes() { - final String baseUri = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=true;autocommit=false", "autocommit")) - .isEqualTo("true"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + "?autocommit=false;autocommit=true", "autocommit")) - .isEqualTo("false"); - assertThat( - ConnectionOptions.parseUriProperty( - baseUri + ";autocommit=false;readonly=false;autocommit=true", "autocommit")) - .isEqualTo("false"); - ConnectionOptions.newBuilder() - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" - + ";autocommit=false;readonly=false;autocommit=true"); - } - - @Test - public void testParseOAuthToken() { - assertThat( - ConnectionOptions.parseUriProperty( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" - + "?oauthtoken=RsT5OjbzRn430zqMLgV3Ia", - "OAuthToken")) - .isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); - // Try to use both credentials and an OAuth token. That should fail. - ConnectionOptions.Builder builder = - ConnectionOptions.newBuilder() - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" - + "?OAuthToken=RsT5OjbzRn430zqMLgV3Ia;credentials=/path/to/credentials.json"); - try { - builder.build(); - fail("missing expected exception"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); - } - - // Now try to use only an OAuth token. - builder = - ConnectionOptions.newBuilder() - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database" - + "?OAuthToken=RsT5OjbzRn430zqMLgV3Ia"); - ConnectionOptions options = builder.build(); - assertThat(options.getCredentials()).isInstanceOf(GoogleCredentials.class); - GoogleCredentials credentials = (GoogleCredentials) options.getCredentials(); - assertThat(credentials.getAccessToken().getTokenValue()).isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); - } - - @Test - public void testSetOAuthToken() { - ConnectionOptions options = - ConnectionOptions.newBuilder() - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") - .setOAuthToken("RsT5OjbzRn430zqMLgV3Ia") - .build(); - assertThat(options.getCredentials()).isInstanceOf(GoogleCredentials.class); - GoogleCredentials credentials = (GoogleCredentials) options.getCredentials(); - assertThat(credentials.getAccessToken()).isNotNull(); - assertThat(credentials.getAccessToken().getTokenValue()).isEqualTo("RsT5OjbzRn430zqMLgV3Ia"); - } - - @Test - public void testSetOAuthTokenAndCredentials() { - try { - ConnectionOptions.newBuilder() - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") - .setOAuthToken("RsT5OjbzRn430zqMLgV3Ia") - .setCredentialsUrl(FILE_TEST_PATH) - .build(); - fail("missing expected exception"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java deleted file mode 100644 index 6e524c497235..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementExecutorTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.TimestampBound; -import com.google.protobuf.Duration; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ConnectionStatementExecutorTest { - - private ConnectionImpl connection; - private ConnectionStatementExecutorImpl subject; - - @Before - public void createSubject() { - connection = mock(ConnectionImpl.class); - when(connection.getAutocommitDmlMode()).thenReturn(AutocommitDmlMode.TRANSACTIONAL); - when(connection.getReadOnlyStaleness()).thenReturn(TimestampBound.strong()); - subject = new ConnectionStatementExecutorImpl(connection); - } - - @Test - public void testGetConnection() { - assertThat(subject.getConnection(), is(equalTo(connection))); - } - - @Test - public void testStatementBeginTransaction() { - subject.statementBeginTransaction(); - verify(connection).beginTransaction(); - } - - @Test - public void testStatementCommit() { - subject.statementCommit(); - verify(connection).commit(); - } - - @Test - public void testStatementGetAutocommit() { - subject.statementShowAutocommit(); - verify(connection).isAutocommit(); - } - - @Test - public void testStatementGetAutocommitDmlMode() { - subject.statementShowAutocommitDmlMode(); - verify(connection).getAutocommitDmlMode(); - } - - @Test - public void testStatementGetCommitTimestamp() { - subject.statementShowCommitTimestamp(); - verify(connection).getCommitTimestampOrNull(); - } - - @Test - public void testStatementGetReadOnly() { - subject.statementShowReadOnly(); - verify(connection).isReadOnly(); - } - - @Test - public void testStatementGetReadOnlyStaleness() { - subject.statementShowReadOnlyStaleness(); - verify(connection).getReadOnlyStaleness(); - } - - @Test - public void testStatementGetOptimizerVersion() { - subject.statementShowOptimizerVersion(); - verify(connection).getOptimizerVersion(); - } - - @Test - public void testStatementGetReadTimestamp() { - subject.statementShowReadTimestamp(); - verify(connection).getReadTimestampOrNull(); - } - - @Test - public void testStatementGetStatementTimeout() { - subject.statementSetStatementTimeout(Duration.newBuilder().setSeconds(1L).build()); - when(connection.hasStatementTimeout()).thenReturn(true); - subject.statementShowStatementTimeout(); - verify(connection, atLeastOnce()).getStatementTimeout(any(TimeUnit.class)); - subject.statementSetStatementTimeout(Duration.getDefaultInstance()); - when(connection.hasStatementTimeout()).thenReturn(false); - } - - @Test - public void testStatementRollback() { - subject.statementRollback(); - verify(connection).rollback(); - } - - @Test - public void testStatementSetAutocommit() { - subject.statementSetAutocommit(Boolean.TRUE); - verify(connection).setAutocommit(true); - subject.statementSetAutocommit(Boolean.FALSE); - verify(connection).setAutocommit(false); - } - - @Test - public void testStatementSetAutocommitDmlMode() { - subject.statementSetAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - verify(connection).setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - subject.statementSetAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL); - verify(connection).setAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL); - } - - @Test - public void testStatementSetReadOnly() { - subject.statementSetReadOnly(Boolean.TRUE); - verify(connection).setReadOnly(true); - subject.statementSetReadOnly(Boolean.FALSE); - verify(connection).setReadOnly(false); - } - - @Test - public void testStatementSetReadOnlyStaleness() { - subject.statementSetReadOnlyStaleness(TimestampBound.strong()); - verify(connection).setReadOnlyStaleness(TimestampBound.strong()); - - subject.statementSetReadOnlyStaleness( - TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); - verify(connection) - .setReadOnlyStaleness( - TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); - - subject.statementSetReadOnlyStaleness( - TimestampBound.ofMinReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); - verify(connection) - .setReadOnlyStaleness( - TimestampBound.ofReadTimestamp(Timestamp.parseTimestamp("2018-10-31T10:11:12.123Z"))); - - subject.statementSetReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - verify(connection).setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - - subject.statementSetReadOnlyStaleness( - TimestampBound.ofMaxStaleness(20L, TimeUnit.MILLISECONDS)); - verify(connection) - .setReadOnlyStaleness(TimestampBound.ofMaxStaleness(20L, TimeUnit.MILLISECONDS)); - } - - @Test - public void testStatementSetOptimizerVersion() { - subject.statementSetOptimizerVersion("1"); - verify(connection).setOptimizerVersion("1"); - subject.statementSetOptimizerVersion(""); - verify(connection).setOptimizerVersion(""); - subject.statementSetOptimizerVersion("LATEST"); - verify(connection).setOptimizerVersion("LATEST"); - } - - @Test - public void testStatementSetStatementTimeout() { - subject.statementSetStatementTimeout(Duration.newBuilder().setNanos(100).build()); - verify(connection).setStatementTimeout(100L, TimeUnit.NANOSECONDS); - } - - @Test - public void testStatementSetTransactionMode() { - subject.statementSetTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - verify(connection).setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION); - subject.statementSetTransactionMode(TransactionMode.READ_WRITE_TRANSACTION); - verify(connection).setTransactionMode(TransactionMode.READ_WRITE_TRANSACTION); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java deleted file mode 100644 index 51aa8abe1c4f..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithNoParametersTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2019 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.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import java.util.concurrent.TimeUnit; -import org.junit.Test; - -public class ConnectionStatementWithNoParametersTest { - private final StatementParser parser = StatementParser.INSTANCE; - - @Test - public void testExecuteGetAutocommit() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable autocommit")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowAutocommit()).thenCallRealMethod(); - statement.getClientSideStatement().execute(executor, "show variable autocommit"); - verify(connection, times(1)).isAutocommit(); - } - - @Test - public void testExecuteGetReadOnly() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable readonly")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowReadOnly()).thenCallRealMethod(); - statement.getClientSideStatement().execute(executor, "show variable readonly"); - verify(connection, times(1)).isReadOnly(); - } - - @Test - public void testExecuteGetAutocommitDmlMode() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable autocommit_dml_mode")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowAutocommitDmlMode()).thenCallRealMethod(); - when(connection.getAutocommitDmlMode()).thenReturn(AutocommitDmlMode.TRANSACTIONAL); - statement.getClientSideStatement().execute(executor, "show variable autocommit_dml_mode"); - verify(connection, times(1)).getAutocommitDmlMode(); - } - - @Test - public void testExecuteGetStatementTimeout() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable statement_timeout")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowStatementTimeout()).thenCallRealMethod(); - when(connection.hasStatementTimeout()).thenReturn(true); - when(connection.getStatementTimeout(TimeUnit.NANOSECONDS)).thenReturn(1L); - statement.getClientSideStatement().execute(executor, "show variable statement_timeout"); - verify(connection, times(2)).getStatementTimeout(TimeUnit.NANOSECONDS); - } - - @Test - public void testExecuteGetReadTimestamp() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable read_timestamp")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowReadTimestamp()).thenCallRealMethod(); - when(connection.getReadTimestampOrNull()).thenReturn(Timestamp.now()); - statement.getClientSideStatement().execute(executor, "show variable read_timestamp"); - verify(connection, times(1)).getReadTimestampOrNull(); - } - - @Test - public void testExecuteGetCommitTimestamp() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable commit_timestamp")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowCommitTimestamp()).thenCallRealMethod(); - when(connection.getCommitTimestampOrNull()).thenReturn(Timestamp.now()); - statement.getClientSideStatement().execute(executor, "show variable commit_timestamp"); - verify(connection, times(1)).getCommitTimestampOrNull(); - } - - @Test - public void testExecuteGetReadOnlyStaleness() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable read_only_staleness")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowReadOnlyStaleness()).thenCallRealMethod(); - when(connection.getReadOnlyStaleness()).thenReturn(TimestampBound.strong()); - statement.getClientSideStatement().execute(executor, "show variable read_only_staleness"); - verify(connection, times(1)).getReadOnlyStaleness(); - } - - @Test - public void testExecuteGetOptimizerVersion() throws Exception { - ParsedStatement statement = parser.parse(Statement.of("show variable optimizer_version")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementShowOptimizerVersion()).thenCallRealMethod(); - when(connection.getOptimizerVersion()).thenReturn("1"); - statement.getClientSideStatement().execute(executor, "show variable optimizer_version"); - verify(connection, times(1)).getOptimizerVersion(); - } - - @Test - public void testExecuteBegin() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("begin")); - for (String statement : subject.getClientSideStatement().getExampleStatements()) { - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementBeginTransaction()).thenCallRealMethod(); - subject.getClientSideStatement().execute(executor, statement); - verify(connection, times(1)).beginTransaction(); - } - } - - @Test - public void testExecuteCommit() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("commit")); - for (String statement : subject.getClientSideStatement().getExampleStatements()) { - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementCommit()).thenCallRealMethod(); - subject.getClientSideStatement().execute(executor, statement); - verify(connection, times(1)).commit(); - } - } - - @Test - public void testExecuteRollback() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("rollback")); - for (String statement : subject.getClientSideStatement().getExampleStatements()) { - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementRollback()).thenCallRealMethod(); - subject.getClientSideStatement().execute(executor, statement); - verify(connection, times(1)).rollback(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java deleted file mode 100644 index b9ebf1edae42..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionStatementWithOneParameterTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2019 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.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.protobuf.Duration; -import java.util.concurrent.TimeUnit; -import org.junit.Test; - -public class ConnectionStatementWithOneParameterTest { - private final StatementParser parser = StatementParser.INSTANCE; - - @Test - public void testExecuteSetAutcommit() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set autocommit = true")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetAutocommit(any(Boolean.class))).thenCallRealMethod(); - for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { - subject - .getClientSideStatement() - .execute(executor, String.format("set autocommit = %s", mode)); - verify(connection, times(1)).setAutocommit(mode); - } - } - - @Test - public void testExecuteSetReadOnly() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set readonly = true")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetReadOnly(any(Boolean.class))).thenCallRealMethod(); - for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { - subject - .getClientSideStatement() - .execute(executor, String.format("set readonly = %s", Boolean.toString(mode))); - verify(connection, times(1)).setReadOnly(mode); - } - } - - @Test - public void testExecuteSetAutcommitDmlMode() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set autocommit_dml_mode='foo'")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetAutocommitDmlMode(any(AutocommitDmlMode.class))).thenCallRealMethod(); - for (AutocommitDmlMode mode : AutocommitDmlMode.values()) { - subject - .getClientSideStatement() - .execute(executor, String.format("set autocommit_dml_mode='%s'", mode.name())); - verify(connection, times(1)).setAutocommitDmlMode(mode); - } - } - - @Test - public void testExecuteSetStatementTimeout() throws Exception { - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.statementSetStatementTimeout(any(Duration.class))).thenCallRealMethod(); - ConnectionImpl connection = mock(ConnectionImpl.class); - when(executor.getConnection()).thenReturn(connection); - for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { - for (Long val : new Long[] {1L, 100L, 999L}) { - ParsedStatement subject = - parser.parse( - Statement.of( - String.format( - "set statement_timeout='%d%s'", - val, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit)))); - subject - .getClientSideStatement() - .execute( - executor, - String.format( - "set statement_timeout='%d%s'", - val, ReadOnlyStalenessUtil.getTimeUnitAbbreviation(unit))); - verify(connection, times(1)).setStatementTimeout(val, unit); - } - } - ParsedStatement subject = - parser.parse(Statement.of(String.format("set statement_timeout=null"))); - subject.getClientSideStatement().execute(executor, String.format("set statement_timeout=null")); - verify(connection, times(1)).clearStatementTimeout(); - } - - @Test - public void testExecuteSetReadOnlyStaleness() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set read_only_staleness='foo'")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetReadOnlyStaleness(any(TimestampBound.class))).thenCallRealMethod(); - for (TimestampBound val : - new TimestampBound[] { - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(Timestamp.now()), - TimestampBound.ofMinReadTimestamp(Timestamp.now()), - TimestampBound.ofExactStaleness(1000L, TimeUnit.SECONDS), - TimestampBound.ofMaxStaleness(2000L, TimeUnit.MICROSECONDS) - }) { - subject - .getClientSideStatement() - .execute( - executor, String.format("set read_only_staleness='%s'", timestampBoundToString(val))); - verify(connection, times(1)).setReadOnlyStaleness(val); - } - } - - private String timestampBoundToString(TimestampBound staleness) { - switch (staleness.getMode()) { - case STRONG: - return "strong"; - case READ_TIMESTAMP: - return "read_timestamp " + staleness.getReadTimestamp().toString(); - case MIN_READ_TIMESTAMP: - return "min_read_timestamp " + staleness.getMinReadTimestamp().toString(); - case EXACT_STALENESS: - return "exact_staleness " + staleness.getExactStaleness(TimeUnit.SECONDS) + "s"; - case MAX_STALENESS: - return "max_staleness " + staleness.getMaxStaleness(TimeUnit.MICROSECONDS) + "us"; - default: - throw new IllegalStateException("Unknown mode: " + staleness.getMode()); - } - } - - @Test - public void testExecuteSetOptimizerVersion() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set optimizer_version='foo'")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetOptimizerVersion(any(String.class))).thenCallRealMethod(); - for (String version : new String[] {"1", "200", "", "LATEST"}) { - subject - .getClientSideStatement() - .execute(executor, String.format("set optimizer_version='%s'", version)); - verify(connection, times(1)).setOptimizerVersion(version); - } - } - - @Test - public void testExecuteSetTransaction() throws Exception { - ParsedStatement subject = parser.parse(Statement.of("set transaction read_only")); - ConnectionImpl connection = mock(ConnectionImpl.class); - ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); - when(executor.getConnection()).thenReturn(connection); - when(executor.statementSetTransactionMode(any(TransactionMode.class))).thenCallRealMethod(); - for (TransactionMode mode : TransactionMode.values()) { - subject - .getClientSideStatement() - .execute(executor, String.format("set transaction %s", mode.getStatementString())); - verify(connection, times(1)).setTransactionMode(mode); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java deleted file mode 100644 index d99b9a738f49..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2020 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 com.google.common.truth.Truth.assertThat; - -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.Statement; -import com.google.spanner.v1.ExecuteSqlRequest; -import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; -import java.sql.SQLException; -import org.junit.Test; - -public class ConnectionTest extends AbstractMockServerTest { - @Test - public void testDefaultOptimizerVersion() throws SQLException { - try (Connection connection = createConnection()) { - try (ResultSet rs = - connection.executeQuery(Statement.of("SHOW VARIABLE OPTIMIZER_VERSION"))) { - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); - assertThat(rs.next()).isFalse(); - } - } - } - - @Test - public void testUseOptimizerVersionFromEnvironment() throws SQLException { - try { - SpannerOptions.useEnvironment( - new SpannerOptions.SpannerEnvironment() { - @Override - public String getOptimizerVersion() { - return "20"; - } - }); - try (Connection connection = createConnection()) { - // Do a query and verify that the version from the environment is used. - try (ResultSet rs = connection.executeQuery(SELECT_COUNT_STATEMENT)) { - assertThat(rs.next()).isTrue(); - assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); - assertThat(rs.next()).isFalse(); - // Verify query options from the environment. - ExecuteSqlRequest request = getLastExecuteSqlRequest(); - assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); - } - // Now set one of the query options on the connection. That option should be used in - // combination with the other option from the environment. - connection.execute(Statement.of("SET OPTIMIZER_VERSION='30'")); - try (ResultSet rs = connection.executeQuery(SELECT_COUNT_STATEMENT)) { - assertThat(rs.next()).isTrue(); - assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); - assertThat(rs.next()).isFalse(); - - ExecuteSqlRequest request = getLastExecuteSqlRequest(); - // Optimizer version should come from the connection. - assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("30"); - } - // Now specify options directly for the query. These should override both the environment - // and what is set on the connection. - try (ResultSet rs = - connection.executeQuery( - Statement.newBuilder(SELECT_COUNT_STATEMENT.getSql()) - .withQueryOptions( - QueryOptions.newBuilder() - .setOptimizerVersion("user-defined-version") - .build()) - .build())) { - assertThat(rs.next()).isTrue(); - assertThat(rs.getLong(0)).isEqualTo(COUNT_BEFORE_INSERT); - assertThat(rs.next()).isFalse(); - - ExecuteSqlRequest request = getLastExecuteSqlRequest(); - // Optimizer version should come from the query. - assertThat(request.getQueryOptions().getOptimizerVersion()) - .isEqualTo("user-defined-version"); - } - } - } finally { - SpannerOptions.useDefaultEnvironment(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java deleted file mode 100644 index 268d4a1a09da..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/CredentialsServiceTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; - -import com.google.auth.oauth2.GoogleCredentials; -import com.google.auth.oauth2.ServiceAccountCredentials; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import java.io.FileInputStream; -import java.io.IOException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for reading and parsing test key files and getting service accounts. */ -@RunWith(JUnit4.class) -public class CredentialsServiceTest { - private static final String FILE_TEST_PATH = - CredentialsServiceTest.class.getResource("test-key.json").getFile(); - private static final String APP_DEFAULT_FILE_TEST_PATH = - CredentialsServiceTest.class.getResource("test-key-app-default.json").getFile(); - - private static final String TEST_PROJECT_ID = "test-project"; - private static final String APP_DEFAULT_PROJECT_ID = "app-default-test-project"; - - private final CredentialsService service = - new CredentialsService() { - - @Override - GoogleCredentials internalGetApplicationDefault() throws IOException { - // Read application default credentials directly from a specific file instead of actually - // fetching the default from the environment. - return GoogleCredentials.fromStream(new FileInputStream(APP_DEFAULT_FILE_TEST_PATH)); - } - }; - - @Test - public void testCreateCredentialsDefault() throws Exception { - ServiceAccountCredentials credentials = - (ServiceAccountCredentials) service.createCredentials(null); - assertThat(credentials.getProjectId(), is(equalTo(APP_DEFAULT_PROJECT_ID))); - } - - @Test - public void testCreateCredentialsFile() throws IOException { - ServiceAccountCredentials credentials = - (ServiceAccountCredentials) service.createCredentials(FILE_TEST_PATH); - assertThat(credentials.getProjectId(), is(equalTo(TEST_PROJECT_ID))); - } - - @Test(expected = SpannerException.class) - public void testCreateCredentialsInvalidFile() { - service.createCredentials("invalid_file_path.json"); - } - - @Test - public void testCreateCredentialsInvalidCloudStorage() { - try { - service.createCredentials("gs://test-bucket/test-blob"); - fail("missing expected exception"); - } catch (SpannerException e) { - assertThat(e.getErrorCode(), is(equalTo(ErrorCode.INVALID_ARGUMENT))); - assertThat(e.getCause().getMessage(), is(equalTo(CredentialsService.GCS_NOT_SUPPORTED_MSG))); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java deleted file mode 100644 index 76a5cc5bf33d..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlBatchTest.java +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ReadContext; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerBatchUpdateException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ConnectionImpl.InternalMetadataQuery; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; -import com.google.protobuf.Timestamp; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import io.grpc.Status; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.ArgumentMatcher; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class DdlBatchTest { - - @Rule public ExpectedException exception = ExpectedException.none(); - - private DdlClient createDefaultMockDdlClient() { - return createDefaultMockDdlClient(false, 0L); - } - - private DdlClient createDefaultMockDdlClient(boolean exceptionOnGetResult) { - return createDefaultMockDdlClient(exceptionOnGetResult, 0L); - } - - private DdlClient createDefaultMockDdlClient(long waitForMillis) { - return createDefaultMockDdlClient(false, waitForMillis); - } - - private DdlClient createDefaultMockDdlClient( - boolean exceptionOnGetResult, final long waitForMillis) { - try { - DdlClient ddlClient = mock(DdlClient.class); - @SuppressWarnings("unchecked") - final OperationFuture operation = - mock(OperationFuture.class); - if (waitForMillis > 0L) { - when(operation.get()) - .thenAnswer( - new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(waitForMillis); - return null; - } - }); - } else if (exceptionOnGetResult) { - when(operation.get()) - .thenThrow( - SpannerExceptionFactory.newSpannerException( - ErrorCode.UNKNOWN, "ddl statement failed")); - } else { - when(operation.get()).thenReturn(null); - } - UpdateDatabaseDdlMetadata.Builder metadataBuilder = UpdateDatabaseDdlMetadata.newBuilder(); - if (!exceptionOnGetResult) { - metadataBuilder.addCommitTimestamps( - Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L)); - } - ApiFuture metadataFuture = - ApiFutures.immediateFuture(metadataBuilder.build()); - when(operation.getMetadata()).thenReturn(metadataFuture); - when(ddlClient.executeDdl(anyString())).thenReturn(operation); - when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); - return ddlClient; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private DdlBatch createSubject() { - return createSubject(createDefaultMockDdlClient()); - } - - private DdlBatch createSubject(DdlClient ddlClient) { - return createSubject(ddlClient, mock(DatabaseClient.class)); - } - - private DdlBatch createSubject(DdlClient ddlClient, DatabaseClient dbClient) { - return DdlBatch.newBuilder() - .setDdlClient(ddlClient) - .setDatabaseClient(dbClient) - .withStatementExecutor(new StatementExecutor()) - .build(); - } - - @Test - public void testExecuteQuery() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.executeQuery(mock(ParsedStatement.class), AnalyzeMode.NONE); - } - - @Test - public void testExecuteMetadataQuery() { - Statement statement = Statement.of("SELECT * FROM INFORMATION_SCHEMA.TABLES"); - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.isQuery()).thenReturn(true); - when(parsedStatement.getStatement()).thenReturn(statement); - DatabaseClient dbClient = mock(DatabaseClient.class); - ReadContext singleUse = mock(ReadContext.class); - ResultSet resultSet = mock(ResultSet.class); - when(singleUse.executeQuery(statement)).thenReturn(resultSet); - when(dbClient.singleUse()).thenReturn(singleUse); - DdlBatch batch = createSubject(createDefaultMockDdlClient(), dbClient); - assertThat( - batch - .executeQuery(parsedStatement, AnalyzeMode.NONE, InternalMetadataQuery.INSTANCE) - .hashCode(), - is(equalTo(resultSet.hashCode()))); - } - - @Test - public void testExecuteUpdate() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.executeUpdate(mock(ParsedStatement.class)); - } - - @Test - public void testGetCommitTimestamp() { - DdlBatch batch = createSubject(); - batch.runBatch(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.getCommitTimestamp(); - } - - @Test - public void testGetReadTimestamp() { - DdlBatch batch = createSubject(); - batch.runBatch(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.getReadTimestamp(); - } - - @Test - public void testWrite() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.write(Mutation.newInsertBuilder("foo").build()); - } - - @Test - public void testWriteIterable() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.write(Arrays.asList(Mutation.newInsertBuilder("foo").build())); - } - - @Test - public void testIsReadOnly() { - DdlBatch batch = createSubject(); - assertThat(batch.isReadOnly(), is(false)); - } - - @Test - public void testGetStateAndIsActive() { - DdlBatch batch = createSubject(); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - batch.runBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.RAN)); - assertThat(batch.isActive(), is(false)); - - batch = createSubject(); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - batch.abortBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); - assertThat(batch.isActive(), is(false)); - - DdlClient client = mock(DdlClient.class); - doThrow(SpannerException.class).when(client).executeDdl(anyListOf(String.class)); - batch = createSubject(client); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); - when(statement.getType()).thenReturn(StatementType.DDL); - batch.executeDdl(statement); - boolean exception = false; - try { - batch.runBatch(); - } catch (SpannerException e) { - exception = true; - } - assertThat(exception, is(true)); - assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); - assertThat(batch.isActive(), is(false)); - } - - private static IsListOfStringsWithSize isEmptyListOfStrings() { - return new IsListOfStringsWithSize(0); - } - - private static IsListOfStringsWithSize isListOfStringsWithSize(int size) { - return new IsListOfStringsWithSize(size); - } - - private static class IsListOfStringsWithSize extends ArgumentMatcher> { - private final int size; - - private IsListOfStringsWithSize(int size) { - this.size = size; - } - - @SuppressWarnings("unchecked") - @Override - public boolean matches(Object list) { - return ((List) list).size() == size; - } - } - - @Test - public void testRunBatch() { - DdlClient client = createDefaultMockDdlClient(); - DdlBatch batch = createSubject(client); - batch.runBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.RAN)); - verify(client, never()).executeDdl(anyString()); - verify(client, never()).executeDdl(argThat(isEmptyListOfStrings())); - - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.DDL); - when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); - - client = createDefaultMockDdlClient(); - batch = createSubject(client); - batch.executeDdl(statement); - batch.runBatch(); - verify(client).executeDdl(argThat(isListOfStringsWithSize(1))); - - client = createDefaultMockDdlClient(); - batch = createSubject(client); - batch.executeDdl(statement); - batch.executeDdl(statement); - batch.runBatch(); - verify(client).executeDdl(argThat(isListOfStringsWithSize(2))); - assertThat(batch.getState(), is(UnitOfWorkState.RAN)); - boolean exception = false; - try { - batch.runBatch(); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { - throw e; - } - exception = true; - } - assertThat(exception, is(true)); - assertThat(batch.getState(), is(UnitOfWorkState.RAN)); - exception = false; - try { - batch.executeDdl(statement); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { - throw e; - } - exception = true; - } - assertThat(exception, is(true)); - exception = false; - try { - batch.executeDdl(statement); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { - throw e; - } - exception = true; - } - assertThat(exception, is(true)); - - client = createDefaultMockDdlClient(true); - batch = createSubject(client); - batch.executeDdl(statement); - batch.executeDdl(statement); - exception = false; - try { - batch.runBatch(); - } catch (SpannerException e) { - exception = true; - } - assertThat(exception, is(true)); - assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); - verify(client).executeDdl(argThat(isListOfStringsWithSize(2))); - } - - @Test - public void testUpdateCount() throws InterruptedException, ExecutionException { - DdlClient client = mock(DdlClient.class); - UpdateDatabaseDdlMetadata metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps( - Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L - 1L)) - .addCommitTimestamps( - Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L)) - .addAllStatements(Arrays.asList("CREATE TABLE FOO", "CREATE TABLE BAR")) - .build(); - ApiFuture metadataFuture = ApiFutures.immediateFuture(metadata); - @SuppressWarnings("unchecked") - OperationFuture operationFuture = mock(OperationFuture.class); - when(operationFuture.get()).thenReturn(null); - when(operationFuture.getMetadata()).thenReturn(metadataFuture); - when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture); - DdlBatch batch = - DdlBatch.newBuilder() - .withStatementExecutor(new StatementExecutor()) - .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) - .build(); - batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); - batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE BAR"))); - long[] updateCounts = batch.runBatch(); - assertThat(updateCounts.length, is(equalTo(2))); - assertThat(updateCounts[0], is(equalTo(1L))); - assertThat(updateCounts[1], is(equalTo(1L))); - } - - @Test - public void testFailedUpdateCount() throws InterruptedException, ExecutionException { - DdlClient client = mock(DdlClient.class); - UpdateDatabaseDdlMetadata metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps( - Timestamp.newBuilder().setSeconds(System.currentTimeMillis() * 1000L - 1L)) - .addAllStatements(Arrays.asList("CREATE TABLE FOO", "CREATE TABLE INVALID_TABLE")) - .build(); - ApiFuture metadataFuture = ApiFutures.immediateFuture(metadata); - @SuppressWarnings("unchecked") - OperationFuture operationFuture = mock(OperationFuture.class); - when(operationFuture.get()) - .thenThrow( - new ExecutionException( - "ddl statement failed", Status.INVALID_ARGUMENT.asRuntimeException())); - when(operationFuture.getMetadata()).thenReturn(metadataFuture); - when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture); - DdlBatch batch = - DdlBatch.newBuilder() - .withStatementExecutor(new StatementExecutor()) - .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) - .build(); - batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); - batch.executeDdl(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE INVALID_TABLE"))); - try { - batch.runBatch(); - fail("missing expected exception"); - } catch (SpannerBatchUpdateException e) { - assertThat(e.getUpdateCounts().length, is(equalTo(2))); - assertThat(e.getUpdateCounts()[0], is(equalTo(1L))); - assertThat(e.getUpdateCounts()[1], is(equalTo(0L))); - } - } - - @Test - public void testAbort() { - DdlClient client = createDefaultMockDdlClient(); - DdlBatch batch = createSubject(client); - batch.abortBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); - verify(client, never()).executeDdl(anyString()); - verify(client, never()).executeDdl(anyListOf(String.class)); - - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.DDL); - when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); - - client = createDefaultMockDdlClient(); - batch = createSubject(client); - batch.executeDdl(statement); - batch.abortBatch(); - verify(client, never()).executeDdl(anyListOf(String.class)); - - client = createDefaultMockDdlClient(); - batch = createSubject(client); - batch.executeDdl(statement); - batch.executeDdl(statement); - batch.abortBatch(); - verify(client, never()).executeDdl(anyListOf(String.class)); - - client = createDefaultMockDdlClient(); - batch = createSubject(client); - batch.executeDdl(statement); - batch.executeDdl(statement); - batch.abortBatch(); - verify(client, never()).executeDdl(anyListOf(String.class)); - boolean exception = false; - try { - batch.runBatch(); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.FAILED_PRECONDITION) { - throw e; - } - exception = true; - } - assertThat(exception, is(true)); - verify(client, never()).executeDdl(anyListOf(String.class)); - } - - @Test - public void testCancel() { - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.DDL); - when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); - - DdlClient client = createDefaultMockDdlClient(10000L); - final DdlBatch batch = createSubject(client); - batch.executeDdl(statement); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - batch.cancel(); - } - }, - 100, - TimeUnit.MILLISECONDS); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - batch.runBatch(); - } - - @Test - public void testCommit() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.commit(); - } - - @Test - public void testRollback() { - DdlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.rollback(); - } - - @Test - public void testExtractUpdateCounts() { - DdlBatch batch = createSubject(); - UpdateDatabaseDdlMetadata metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) - .addStatements("CREATE TABLE FOO") - .addStatements("CREATE TABLE BAR") - .addStatements("CREATE TABLE BAZ") - .build(); - long[] updateCounts = batch.extractUpdateCounts(metadata); - assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 0L}))); - - metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) - .addStatements("CREATE TABLE FOO") - .addStatements("CREATE TABLE BAR") - .addStatements("CREATE TABLE BAZ") - .build(); - updateCounts = batch.extractUpdateCounts(metadata); - assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); - - metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) - .addStatements("CREATE TABLE FOO") - .addStatements("CREATE TABLE BAR") - .addStatements("CREATE TABLE BAZ") - .build(); - updateCounts = batch.extractUpdateCounts(metadata); - assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); - - // This is not something Cloud Spanner should return, but the method can handle it. - metadata = - UpdateDatabaseDdlMetadata.newBuilder() - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(1000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(2000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(3000L).build()) - .addCommitTimestamps(Timestamp.newBuilder().setSeconds(4000L).build()) - .addStatements("CREATE TABLE FOO") - .addStatements("CREATE TABLE BAR") - .addStatements("CREATE TABLE BAZ") - .build(); - updateCounts = batch.extractUpdateCounts(metadata); - assertThat(updateCounts, is(equalTo(new long[] {1L, 1L, 1L}))); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java deleted file mode 100644 index 8ec9f600d31b..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlClientTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019 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.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.spanner.DatabaseAdminClient; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DdlClientTest { - - private final String instanceId = "test-instance"; - private final String databaseId = "test-database"; - - private DdlClient createSubject(DatabaseAdminClient client) { - return DdlClient.newBuilder() - .setInstanceId(instanceId) - .setDatabaseName(databaseId) - .setDatabaseAdminClient(client) - .build(); - } - - @Test - public void testExecuteDdl() throws InterruptedException, ExecutionException { - DatabaseAdminClient client = mock(DatabaseAdminClient.class); - @SuppressWarnings("unchecked") - OperationFuture operation = mock(OperationFuture.class); - when(operation.get()).thenReturn(null); - when(client.updateDatabaseDdl( - eq(instanceId), eq(databaseId), anyListOf(String.class), isNull(String.class))) - .thenReturn(operation); - DdlClient subject = createSubject(client); - String ddl = "CREATE TABLE FOO"; - subject.executeDdl(ddl); - verify(client).updateDatabaseDdl(instanceId, databaseId, Arrays.asList(ddl), null); - - subject = createSubject(client); - List ddlList = Arrays.asList("CREATE TABLE FOO", "DROP TABLE FOO"); - subject.executeDdl(ddlList); - verify(client).updateDatabaseDdl(instanceId, databaseId, ddlList, null); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java deleted file mode 100644 index 533c417b47b0..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DirectExecuteResultSetTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.ResultSets; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.Type.StructField; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DirectExecuteResultSetTest { - - private DirectExecuteResultSet createSubject() { - ResultSet delegate = - ResultSets.forRows( - Type.struct(StructField.of("test", Type.int64())), - Arrays.asList(Struct.newBuilder().set("test").to(1L).build())); - return DirectExecuteResultSet.ofResultSet(delegate); - } - - @Test - public void testMethodCallBeforeNext() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = - Arrays.asList("getStats", "next", "close", "ofResultSet", "equals", "hashCode"); - DirectExecuteResultSet subject = createSubject(); - callMethods(subject, excludedMethods, IllegalStateException.class); - } - - @Test - public void testMethodCallAfterClose() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = - Arrays.asList( - "getStats", - "next", - "close", - "getType", - "getColumnCount", - "getColumnIndex", - "getColumnType", - "ofResultSet", - "equals", - "hashCode"); - DirectExecuteResultSet subject = createSubject(); - subject.next(); - subject.close(); - callMethods(subject, excludedMethods, IllegalStateException.class); - } - - @Test - public void testMethodCallAfterNextHasReturnedFalse() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = - Arrays.asList( - "getStats", - "next", - "close", - "getType", - "getColumnCount", - "getColumnIndex", - "getColumnType", - "ofResultSet", - "equals", - "hashCode"); - DirectExecuteResultSet subject = createSubject(); - subject.next(); - subject.next(); - callMethods(subject, excludedMethods, IndexOutOfBoundsException.class); - } - - private void callMethods( - DirectExecuteResultSet subject, - List excludedMethods, - Class expectedException) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - for (Method method : DirectExecuteResultSet.class.getDeclaredMethods()) { - if (Modifier.isPublic(method.getModifiers()) && !excludedMethods.contains(method.getName())) { - boolean exception = false; - int numberOfParameters = method.getParameterTypes().length; - Class firstParameterType = null; - if (numberOfParameters == 1) { - firstParameterType = method.getParameterTypes()[0]; - } - try { - switch (numberOfParameters) { - case 0: - method.invoke(subject); - break; - case 1: - if (firstParameterType == String.class) { - method.invoke(subject, "test"); - } else if (firstParameterType == int.class) { - method.invoke(subject, 0); - } else { - fail("unknown parameter type"); - } - break; - default: - fail("method with more than 1 parameter is unknown"); - } - } catch (InvocationTargetException e) { - if (e.getCause().getClass().equals(expectedException)) { - // expected - exception = true; - } else { - throw e; - } - } - assertThat( - method.getName() + " did not throw an IllegalStateException", exception, is(true)); - } - } - } - - @Test - public void testValidMethodCall() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - ResultSet delegate = mock(ResultSet.class); - when(delegate.next()).thenReturn(true, true, false); - DirectExecuteResultSet subject = DirectExecuteResultSet.ofResultSet(delegate); - subject.next(); - - subject.getBoolean(0); - verify(delegate).getBoolean(0); - subject.getBoolean("test0"); - verify(delegate).getBoolean("test0"); - subject.getBooleanArray(1); - verify(delegate).getBooleanArray(1); - subject.getBooleanArray("test1"); - verify(delegate).getBooleanArray("test1"); - subject.getBooleanList(2); - verify(delegate).getBooleanList(2); - subject.getBooleanList("test2"); - verify(delegate).getBooleanList("test2"); - - subject.getBytes(0); - verify(delegate).getBytes(0); - subject.getBytes("test0"); - verify(delegate).getBytes("test0"); - subject.getBytesList(2); - verify(delegate).getBytesList(2); - subject.getBytesList("test2"); - verify(delegate).getBytesList("test2"); - - subject.getDate(0); - verify(delegate).getDate(0); - subject.getDate("test0"); - verify(delegate).getDate("test0"); - subject.getDateList(2); - verify(delegate).getDateList(2); - subject.getDateList("test2"); - verify(delegate).getDateList("test2"); - - subject.getDouble(0); - verify(delegate).getDouble(0); - subject.getDouble("test0"); - verify(delegate).getDouble("test0"); - subject.getDoubleArray(1); - verify(delegate).getDoubleArray(1); - subject.getDoubleArray("test1"); - verify(delegate).getDoubleArray("test1"); - subject.getDoubleList(2); - verify(delegate).getDoubleList(2); - subject.getDoubleList("test2"); - verify(delegate).getDoubleList("test2"); - - subject.getLong(0); - verify(delegate).getLong(0); - subject.getLong("test0"); - verify(delegate).getLong("test0"); - subject.getLongArray(1); - verify(delegate).getLongArray(1); - subject.getLongArray("test1"); - verify(delegate).getLongArray("test1"); - subject.getLongList(2); - verify(delegate).getLongList(2); - subject.getLongList("test2"); - verify(delegate).getLongList("test2"); - - subject.getString(0); - verify(delegate).getString(0); - subject.getString("test0"); - verify(delegate).getString("test0"); - subject.getStringList(2); - verify(delegate).getStringList(2); - subject.getStringList("test2"); - verify(delegate).getStringList("test2"); - - subject.getStructList(0); - subject.getStructList("test0"); - - subject.getTimestamp(0); - verify(delegate).getTimestamp(0); - subject.getTimestamp("test0"); - verify(delegate).getTimestamp("test0"); - subject.getTimestampList(2); - verify(delegate).getTimestampList(2); - subject.getTimestampList("test2"); - verify(delegate).getTimestampList("test2"); - - subject.getColumnCount(); - verify(delegate).getColumnCount(); - subject.getColumnIndex("test"); - verify(delegate).getColumnIndex("test"); - subject.getColumnType(100); - verify(delegate).getColumnType(100); - subject.getColumnType("test"); - verify(delegate).getColumnType("test"); - subject.getCurrentRowAsStruct(); - verify(delegate).getCurrentRowAsStruct(); - subject.getType(); - verify(delegate).getType(); - subject.isNull(50); - verify(delegate).isNull(50); - subject.isNull("test"); - verify(delegate).isNull("test"); - - while (subject.next()) { - // ignore - } - subject.getStats(); - verify(delegate).getStats(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java deleted file mode 100644 index b8a96cda9635..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DmlBatchTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; -import java.util.Arrays; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DmlBatchTest { - private final ParsedStatement statement1 = - StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2")); - private final ParsedStatement statement2 = - StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=2 WHERE BAZ=3")); - - @Rule public ExpectedException exception = ExpectedException.none(); - - private DmlBatch createSubject() { - UnitOfWork transaction = mock(UnitOfWork.class); - when(transaction.executeBatchUpdate(Arrays.asList(statement1, statement2))) - .thenReturn(new long[] {3L, 5L}); - return createSubject(transaction); - } - - private DmlBatch createSubject(UnitOfWork transaction) { - return DmlBatch.newBuilder() - .setTransaction(transaction) - .withStatementExecutor(new StatementExecutor()) - .build(); - } - - @Test - public void testExecuteQuery() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.executeQuery(mock(ParsedStatement.class), AnalyzeMode.NONE); - } - - @Test - public void testExecuteDdl() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.executeDdl(mock(ParsedStatement.class)); - } - - @Test - public void testGetReadTimestamp() { - DmlBatch batch = createSubject(); - batch.runBatch(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.getReadTimestamp(); - } - - @Test - public void testIsReadOnly() { - DmlBatch batch = createSubject(); - assertThat(batch.isReadOnly(), is(false)); - } - - @Test - public void testGetCommitTimestamp() { - DmlBatch batch = createSubject(); - batch.runBatch(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.getCommitTimestamp(); - } - - @Test - public void testWrite() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.write(Mutation.newInsertBuilder("foo").build()); - } - - @Test - public void testWriteIterable() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.write(Arrays.asList(Mutation.newInsertBuilder("foo").build())); - } - - @Test - public void testGetStateAndIsActive() { - DmlBatch batch = createSubject(); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - batch.runBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.RAN)); - assertThat(batch.isActive(), is(false)); - - batch = createSubject(); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - batch.abortBatch(); - assertThat(batch.getState(), is(UnitOfWorkState.ABORTED)); - assertThat(batch.isActive(), is(false)); - - UnitOfWork tx = mock(UnitOfWork.class); - doThrow(SpannerException.class).when(tx).executeBatchUpdate(anyListOf(ParsedStatement.class)); - batch = createSubject(tx); - assertThat(batch.getState(), is(UnitOfWorkState.STARTED)); - assertThat(batch.isActive(), is(true)); - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getStatement()).thenReturn(Statement.of("UPDATE TEST SET COL1=2")); - when(statement.getSqlWithoutComments()).thenReturn("UPDATE TEST SET COL1=2"); - when(statement.getType()).thenReturn(StatementType.UPDATE); - batch.executeUpdate(statement); - boolean exception = false; - try { - batch.runBatch(); - } catch (SpannerException e) { - exception = true; - } - assertThat(exception, is(true)); - assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED)); - assertThat(batch.isActive(), is(false)); - } - - @Test - public void testCommit() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.commit(); - } - - @Test - public void testRollback() { - DmlBatch batch = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - batch.rollback(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java deleted file mode 100644 index 77b41e9d04f7..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DurationConverterTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.DurationConverter; -import com.google.protobuf.Duration; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DurationConverterTest { - - @Test - public void testConvert() throws CompileException { - String allowedValues = ReadOnlyStalenessConverterTest.getAllowedValues(DurationConverter.class); - assertThat(allowedValues, is(notNullValue())); - DurationConverter converter = new DurationConverter(allowedValues); - assertThat( - converter.convert("'100ms'"), - is( - equalTo( - Duration.newBuilder() - .setNanos((int) TimeUnit.MILLISECONDS.toNanos(100L)) - .build()))); - assertThat(converter.convert("'0ms'"), is(nullValue())); - assertThat(converter.convert("'-100ms'"), is(nullValue())); - assertThat( - converter.convert("'315576000000000ms'"), - is(equalTo(Duration.newBuilder().setSeconds(315576000000L).build()))); - assertThat( - converter.convert("'1000ms'"), is(equalTo(Duration.newBuilder().setSeconds(1L).build()))); - assertThat( - converter.convert("'1001ms'"), - is( - equalTo( - Duration.newBuilder() - .setSeconds(1L) - .setNanos((int) TimeUnit.MILLISECONDS.toNanos(1L)) - .build()))); - - assertThat(converter.convert("'1ns'"), is(equalTo(Duration.newBuilder().setNanos(1).build()))); - assertThat( - converter.convert("'1us'"), is(equalTo(Duration.newBuilder().setNanos(1000).build()))); - assertThat( - converter.convert("'1ms'"), is(equalTo(Duration.newBuilder().setNanos(1000000).build()))); - assertThat( - converter.convert("'999999999ns'"), - is(equalTo(Duration.newBuilder().setNanos(999999999).build()))); - assertThat( - converter.convert("'1s'"), is(equalTo(Duration.newBuilder().setSeconds(1L).build()))); - - assertThat(converter.convert("''"), is(nullValue())); - assertThat(converter.convert("' '"), is(nullValue())); - assertThat(converter.convert("'random string'"), is(nullValue())); - - assertThat(converter.convert("null"), is(equalTo(Duration.getDefaultInstance()))); - assertThat(converter.convert("NULL"), is(equalTo(Duration.getDefaultInstance()))); - assertThat(converter.convert("Null"), is(equalTo(Duration.getDefaultInstance()))); - assertThat(converter.convert("'null'"), is(nullValue())); - assertThat(converter.convert("'NULL'"), is(nullValue())); - assertThat(converter.convert("'Null'"), is(nullValue())); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index eab1fcc521af..2d173977787e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -20,7 +20,8 @@ import com.google.cloud.spanner.GceTestEnvConfig; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.IntegrationTestEnv; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; +import com.google.cloud.spanner.connection.ITAbstractSpannerTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -41,7 +42,9 @@ /** Base class for all JDBC integration tests. */ @Category(IntegrationTest.class) public class ITAbstractJdbcTest { - protected class ITJdbcConnectionProvider implements GenericConnectionProvider { + protected class ITJdbcConnectionProvider + implements com.google.cloud.spanner.connection.AbstractSqlScriptVerifier + .GenericConnectionProvider { public ITJdbcConnectionProvider() {} @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java deleted file mode 100644 index 7cd39c7a3ddc..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractSpannerTest.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2019 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.Database; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.GceTestEnvConfig; -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.IntegrationTestEnv; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.SpannerOptions; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionManager.TransactionState; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ExecutionException; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.experimental.categories.Category; - -/** - * Base class for integration tests. This class is located in this package to be able to access - * package-private methods of the Connection API - */ -@Category(IntegrationTest.class) -public abstract class ITAbstractSpannerTest { - protected class ITConnectionProvider implements GenericConnectionProvider { - public ITConnectionProvider() {} - - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of(createConnection()); - } - } - - protected interface ITConnection extends Connection {} - - private ITConnection createITConnection(ConnectionOptions options) { - return new ITConnectionImpl(options); - } - - protected void closeSpanner() { - ConnectionOptions.closeSpanner(); - } - - public static class AbortInterceptor implements StatementExecutionInterceptor { - /** We need to replicate the enum here as it is not visibible outside the connection package */ - public enum ExecutionStep { - /** The initial execution of a statement (DML/Query) */ - EXECUTE_STATEMENT, - /** A call to {@link ResultSet#next()} */ - CALL_NEXT_ON_RESULT_SET, - /** Execution of the statement during a transaction retry */ - RETRY_STATEMENT, - /** A call to {@link ResultSet#next()} during transaction retry */ - RETRY_NEXT_ON_RESULT_SET; - - static ExecutionStep of(StatementExecutionStep step) { - return ExecutionStep.valueOf(step.name()); - } - } - - private double probability; - private boolean onlyInjectOnce = false; - private final Random random = new Random(); - - public AbortInterceptor(double probability) { - Preconditions.checkArgument(probability >= 0.0D && probability <= 1.0D); - this.probability = probability; - } - - public void setProbability(double probability) { - Preconditions.checkArgument(probability >= 0.0D && probability <= 1.0D); - this.probability = probability; - } - - /** Set this value to true to automatically set the probability to zero after an abort */ - public void setOnlyInjectOnce(boolean value) { - this.onlyInjectOnce = value; - } - - protected boolean shouldAbort(String statement, ExecutionStep step) { - return probability > random.nextDouble(); - } - - @Override - public void intercept( - ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction) { - if (shouldAbort(statement.getSqlWithoutComments(), ExecutionStep.of(step))) { - // ugly hack warning: inject the aborted state into the transaction manager to simulate an - // abort - if (transaction instanceof ReadWriteTransaction) { - try { - Field field = ReadWriteTransaction.class.getDeclaredField("txManager"); - field.setAccessible(true); - TransactionManager tx = (TransactionManager) field.get(transaction); - Class cls = Class.forName("com.google.cloud.spanner.TransactionManagerImpl"); - Class cls2 = - Class.forName("com.google.cloud.spanner.SessionPool$AutoClosingTransactionManager"); - Field delegateField = cls2.getDeclaredField("delegate"); - delegateField.setAccessible(true); - TransactionManager delegate = (TransactionManager) delegateField.get(tx); - Field stateField = cls.getDeclaredField("txnState"); - stateField.setAccessible(true); - - // First rollback the delegate, and then pretend it aborted. - // We should call rollback on the delegate and not the wrapping - // AutoClosingTransactionManager, as the latter would cause the session to be returned - // to the session pool. - delegate.rollback(); - stateField.set(delegate, TransactionState.ABORTED); - } catch (Exception e) { - throw new RuntimeException(e); - } - if (onlyInjectOnce) { - probability = 0; - } - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.ABORTED, "Transaction was aborted by interceptor"); - } - } - } - } - - @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static final String DEFAULT_KEY_FILE = null; - private static Database database; - - protected static String getKeyFile() { - return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); - } - - protected static boolean hasValidKeyFile() { - return getKeyFile() != null && Files.exists(Paths.get(getKeyFile())); - } - - protected static IntegrationTestEnv getTestEnv() { - return env; - } - - protected static Database getDatabase() { - return database; - } - - /** - * Returns a connection URL that is extracted from the given {@link SpannerOptions} and database - * in the form - * cloudspanner:[//host]/projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID - */ - static StringBuilder extractConnectionUrl(SpannerOptions options, Database database) { - StringBuilder url = new StringBuilder("cloudspanner:"); - if (options.getHost() != null) { - url.append(options.getHost().substring(options.getHost().indexOf(':') + 1)); - } - url.append("/").append(database.getId().getName()); - return url; - } - - @BeforeClass - public static void setup() throws IOException, InterruptedException, ExecutionException { - database = env.getTestHelper().createTestDatabase(); - } - - /** - * Creates a new default connection to a test database. Use the method {@link - * ITAbstractSpannerTest#appendConnectionUri(StringBuilder)} to append additional connection - * options to the connection URI. - * - * @return the newly opened connection. - */ - public ITConnection createConnection() { - return createConnection( - Collections.emptyList(), - Collections.emptyList()); - } - - public ITConnection createConnection(AbortInterceptor interceptor) { - return createConnection( - Arrays.asList(interceptor), - Collections.emptyList()); - } - - public ITConnection createConnection( - AbortInterceptor interceptor, TransactionRetryListener transactionRetryListener) { - return createConnection( - Arrays.asList(interceptor), - Arrays.asList(transactionRetryListener)); - } - - /** - * Creates a new default connection to a test database. Use the method {@link - * ITAbstractSpannerTest#appendConnectionUri(StringBuilder)} to append additional connection - * options to the connection URI. - * - * @param interceptors Interceptors that should be executed after each statement - * @param transactionRetryListeners Transaction retry listeners that should be added to the {@link - * Connection} - * @return the newly opened connection. - */ - public ITConnection createConnection( - List interceptors, - List transactionRetryListeners) { - StringBuilder url = - extractConnectionUrl(getTestEnv().getTestHelper().getOptions(), getDatabase()); - appendConnectionUri(url); - ConnectionOptions.Builder builder = - ConnectionOptions.newBuilder() - .setUri(url.toString()) - .setStatementExecutionInterceptors(interceptors); - if (hasValidKeyFile()) { - builder.setCredentialsUrl(getKeyFile()); - } - ConnectionOptions options = builder.build(); - ITConnection connection = createITConnection(options); - for (TransactionRetryListener listener : transactionRetryListeners) { - connection.addTransactionRetryListener(listener); - } - return connection; - } - - protected void appendConnectionUri(StringBuilder uri) {} - - /** - * Override this method to instruct the test to create a default test table in the form: - * - *

    -   * CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)
    -   * 
    - * - * Note that the table is not re-created for each test case, but is preserved between test cases. - * It is the responsibility of the test class to either empty the table at the end of each test - * case, or keep track of the state of the test table and execute the test cases in a specific - * order. - * - * @return true if the default test table should be created. - */ - protected boolean doCreateDefaultTestTable() { - return false; - } - - @Before - public void createTestTable() throws Exception { - if (doCreateDefaultTestTable()) { - try (Connection connection = createConnection()) { - connection.setAutocommit(true); - if (!tableExists(connection, "TEST")) { - connection.setAutocommit(false); - connection.startBatchDdl(); - connection.execute( - Statement.of( - "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)")); - connection.runBatch(); - } - } - } - } - - protected boolean tableExists(Connection connection, String table) { - Preconditions.checkArgument(!Strings.isNullOrEmpty(table)); - try (ResultSet rs = - connection.executeQuery( - Statement.newBuilder( - "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE UPPER(TABLE_NAME)=@table_name") - .bind("table_name") - .to(table.toUpperCase()) - .build())) { - while (rs.next()) { - return true; - } - } - return false; - } - - protected boolean indexExists(Connection connection, String table, String index) { - Preconditions.checkArgument(!Strings.isNullOrEmpty(index)); - try (ResultSet rs = - connection.executeQuery( - Statement.newBuilder( - "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE UPPER(TABLE_NAME)=@table_name AND UPPER(INDEX_NAME)=@index_name") - .bind("table_name") - .to(table) - .bind("index_name") - .to(index.toUpperCase()) - .build())) { - while (rs.next()) { - return true; - } - } - return false; - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java deleted file mode 100644 index c6361d0fd04d..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITConnectionImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2019 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.jdbc.ITAbstractSpannerTest.ITConnection; - -/** Implementation of {@link ITConnection} for Spanner generic (not JDBC) connections. */ -class ITConnectionImpl extends ConnectionImpl implements ITConnection { - ITConnectionImpl(ConnectionOptions options) { - super(options); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java index 681f60528144..9c5628399b88 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -26,6 +26,9 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.connection.RandomResultSetGenerator; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.connection.TransactionRetryListener; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedDueToConcurrentModificationException; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedException; import com.google.protobuf.ListValue; @@ -154,7 +157,7 @@ private int getRetryCount(Connection connection) throws SQLException { return ((TransactionRetryCounter) connection .unwrap(CloudSpannerJdbcConnection.class) - .getTransactionRetryListeners() + .getTransactionRetryListenersFromConnection() .next()) .retriesFinished; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index fb4fccbc643b..b835668bf009 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -19,8 +19,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.connection.ConnectionImplTest; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,7 +43,7 @@ static class TestConnectionProvider implements GenericConnectionProvider { public GenericConnection getConnection() { ConnectionOptions options = mock(ConnectionOptions.class); when(options.getUri()).thenReturn(ConnectionImplTest.URI); - com.google.cloud.spanner.jdbc.Connection spannerConnection = + com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); when(options.getConnection()).thenReturn(spannerConnection); JdbcConnection connection = diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 8d49440a5e55..a80e8009fe3b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -29,6 +29,9 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.connection.AbstractConnectionImplTest; +import com.google.cloud.spanner.connection.ConnectionImplTest; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.rpc.Code; import java.lang.reflect.InvocationTargetException; @@ -57,7 +60,7 @@ public class JdbcConnectionTest { Arrays.asList(Struct.newBuilder().set("").to(1L).build())); private JdbcConnection createConnection(ConnectionOptions options) { - com.google.cloud.spanner.jdbc.Connection spannerConnection = + com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); when(options.getConnection()).thenReturn(spannerConnection); return new JdbcConnection( @@ -427,8 +430,8 @@ public void testSetClientInfo() throws SQLException { public void testIsValid() throws SQLException { // Setup. ConnectionOptions options = mock(ConnectionOptions.class); - com.google.cloud.spanner.jdbc.Connection spannerConnection = - mock(com.google.cloud.spanner.jdbc.Connection.class); + com.google.cloud.spanner.connection.Connection spannerConnection = + mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); Statement statement = Statement.of(JdbcConnection.IS_VALID_QUERY); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 4b7fb713ef7f..48d55214de31 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -24,6 +24,8 @@ import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.ConnectionOptionsTest; import java.io.IOException; import java.sql.Connection; import java.sql.DatabaseMetaData; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java index 95e0acae24ef..0b8cd64c32aa 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java @@ -19,6 +19,8 @@ import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; import com.google.protobuf.ListValue; import com.google.protobuf.Value; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 1215434c90a6..9eb1047487e9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -20,13 +20,23 @@ import static org.junit.Assert.fail; import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.rpc.Code; import io.grpc.Server; import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; import java.io.IOException; import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.DriverPropertyInfo; import java.sql.SQLException; +import java.util.Collection; +import java.util.Properties; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -51,7 +61,7 @@ public class JdbcDriverTest { private static Server server; private static InetSocketAddress address; private static final String TEST_KEY_PATH = - ConnectionOptionsTest.class.getResource("test-key.json").getFile(); + JdbcDriverTest.class.getResource("test-key.json").getFile(); @BeforeClass public static void startStaticServer() throws IOException { @@ -67,6 +77,27 @@ public static void stopServer() throws Exception { server.awaitTermination(); } + @Test + public void testClientLibToken() { + assertThat(JdbcDriver.getClientLibToken()).isEqualTo("sp-jdbc"); + } + + @Test + public void testRegister() throws SQLException { + assertThat(JdbcDriver.isRegistered()).isTrue(); + JdbcDriver.deregister(); + assertThat(JdbcDriver.isRegistered()).isFalse(); + try { + JdbcDriver.getRegisteredDriver(); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat(e.getErrorCode()).isEqualTo(Code.FAILED_PRECONDITION_VALUE); + } + JdbcDriver.register(); + assertThat(JdbcDriver.isRegistered()).isTrue(); + assertThat(JdbcDriver.getRegisteredDriver()).isNotNull(); + } + @Test public void testConnect() throws SQLException { try (Connection connection = @@ -101,4 +132,33 @@ public void testConnectWithCredentialsAndOAuthToken() throws SQLException { assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); } } + + @Test + public void testGetPropertyInfo() throws SQLException { + DriverPropertyInfo[] props = + JdbcDriver.getRegisteredDriver() + .getPropertyInfo( + "jdbc:cloudspanner:/projects/p/instances/i/databases/d", new Properties()); + assertThat(props).hasLength(ConnectionOptions.VALID_PROPERTIES.size()); + + Collection validConnectionPropertyNames = + Collections2.transform( + ConnectionOptions.VALID_PROPERTIES, + new Function() { + @Override + public String apply(ConnectionProperty input) { + return input.getName(); + } + }); + Collection driverPropertyNames = + Collections2.transform( + ImmutableList.copyOf(props), + new Function() { + @Override + public String apply(DriverPropertyInfo input) { + return input.name; + } + }); + assertThat(driverPropertyNames).containsExactlyElementsIn(validConnectionPropertyNames); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index a902207b8ad0..416721328519 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; +import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.protobuf.ListValue; import com.google.protobuf.Value; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index cf93d69d099e..1b201f9a916e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -19,7 +19,6 @@ import static com.google.cloud.spanner.jdbc.JdbcParameterStore.convertPositionalParametersToNamedParameters; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; @@ -28,6 +27,7 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.common.io.CharStreams; +import com.google.common.truth.Truth; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -740,21 +740,18 @@ public void testConvertPositionalParametersToNamedParameters() throws SQLExcepti } private void assertUnclosedLiteral(String sql) { - boolean exception = false; try { convertPositionalParametersToNamedParameters(sql); + fail("missing expected exception"); } catch (SQLException t) { - assertThat(t instanceof JdbcSqlException, is(true)); + Truth.assertThat((Throwable) t).isInstanceOf(JdbcSqlException.class); JdbcSqlException e = (JdbcSqlException) t; - assertThat(e.getCode(), is(Code.INVALID_ARGUMENT)); - assertThat( - e.getMessage(), - startsWith( + Truth.assertThat(e.getCode()).isSameInstanceAs(Code.INVALID_ARGUMENT); + Truth.assertThat(e.getMessage()) + .startsWith( Code.INVALID_ARGUMENT.name() + ": SQL statement contains an unclosed literal: " - + sql)); - exception = true; + + sql); } - assertThat(exception, is(true)); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 9b829e54e07a..bcf0454f75a5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -30,6 +30,7 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.connection.Connection; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.StringReader; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index 460e07f6699e..f628e17ee150 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -21,6 +21,7 @@ import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.common.base.MoreObjects; import com.google.spanner.v1.ExecuteSqlRequest; import java.sql.DriverManager; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java index 7a4543089aa4..4f41771eb900 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -16,12 +16,12 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.hamcrest.MatcherAssert.assertThat; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; +import com.google.cloud.spanner.connection.StatementParser; +import com.google.cloud.spanner.connection.StatementResult.ResultType; import com.google.rpc.Code; import java.sql.Array; import java.sql.Connection; @@ -172,14 +172,13 @@ public JdbcSqlScriptVerifier(GenericConnectionProvider connectionProvider) { @Override protected void verifyExpectedException( String statement, Exception e, String code, String messagePrefix) { - assertThat(e instanceof JdbcSqlException, is(true)); + assertThat(e).isInstanceOf(JdbcSqlException.class); JdbcSqlException jdbcException = (JdbcSqlException) e; - assertThat(statement, jdbcException.getCode(), is(equalTo(Code.valueOf(code)))); + assertWithMessage(statement).that(jdbcException.getCode()).isEqualTo(Code.valueOf(code)); if (messagePrefix != null) { - assertThat( - statement, - e.getMessage(), - startsWith(messagePrefix.substring(1, messagePrefix.length() - 1))); + assertWithMessage(statement) + .that(e.getMessage()) + .startsWith(messagePrefix.substring(1, messagePrefix.length() - 1)); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 12e0921e36c7..c1b1e992fc6c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -25,8 +25,11 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.connection.Connection; +import com.google.cloud.spanner.connection.StatementParser; +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.cloud.spanner.jdbc.StatementResult.ResultType; import com.google.rpc.Code; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 328c01f1cfbc..870711d02fa4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -34,6 +34,7 @@ import com.google.cloud.ByteArray; import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.connection.ReadOnlyStalenessUtil; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.rpc.Code; import java.math.BigDecimal; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java deleted file mode 100644 index 44e326cf9177..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetGenerator.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2019 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 - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc; - -import com.google.api.client.util.Base64; -import com.google.cloud.Date; -import com.google.cloud.Timestamp; -import com.google.protobuf.ListValue; -import com.google.protobuf.NullValue; -import com.google.protobuf.Value; -import com.google.protobuf.util.Timestamps; -import com.google.spanner.v1.ResultSet; -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.util.Random; - -public class RandomResultSetGenerator { - private static final Type TYPES[] = - new Type[] { - Type.newBuilder().setCode(TypeCode.BOOL).build(), - Type.newBuilder().setCode(TypeCode.INT64).build(), - Type.newBuilder().setCode(TypeCode.FLOAT64).build(), - Type.newBuilder().setCode(TypeCode.STRING).build(), - Type.newBuilder().setCode(TypeCode.BYTES).build(), - Type.newBuilder().setCode(TypeCode.DATE).build(), - Type.newBuilder().setCode(TypeCode.TIMESTAMP).build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.BOOL)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.INT64)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.FLOAT64)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.STRING)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.BYTES)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.DATE)) - .build(), - Type.newBuilder() - .setCode(TypeCode.ARRAY) - .setArrayElementType(Type.newBuilder().setCode(TypeCode.TIMESTAMP)) - .build(), - }; - - private static final ResultSetMetadata generateMetadata() { - StructType.Builder rowTypeBuilder = StructType.newBuilder(); - for (int col = 0; col < TYPES.length; col++) { - rowTypeBuilder.addFields(Field.newBuilder().setName("COL" + col).setType(TYPES[col])).build(); - } - ResultSetMetadata.Builder builder = ResultSetMetadata.newBuilder(); - builder.setRowType(rowTypeBuilder.build()); - return builder.build(); - } - - private static final ResultSetMetadata METADATA = generateMetadata(); - - private final int rowCount; - private final Random random = new Random(); - - public RandomResultSetGenerator(int rowCount) { - this.rowCount = rowCount; - } - - public ResultSet generate() { - ResultSet.Builder builder = ResultSet.newBuilder(); - for (int row = 0; row < rowCount; row++) { - ListValue.Builder rowBuilder = ListValue.newBuilder(); - for (int col = 0; col < TYPES.length; col++) { - Value.Builder valueBuilder = Value.newBuilder(); - setRandomValue(valueBuilder, TYPES[col]); - rowBuilder.addValues(valueBuilder.build()); - } - builder.addRows(rowBuilder.build()); - } - builder.setMetadata(METADATA); - return builder.build(); - } - - private void setRandomValue(Value.Builder builder, Type type) { - if (randomNull()) { - builder.setNullValue(NullValue.NULL_VALUE); - } else { - switch (type.getCode()) { - case ARRAY: - int length = random.nextInt(20) + 1; - ListValue.Builder arrayBuilder = ListValue.newBuilder(); - for (int i = 0; i < length; i++) { - Value.Builder valueBuilder = Value.newBuilder(); - setRandomValue(valueBuilder, type.getArrayElementType()); - arrayBuilder.addValues(valueBuilder.build()); - } - builder.setListValue(arrayBuilder.build()); - break; - case BOOL: - builder.setBoolValue(random.nextBoolean()); - break; - case STRING: - case BYTES: - byte[] bytes = new byte[random.nextInt(200)]; - random.nextBytes(bytes); - builder.setStringValue(Base64.encodeBase64String(bytes)); - break; - case DATE: - Date date = - Date.fromYearMonthDay( - random.nextInt(2019) + 1, random.nextInt(11) + 1, random.nextInt(28) + 1); - builder.setStringValue(date.toString()); - break; - case FLOAT64: - builder.setNumberValue(random.nextDouble()); - break; - case INT64: - builder.setStringValue(String.valueOf(random.nextLong())); - break; - case TIMESTAMP: - com.google.protobuf.Timestamp ts = - Timestamps.add( - Timestamps.EPOCH, - com.google.protobuf.Duration.newBuilder() - .setSeconds(random.nextInt(100_000_000)) - .setNanos(random.nextInt(1000_000_000)) - .build()); - builder.setStringValue(Timestamp.fromProto(ts).toString()); - break; - case STRUCT: - case TYPE_CODE_UNSPECIFIED: - case UNRECOGNIZED: - default: - throw new IllegalArgumentException("Unknown or unsupported type: " + type.getCode()); - } - } - } - - private boolean randomNull() { - return random.nextInt(10) == 0; - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java deleted file mode 100644 index 12f1094fef86..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessConverterTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.ReadOnlyStalenessConverter; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ReadOnlyStalenessConverterTest { - - static String getAllowedValues( - Class> converterClass) - throws CompileException { - Set statements = ClientSideStatements.INSTANCE.getCompiledStatements(); - for (ClientSideStatementImpl statement : statements) { - if (statement.getSetStatement() != null - && converterClass.getName().endsWith(statement.getSetStatement().getConverterName())) { - return statement.getSetStatement().getAllowedValues(); - } - } - return null; - } - - @Test - public void testConvert() throws CompileException { - String allowedValues = getAllowedValues(ReadOnlyStalenessConverter.class); - assertThat(allowedValues, is(notNullValue())); - ReadOnlyStalenessConverter converter = new ReadOnlyStalenessConverter(allowedValues); - - assertThat(converter.convert("strong"), is(equalTo(TimestampBound.strong()))); - assertThat(converter.convert("Strong"), is(equalTo(TimestampBound.strong()))); - assertThat(converter.convert("STRONG"), is(equalTo(TimestampBound.strong()))); - - assertThat( - converter.convert("read_timestamp 2018-10-01T23:11:15.10001Z"), - is( - equalTo( - TimestampBound.ofReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); - assertThat( - converter.convert("Read_Timestamp 2018-10-01T23:11:15.999Z"), - is( - equalTo( - TimestampBound.ofReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.999Z"))))); - assertThat( - converter.convert("READ_TIMESTAMP 2018-10-01T23:11:15.1000Z"), - is( - equalTo( - TimestampBound.ofReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.1000Z"))))); - assertThat( - converter.convert("read_timestamp 2018-10-01T23:11:15.999999999Z"), - is( - equalTo( - TimestampBound.ofReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.999999999Z"))))); - assertThat( - converter.convert("read_timestamp\t2018-10-01T23:11:15.10001Z"), - is( - equalTo( - TimestampBound.ofReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); - assertThat(converter.convert("read_timestamp\n2018-10-01T23:11:15.10001Z"), is(nullValue())); - - assertThat( - converter.convert("min_read_timestamp 2018-10-01T23:11:15.10001Z"), - is( - equalTo( - TimestampBound.ofMinReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); - assertThat( - converter.convert("Min_Read_Timestamp 2018-10-01T23:11:15.999Z"), - is( - equalTo( - TimestampBound.ofMinReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.999Z"))))); - assertThat( - converter.convert("MIN_READ_TIMESTAMP 2018-10-01T23:11:15.1000Z"), - is( - equalTo( - TimestampBound.ofMinReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.1000Z"))))); - assertThat( - converter.convert("min_read_timestamp 2018-10-01T23:11:15.999999999Z"), - is( - equalTo( - TimestampBound.ofMinReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.999999999Z"))))); - assertThat( - converter.convert("min_read_timestamp\t2018-10-01T23:11:15.10001Z"), - is( - equalTo( - TimestampBound.ofMinReadTimestamp( - Timestamp.parseTimestamp("2018-10-01T23:11:15.10001Z"))))); - assertThat( - converter.convert("min_read_timestamp\n2018-10-01T23:11:15.10001Z"), is(nullValue())); - - assertThat( - converter.convert("exact_staleness 10s"), - is(equalTo(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)))); - assertThat( - converter.convert("Exact_Staleness 100ms"), - is(equalTo(TimestampBound.ofExactStaleness(100L, TimeUnit.MILLISECONDS)))); - assertThat( - converter.convert("EXACT_STALENESS 99999us"), - is(equalTo(TimestampBound.ofExactStaleness(99999L, TimeUnit.MICROSECONDS)))); - assertThat( - converter.convert("exact_staleness 999999999ns"), - is(equalTo(TimestampBound.ofExactStaleness(999999999L, TimeUnit.NANOSECONDS)))); - assertThat( - converter.convert("exact_staleness " + Long.MAX_VALUE + "ns"), - is(equalTo(TimestampBound.ofExactStaleness(Long.MAX_VALUE, TimeUnit.NANOSECONDS)))); - - assertThat( - converter.convert("max_staleness 10s"), - is(equalTo(TimestampBound.ofMaxStaleness(10L, TimeUnit.SECONDS)))); - assertThat( - converter.convert("Max_Staleness 100ms"), - is(equalTo(TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)))); - assertThat( - converter.convert("MAX_STALENESS 99999us"), - is(equalTo(TimestampBound.ofMaxStaleness(99999L, TimeUnit.MICROSECONDS)))); - assertThat( - converter.convert("max_staleness 999999999ns"), - is(equalTo(TimestampBound.ofMaxStaleness(999999999L, TimeUnit.NANOSECONDS)))); - assertThat( - converter.convert("max_staleness " + Long.MAX_VALUE + "ns"), - is(equalTo(TimestampBound.ofMaxStaleness(Long.MAX_VALUE, TimeUnit.NANOSECONDS)))); - - assertThat(converter.convert(""), is(nullValue())); - assertThat(converter.convert(" "), is(nullValue())); - assertThat(converter.convert("random string"), is(nullValue())); - assertThat(converter.convert("read_timestamp"), is(nullValue())); - assertThat(converter.convert("min_read_timestamp"), is(nullValue())); - assertThat(converter.convert("exact_staleness"), is(nullValue())); - assertThat(converter.convert("max_staleness"), is(nullValue())); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java deleted file mode 100644 index bc43e2aa1ed9..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.NoCredentials; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ReadOnlyTransaction; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Matchers; - -@RunWith(JUnit4.class) -public class ReadOnlyStalenessTest { - private static final String URI = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?readOnly=true"; - private static final String SELECT = "select foo from bar"; - - private final DatabaseClient dbClient = mock(DatabaseClient.class); - - private ConnectionImpl createConnection(ConnectionOptions options) { - Spanner spanner = mock(Spanner.class); - SpannerPool spannerPool = mock(SpannerPool.class); - when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) - .thenReturn(spanner); - DdlClient ddlClient = mock(DdlClient.class); - ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); - when(singleUseReadOnlyTx.executeQuery(Statement.of(SELECT))).thenReturn(mock(ResultSet.class)); - when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) - .thenReturn(singleUseReadOnlyTx); - ReadOnlyTransaction readOnlyTx = mock(ReadOnlyTransaction.class); - when(readOnlyTx.executeQuery(Statement.of(SELECT))).thenReturn(mock(ResultSet.class)); - when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))).thenReturn(readOnlyTx); - - return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); - } - - @Test - public void testDefaultReadOnlyStalenessAutocommitOnce() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(connection.isAutocommit(), is(true)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).singleUseReadOnlyTransaction(TimestampBound.strong()); - } - } - - @Test - public void testDefaultReadOnlyStalenessAutocommitTwice() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(connection.isAutocommit(), is(true)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - connection.execute(Statement.of(SELECT)); - verify(dbClient, times(2)).singleUseReadOnlyTransaction(TimestampBound.strong()); - } - } - - @Test - public void testDefaultReadOnlyStalenessAutocommitChanging() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - assertThat(connection.isAutocommit(), is(true)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).singleUseReadOnlyTransaction(TimestampBound.strong()); - - connection.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - connection.execute(Statement.of(SELECT)); - verify(dbClient) - .singleUseReadOnlyTransaction(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - - connection.setReadOnlyStaleness(TimestampBound.ofMaxStaleness(5L, TimeUnit.SECONDS)); - connection.execute(Statement.of(SELECT)); - verify(dbClient) - .singleUseReadOnlyTransaction(TimestampBound.ofMaxStaleness(5L, TimeUnit.SECONDS)); - - connection.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); - connection.execute(Statement.of(SELECT)); - verify(dbClient) - .singleUseReadOnlyTransaction(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); - - connection.setReadOnlyStaleness(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); - connection.execute(Statement.of(SELECT)); - verify(dbClient) - .singleUseReadOnlyTransaction(TimestampBound.ofMinReadTimestamp(Timestamp.MAX_VALUE)); - } - } - - @Test - public void testDefaultReadOnlyStalenessTransactionalOnce() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - assertThat(connection.isAutocommit(), is(false)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).readOnlyTransaction(TimestampBound.strong()); - } - } - - @Test - public void testDefaultReadOnlyStalenessTransactionalTwice() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - assertThat(connection.isAutocommit(), is(false)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - connection.execute(Statement.of(SELECT)); - connection.commit(); - // one transaction - verify(dbClient, times(1)).readOnlyTransaction(TimestampBound.strong()); - - connection.execute(Statement.of(SELECT)); - connection.commit(); - connection.execute(Statement.of(SELECT)); - // two transactions (plus one above) - verify(dbClient, times(3)).readOnlyTransaction(TimestampBound.strong()); - } - } - - @Test - public void testDefaultReadOnlyStalenessTransactionalChanging() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - assertThat(connection.isAutocommit(), is(false)); - assertThat(connection.isReadOnly(), is(true)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).readOnlyTransaction(TimestampBound.strong()); - connection.commit(); - - connection.setReadOnlyStaleness(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).readOnlyTransaction(TimestampBound.ofExactStaleness(10L, TimeUnit.SECONDS)); - connection.commit(); - - connection.setReadOnlyStaleness(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); - connection.execute(Statement.of(SELECT)); - verify(dbClient).readOnlyTransaction(TimestampBound.ofReadTimestamp(Timestamp.MIN_VALUE)); - connection.commit(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java deleted file mode 100644 index 3af641f1f799..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyStalenessUtilTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2019 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 com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.durationToString; -import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.getTimeUnitAbbreviation; -import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.parseRfc3339; -import static com.google.cloud.spanner.jdbc.ReadOnlyStalenessUtil.parseTimeUnit; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.TimestampBound; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ReadOnlyStalenessUtilTest { - - @Test - public void testParseRfc3339() { - Map timestamps = new HashMap<>(); - timestamps.put( - "2018-03-01T10:11:12.999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999000000)); - timestamps.put("2018-10-28T02:00:00+02:00", Timestamp.ofTimeSecondsAndNanos(1540684800L, 0)); - timestamps.put("2018-10-28T03:00:00+01:00", Timestamp.ofTimeSecondsAndNanos(1540692000L, 0)); - timestamps.put( - "2018-01-01T00:00:00.000000001Z", Timestamp.ofTimeSecondsAndNanos(1514764800L, 1)); - timestamps.put("2018-10-28T02:00:00Z", Timestamp.ofTimeSecondsAndNanos(1540692000L, 0)); - timestamps.put( - "2018-12-31T23:59:59.999999999Z", Timestamp.ofTimeSecondsAndNanos(1546300799L, 999999999)); - timestamps.put( - "2018-03-01T10:11:12.9999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999900000)); - timestamps.put( - "2018-03-01T10:11:12.000000001Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 1)); - timestamps.put( - "2018-03-01T10:11:12.100000000Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000000)); - timestamps.put( - "2018-03-01T10:11:12.100000001Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000001)); - timestamps.put("2018-03-01T10:11:12-10:00", Timestamp.ofTimeSecondsAndNanos(1519935072L, 0)); - timestamps.put( - "2018-03-01T10:11:12.999999999Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 999999999)); - timestamps.put("2018-03-01T10:11:12-12:00", Timestamp.ofTimeSecondsAndNanos(1519942272L, 0)); - timestamps.put("2018-10-28T03:00:00Z", Timestamp.ofTimeSecondsAndNanos(1540695600L, 0)); - timestamps.put("2018-10-28T02:30:00Z", Timestamp.ofTimeSecondsAndNanos(1540693800L, 0)); - timestamps.put( - "2018-03-01T10:11:12.123Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 123000000)); - timestamps.put("2018-10-28T02:30:00+02:00", Timestamp.ofTimeSecondsAndNanos(1540686600L, 0)); - timestamps.put( - "2018-03-01T10:11:12.123456789Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 123456789)); - timestamps.put( - "2018-03-01T10:11:12.1000Z", Timestamp.ofTimeSecondsAndNanos(1519899072L, 100000000)); - - for (Entry ts : timestamps.entrySet()) { - Timestamp gTimestamp = parseRfc3339(ts.getKey()); - assertThat( - "Seconds for timestamp " + ts + " do not match", - gTimestamp.getSeconds(), - is(equalTo(ts.getValue().getSeconds()))); - assertThat( - "Nanos for timestamp " + ts + " do not match", - gTimestamp.getNanos(), - is(equalTo(ts.getValue().getNanos()))); - } - } - - @Test - public void testParseTimeUnit() { - assertThat(parseTimeUnit("s"), is(equalTo(TimeUnit.SECONDS))); - assertThat(parseTimeUnit("ms"), is(equalTo(TimeUnit.MILLISECONDS))); - assertThat(parseTimeUnit("us"), is(equalTo(TimeUnit.MICROSECONDS))); - assertThat(parseTimeUnit("ns"), is(equalTo(TimeUnit.NANOSECONDS))); - } - - @Test - public void testGetTimeUnitAbbreviation() { - assertThat(getTimeUnitAbbreviation(TimeUnit.SECONDS), is(equalTo("s"))); - assertThat(getTimeUnitAbbreviation(TimeUnit.MILLISECONDS), is(equalTo("ms"))); - assertThat(getTimeUnitAbbreviation(TimeUnit.MICROSECONDS), is(equalTo("us"))); - assertThat(getTimeUnitAbbreviation(TimeUnit.NANOSECONDS), is(equalTo("ns"))); - - List supportedTimeUnits = - Arrays.asList( - TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS); - for (TimeUnit unit : TimeUnit.values()) { - if (supportedTimeUnits.contains(unit)) { - assertThat(getTimeUnitAbbreviation(unit), is(notNullValue())); - } else { - String value = null; - try { - value = getTimeUnitAbbreviation(unit); - } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.INVALID_ARGUMENT) { - value = "unsupported"; - } - } - assertThat(value, is(equalTo("unsupported"))); - } - } - } - - @Test - public void testStalenessToString() { - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(10L, TimeUnit.NANOSECONDS))), - is(equalTo("10ns"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(1000L, TimeUnit.NANOSECONDS))), - is(equalTo("1us"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(100000L, TimeUnit.NANOSECONDS))), - is(equalTo("100us"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(999999L, TimeUnit.NANOSECONDS))), - is(equalTo("999999ns"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(1L, TimeUnit.SECONDS))), - is(equalTo("1s"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(1000L, TimeUnit.MILLISECONDS))), - is(equalTo("1s"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(1001L, TimeUnit.MILLISECONDS))), - is(equalTo("1001ms"))); - assertThat( - durationToString( - new ReadOnlyStalenessUtil.MaxStalenessGetter( - TimestampBound.ofMaxStaleness(1000000000L, TimeUnit.NANOSECONDS))), - is(equalTo("1s"))); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java deleted file mode 100644 index 0642b75ae57f..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadOnlyTransactionTest.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Key; -import com.google.cloud.spanner.KeySet; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.Options.ReadOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState; -import com.google.spanner.v1.ResultSetStats; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; -import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ReadOnlyTransactionTest { - @Rule public ExpectedException exception = ExpectedException.none(); - - private static final class SimpleReadOnlyTransaction - implements com.google.cloud.spanner.ReadOnlyTransaction { - private Timestamp readTimestamp = null; - private final TimestampBound staleness; - - private SimpleReadOnlyTransaction(TimestampBound staleness) { - this.staleness = staleness; - } - - @Override - public ResultSet read( - String table, KeySet keys, Iterable columns, ReadOption... options) { - return null; - } - - @Override - public ResultSet readUsingIndex( - String table, String index, KeySet keys, Iterable columns, ReadOption... options) { - return null; - } - - @Override - public Struct readRow(String table, Key key, Iterable columns) { - return null; - } - - @Override - public Struct readRowUsingIndex(String table, String index, Key key, Iterable columns) { - return null; - } - - @Override - public ResultSet executeQuery(Statement statement, QueryOption... options) { - if (readTimestamp == null) { - switch (staleness.getMode()) { - case STRONG: - readTimestamp = Timestamp.now(); - break; - case READ_TIMESTAMP: - readTimestamp = staleness.getReadTimestamp(); - break; - case MIN_READ_TIMESTAMP: - readTimestamp = staleness.getMinReadTimestamp(); - break; - case EXACT_STALENESS: - Calendar cal = Calendar.getInstance(); - cal.add( - Calendar.MILLISECOND, (int) -staleness.getExactStaleness(TimeUnit.MILLISECONDS)); - readTimestamp = Timestamp.of(cal.getTime()); - break; - case MAX_STALENESS: - cal = Calendar.getInstance(); - cal.add(Calendar.MILLISECOND, (int) -staleness.getMaxStaleness(TimeUnit.MILLISECONDS)); - readTimestamp = Timestamp.of(cal.getTime()); - break; - default: - throw new IllegalStateException(); - } - } - return mock(ResultSet.class); - } - - @Override - public ResultSet analyzeQuery(Statement statement, QueryAnalyzeMode queryMode) { - ResultSet res = executeQuery(statement); - when(res.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); - return res; - } - - @Override - public void close() {} - - @Override - public Timestamp getReadTimestamp() { - return readTimestamp; - } - } - - private ReadOnlyTransaction createSubject() { - return createSubject(TimestampBound.strong()); - } - - private ReadOnlyTransaction createSubject(TimestampBound staleness) { - DatabaseClient client = mock(DatabaseClient.class); - when(client.readOnlyTransaction(staleness)) - .thenReturn(new SimpleReadOnlyTransaction(staleness)); - return ReadOnlyTransaction.newBuilder() - .setDatabaseClient(client) - .setReadOnlyStaleness(staleness) - .withStatementExecutor(new StatementExecutor()) - .build(); - } - - @Test - public void testExecuteDdl() { - ParsedStatement ddl = mock(ParsedStatement.class); - when(ddl.getType()).thenReturn(StatementType.DDL); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - createSubject().executeDdl(ddl); - } - - @Test - public void testExecuteUpdate() { - ParsedStatement update = mock(ParsedStatement.class); - when(update.getType()).thenReturn(StatementType.UPDATE); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - createSubject().executeUpdate(update); - } - - @Test - public void testWrite() { - Mutation mutation = Mutation.newInsertBuilder("foo").build(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - createSubject().write(mutation); - } - - @Test - public void testWriteIterable() { - Mutation mutation = Mutation.newInsertBuilder("foo").build(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - createSubject().write(Arrays.asList(mutation, mutation)); - } - - @Test - public void testRunBatch() { - ReadOnlyTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.runBatch(); - } - - @Test - public void testAbortBatch() { - ReadOnlyTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.abortBatch(); - } - - @Test - public void testGetCommitTimestamp() { - ReadOnlyTransaction transaction = createSubject(); - transaction.commit(); - assertThat(transaction.getState(), is(UnitOfWorkState.COMMITTED)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - transaction.getCommitTimestamp(); - } - - @Test - public void testIsReadOnly() { - assertThat(createSubject().isReadOnly(), is(true)); - } - - @Test - public void testExecuteQuery() { - for (TimestampBound staleness : getTestTimestampBounds()) { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - - ReadOnlyTransaction transaction = createSubject(staleness); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.NONE); - assertThat(rs, is(notNullValue())); - assertThat(rs.getStats(), is(nullValue())); - } - } - - @Test - public void testExecuteQueryWithOptionsTest() { - String sql = "SELECT * FROM FOO"; - QueryOption option = Options.prefetchChunks(10000); - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of(sql); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - DatabaseClient client = mock(DatabaseClient.class); - com.google.cloud.spanner.ReadOnlyTransaction tx = - mock(com.google.cloud.spanner.ReadOnlyTransaction.class); - ResultSet resWithOptions = mock(ResultSet.class); - ResultSet resWithoutOptions = mock(ResultSet.class); - when(tx.executeQuery(Statement.of(sql), option)).thenReturn(resWithOptions); - when(tx.executeQuery(Statement.of(sql))).thenReturn(resWithoutOptions); - when(client.readOnlyTransaction(TimestampBound.strong())).thenReturn(tx); - - ReadOnlyTransaction transaction = - ReadOnlyTransaction.newBuilder() - .setDatabaseClient(client) - .setReadOnlyStaleness(TimestampBound.strong()) - .withStatementExecutor(new StatementExecutor()) - .build(); - ResultSet expectedWithOptions = DirectExecuteResultSet.ofResultSet(resWithOptions); - assertThat( - transaction.executeQuery(parsedStatement, AnalyzeMode.NONE, option), - is(equalTo(expectedWithOptions))); - ResultSet expectedWithoutOptions = DirectExecuteResultSet.ofResultSet(resWithoutOptions); - assertThat( - transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), - is(equalTo(expectedWithoutOptions))); - } - - @Test - public void testPlanQuery() { - for (TimestampBound staleness : getTestTimestampBounds()) { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - - ReadOnlyTransaction transaction = createSubject(staleness); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PLAN); - assertThat(rs, is(notNullValue())); - // get all results and then get the stats - while (rs.next()) { - // do nothing - } - assertThat(rs.getStats(), is(notNullValue())); - } - } - - @Test - public void testProfileQuery() { - for (TimestampBound staleness : getTestTimestampBounds()) { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - - ReadOnlyTransaction transaction = createSubject(staleness); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PROFILE); - assertThat(rs, is(notNullValue())); - // get all results and then get the stats - while (rs.next()) { - // do nothing - } - assertThat(rs.getStats(), is(notNullValue())); - } - } - - @Test - public void testGetReadTimestamp() { - for (TimestampBound staleness : getTestTimestampBounds()) { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - - ReadOnlyTransaction transaction = createSubject(staleness); - boolean expectedException = false; - try { - transaction.getReadTimestamp(); - } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION) { - expectedException = true; - } - } - assertThat(expectedException, is(true)); - assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); - assertThat(transaction.getReadTimestamp(), is(notNullValue())); - } - } - - private List getTestTimestampBounds() { - return Arrays.asList( - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(Timestamp.now()), - TimestampBound.ofMinReadTimestamp(Timestamp.now()), - TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), - TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)); - } - - @Test - public void testState() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); - - ReadOnlyTransaction transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - transaction.commit(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); - assertThat(transaction.isActive(), is(false)); - - transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - - transaction.commit(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); - assertThat(transaction.isActive(), is(false)); - - // start a new transaction - transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - transaction.rollback(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); - assertThat(transaction.isActive(), is(false)); - - transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - transaction.rollback(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); - assertThat(transaction.isActive(), is(false)); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java deleted file mode 100644 index 54a83c628940..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReadWriteTransactionTest.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.ResultSets; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionManager.TransactionState; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.Type.StructField; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.spanner.v1.ResultSetStats; -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.ExecutionException; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class ReadWriteTransactionTest { - - @Rule public final ExpectedException exception = ExpectedException.none(); - - private enum CommitBehavior { - SUCCEED, - FAIL, - ABORT; - } - - private static class SimpleTransactionManager implements TransactionManager { - private TransactionState state; - private Timestamp commitTimestamp; - private TransactionContext txContext; - private CommitBehavior commitBehavior; - - private SimpleTransactionManager(TransactionContext txContext, CommitBehavior commitBehavior) { - this.txContext = txContext; - this.commitBehavior = commitBehavior; - } - - @Override - public TransactionContext begin() { - state = TransactionState.STARTED; - return txContext; - } - - @Override - public void commit() { - switch (commitBehavior) { - case SUCCEED: - commitTimestamp = Timestamp.now(); - state = TransactionState.COMMITTED; - break; - case FAIL: - state = TransactionState.COMMIT_FAILED; - throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "commit failed"); - case ABORT: - state = TransactionState.COMMIT_FAILED; - commitBehavior = CommitBehavior.SUCCEED; - throw SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted"); - default: - throw new IllegalStateException(); - } - } - - @Override - public void rollback() { - state = TransactionState.ROLLED_BACK; - } - - @Override - public TransactionContext resetForRetry() { - return txContext; - } - - @Override - public Timestamp getCommitTimestamp() { - return commitTimestamp; - } - - @Override - public TransactionState getState() { - return state; - } - - @Override - public void close() { - if (state != TransactionState.COMMITTED) { - state = TransactionState.ROLLED_BACK; - } - } - } - - private ReadWriteTransaction createSubject() { - return createSubject(CommitBehavior.SUCCEED, false); - } - - private ReadWriteTransaction createSubject(CommitBehavior commitBehavior) { - return createSubject(commitBehavior, false); - } - - private ReadWriteTransaction createSubject( - final CommitBehavior commitBehavior, boolean withRetry) { - DatabaseClient client = mock(DatabaseClient.class); - when(client.transactionManager()) - .thenAnswer( - new Answer() { - @Override - public TransactionManager answer(InvocationOnMock invocation) throws Throwable { - TransactionContext txContext = mock(TransactionContext.class); - when(txContext.executeQuery(any(Statement.class))) - .thenReturn(mock(ResultSet.class)); - ResultSet rsWithStats = mock(ResultSet.class); - when(rsWithStats.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); - when(txContext.analyzeQuery(any(Statement.class), any(QueryAnalyzeMode.class))) - .thenReturn(rsWithStats); - when(txContext.executeUpdate(any(Statement.class))).thenReturn(1L); - return new SimpleTransactionManager(txContext, commitBehavior); - } - }); - return ReadWriteTransaction.newBuilder() - .setDatabaseClient(client) - .setRetryAbortsInternally(withRetry) - .setTransactionRetryListeners(Collections.emptyList()) - .withStatementExecutor(new StatementExecutor()) - .build(); - } - - @Test - public void testExecuteDdl() { - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.DDL); - - ReadWriteTransaction transaction = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - transaction.executeDdl(statement); - } - - @Test - public void testRunBatch() { - ReadWriteTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.runBatch(); - } - - @Test - public void testAbortBatch() { - ReadWriteTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.abortBatch(); - } - - @Test - public void testExecuteQuery() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.NONE); - assertThat(rs, is(notNullValue())); - assertThat(rs.getStats(), is(nullValue())); - } - - @Test - public void testPlanQuery() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PLAN); - assertThat(rs, is(notNullValue())); - while (rs.next()) { - // do nothing - } - assertThat(rs.getStats(), is(notNullValue())); - } - - @Test - public void testProfileQuery() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - ResultSet rs = transaction.executeQuery(parsedStatement, AnalyzeMode.PROFILE); - assertThat(rs, is(notNullValue())); - while (rs.next()) { - // do nothing - } - assertThat(rs.getStats(), is(notNullValue())); - } - - @Test - public void testExecuteUpdate() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); - when(parsedStatement.isUpdate()).thenReturn(true); - Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - assertThat(transaction.executeUpdate(parsedStatement), is(1L)); - } - - @Test - public void testGetCommitTimestampBeforeCommit() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); - when(parsedStatement.isUpdate()).thenReturn(true); - Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - assertThat(transaction.executeUpdate(parsedStatement), is(1L)); - - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - transaction.getCommitTimestamp(); - } - - @Test - public void testGetCommitTimestampAfterCommit() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.UPDATE); - when(parsedStatement.isUpdate()).thenReturn(true); - Statement statement = Statement.of("UPDATE FOO SET BAR=1 WHERE ID=2"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - assertThat(transaction.executeUpdate(parsedStatement), is(1L)); - transaction.commit(); - - assertThat(transaction.getCommitTimestamp(), is(notNullValue())); - } - - @Test - public void testGetReadTimestamp() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); - - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - transaction.getReadTimestamp(); - } - - @Test - public void testState() { - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - - ReadWriteTransaction transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - assertThat(transaction.executeQuery(parsedStatement, AnalyzeMode.NONE), is(notNullValue())); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - - transaction.commit(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); - assertThat(transaction.isActive(), is(false)); - - // start a new transaction - transaction = createSubject(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - transaction.rollback(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.ROLLED_BACK))); - assertThat(transaction.isActive(), is(false)); - - // start a new transaction that will fail on commit - transaction = createSubject(CommitBehavior.FAIL); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - try { - transaction.commit(); - } catch (SpannerException e) { - // ignore - } - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED))); - assertThat(transaction.isActive(), is(false)); - - // start a new transaction that will abort on commit - transaction = createSubject(CommitBehavior.ABORT); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - try { - transaction.commit(); - } catch (AbortedException e) { - // ignore - } - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED))); - assertThat(transaction.isActive(), is(false)); - - // Start a new transaction that will abort on commit, but with internal retry enabled, so it - // will in the end succeed. - transaction = createSubject(CommitBehavior.ABORT, true); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.STARTED))); - assertThat(transaction.isActive(), is(true)); - transaction.commit(); - assertThat( - transaction.getState(), - is(equalTo(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED))); - assertThat(transaction.isActive(), is(false)); - } - - @Test - public void testIsReadOnly() { - assertThat(createSubject().isReadOnly(), is(false)); - } - - private enum RetryResults { - SAME, - DIFFERENT; - } - - @Test - public void testRetry() { - for (RetryResults results : RetryResults.values()) { - String sql1 = "UPDATE FOO SET BAR=1 WHERE BAZ>=100 AND BAZ<200"; - String sql2 = "UPDATE FOO SET BAR=2 WHERE BAZ>=200 AND BAZ<300"; - DatabaseClient client = mock(DatabaseClient.class); - ParsedStatement update1 = mock(ParsedStatement.class); - when(update1.getType()).thenReturn(StatementType.UPDATE); - when(update1.isUpdate()).thenReturn(true); - when(update1.getStatement()).thenReturn(Statement.of(sql1)); - ParsedStatement update2 = mock(ParsedStatement.class); - when(update2.getType()).thenReturn(StatementType.UPDATE); - when(update2.isUpdate()).thenReturn(true); - when(update2.getStatement()).thenReturn(Statement.of(sql2)); - - TransactionManager txManager = mock(TransactionManager.class); - TransactionContext txContext1 = mock(TransactionContext.class); - when(txManager.begin()).thenReturn(txContext1); - when(txManager.getState()).thenReturn(null, TransactionState.STARTED); - when(client.transactionManager()).thenReturn(txManager); - when(txContext1.executeUpdate(Statement.of(sql1))).thenReturn(90L); - when(txContext1.executeUpdate(Statement.of(sql2))).thenReturn(80L); - - TransactionContext txContext2 = mock(TransactionContext.class); - when(txManager.resetForRetry()).thenReturn(txContext2); - when(client.transactionManager()).thenReturn(txManager); - if (results == RetryResults.SAME) { - when(txContext2.executeUpdate(Statement.of(sql1))).thenReturn(90L); - when(txContext2.executeUpdate(Statement.of(sql2))).thenReturn(80L); - } else if (results == RetryResults.DIFFERENT) { - when(txContext2.executeUpdate(Statement.of(sql1))).thenReturn(90L); - when(txContext2.executeUpdate(Statement.of(sql2))).thenReturn(90L); - } - - // first abort, then do nothing - doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted")) - .doNothing() - .when(txManager) - .commit(); - - ReadWriteTransaction subject = - ReadWriteTransaction.newBuilder() - .setRetryAbortsInternally(true) - .setTransactionRetryListeners(Collections.emptyList()) - .setDatabaseClient(client) - .withStatementExecutor(new StatementExecutor()) - .build(); - subject.executeUpdate(update1); - subject.executeUpdate(update2); - boolean expectedException = false; - try { - subject.commit(); - } catch (SpannerException e) { - if (results == RetryResults.DIFFERENT && e.getErrorCode() == ErrorCode.ABORTED) { - // expected - expectedException = true; - } else { - throw e; - } - } - assertThat(expectedException, is(results == RetryResults.DIFFERENT)); - } - } - - @Test - public void testChecksumResultSet() throws InterruptedException, ExecutionException { - DatabaseClient client = mock(DatabaseClient.class); - ReadWriteTransaction transaction = - ReadWriteTransaction.newBuilder() - .setRetryAbortsInternally(true) - .setTransactionRetryListeners(Collections.emptyList()) - .setDatabaseClient(client) - .withStatementExecutor(new StatementExecutor()) - .build(); - ParsedStatement parsedStatement = mock(ParsedStatement.class); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - ResultSet delegate1 = - ResultSets.forRows( - Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), - Arrays.asList( - Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), - Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build())); - ChecksumResultSet rs1 = - transaction.createChecksumResultSet(delegate1, parsedStatement, AnalyzeMode.NONE); - ResultSet delegate2 = - ResultSets.forRows( - Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), - Arrays.asList( - Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), - Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build())); - ChecksumResultSet rs2 = - transaction.createChecksumResultSet(delegate2, parsedStatement, AnalyzeMode.NONE); - // rs1 and rs2 are equal, rs3 contains the same rows, but in a different order - ResultSet delegate3 = - ResultSets.forRows( - Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), - Arrays.asList( - Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build(), - Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build())); - ChecksumResultSet rs3 = - transaction.createChecksumResultSet(delegate3, parsedStatement, AnalyzeMode.NONE); - - // rs4 contains the same rows as rs1 and rs2, but also an additional row - ResultSet delegate4 = - ResultSets.forRows( - Type.struct(StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string())), - Arrays.asList( - Struct.newBuilder().set("ID").to(1l).set("NAME").to("TEST 1").build(), - Struct.newBuilder().set("ID").to(2l).set("NAME").to("TEST 2").build(), - Struct.newBuilder().set("ID").to(3l).set("NAME").to("TEST 3").build())); - ChecksumResultSet rs4 = - transaction.createChecksumResultSet(delegate4, parsedStatement, AnalyzeMode.NONE); - - assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); - while (rs1.next() && rs2.next() && rs3.next() && rs4.next()) { - assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); - assertThat(rs1.getChecksum(), is(not(equalTo(rs3.getChecksum())))); - assertThat(rs1.getChecksum(), is(equalTo(rs4.getChecksum()))); - } - assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); - assertThat(rs1.getChecksum(), is(not(equalTo(rs3.getChecksum())))); - // rs4 contains one more row than rs1, but the last row of rs4 hasn't been consumed yet - assertThat(rs1.getChecksum(), is(equalTo(rs4.getChecksum()))); - assertThat(rs4.next(), is(true)); - assertThat(rs1.getChecksum(), is(not(equalTo(rs4.getChecksum())))); - } - - @Test - public void testChecksumResultSetWithArray() throws InterruptedException, ExecutionException { - DatabaseClient client = mock(DatabaseClient.class); - ReadWriteTransaction transaction = - ReadWriteTransaction.newBuilder() - .setRetryAbortsInternally(true) - .setTransactionRetryListeners(Collections.emptyList()) - .setDatabaseClient(client) - .withStatementExecutor(new StatementExecutor()) - .build(); - ParsedStatement parsedStatement = mock(ParsedStatement.class); - Statement statement = Statement.of("SELECT * FROM FOO"); - when(parsedStatement.getStatement()).thenReturn(statement); - ResultSet delegate1 = - ResultSets.forRows( - Type.struct( - StructField.of("ID", Type.int64()), - StructField.of("PRICES", Type.array(Type.int64()))), - Arrays.asList( - Struct.newBuilder() - .set("ID") - .to(1l) - .set("PRICES") - .toInt64Array(new long[] {1L, 2L}) - .build(), - Struct.newBuilder() - .set("ID") - .to(2l) - .set("PRICES") - .toInt64Array(new long[] {3L, 4L}) - .build())); - ChecksumResultSet rs1 = - transaction.createChecksumResultSet(delegate1, parsedStatement, AnalyzeMode.NONE); - ResultSet delegate2 = - ResultSets.forRows( - Type.struct( - StructField.of("ID", Type.int64()), - StructField.of("PRICES", Type.array(Type.int64()))), - Arrays.asList( - Struct.newBuilder() - .set("ID") - .to(1l) - .set("PRICES") - .toInt64Array(new long[] {1L, 2L}) - .build(), - Struct.newBuilder() - .set("ID") - .to(2l) - .set("PRICES") - .toInt64Array(new long[] {3L, 5L}) - .build())); - ChecksumResultSet rs2 = - transaction.createChecksumResultSet(delegate2, parsedStatement, AnalyzeMode.NONE); - - rs1.next(); - rs2.next(); - assertThat(rs1.getChecksum(), is(equalTo(rs2.getChecksum()))); - rs1.next(); - rs2.next(); - assertThat(rs1.getChecksum(), is(not(equalTo(rs2.getChecksum())))); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java deleted file mode 100644 index 4f90773cf657..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ReplaceableForwardingResultSetTest.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.ResultSets; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.Type.StructField; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ReplaceableForwardingResultSetTest { - - private ReplaceableForwardingResultSet createSubject() { - ResultSet delegate = - ResultSets.forRows( - Type.struct(StructField.of("test", Type.int64())), - Arrays.asList(Struct.newBuilder().set("test").to(1L).build())); - return new ReplaceableForwardingResultSet(delegate); - } - - @Test - public void testReplace() { - ResultSet delegate1 = - ResultSets.forRows( - Type.struct(StructField.of("test", Type.int64())), - Arrays.asList( - Struct.newBuilder().set("test").to(1L).build(), - Struct.newBuilder().set("test").to(2L).build())); - // First verify the behavior without replacing. - try (ResultSet rs = new ReplaceableForwardingResultSet(delegate1)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("test"), is(equalTo(1L))); - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("test"), is(equalTo(2L))); - assertThat(rs.next(), is(false)); - } - - delegate1 = - ResultSets.forRows( - Type.struct(StructField.of("test", Type.int64())), - Arrays.asList( - Struct.newBuilder().set("test").to(1L).build(), - Struct.newBuilder().set("test").to(2L).build())); - ResultSet delegate2 = - ResultSets.forRows( - Type.struct(StructField.of("test", Type.int64())), - Arrays.asList( - Struct.newBuilder().set("test").to(1L).build(), - Struct.newBuilder().set("test").to(3L).build())); - // Then verify the behavior with replacing. - try (ReplaceableForwardingResultSet rs = new ReplaceableForwardingResultSet(delegate1)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("test"), is(equalTo(1L))); - // Advance the delegate result set that will be used as replacement. - delegate2.next(); - // Replace the result set. - rs.replaceDelegate(delegate2); - // Verify that the replacement is being used. - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("test"), is(equalTo(3L))); - assertThat(rs.next(), is(false)); - } - } - - @Test - public void testMethodCallBeforeNext() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = Arrays.asList("getStats", "next", "close", "equals", "hashCode"); - ReplaceableForwardingResultSet subject = createSubject(); - // Test that all methods throw an IllegalStateException except the excluded methods when called - // before a call to ResultSet#next(). - callMethods(subject, excludedMethods, IllegalStateException.class); - } - - @Test - public void testMethodCallAfterClose() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = - Arrays.asList( - "getStats", - "next", - "close", - "getType", - "getColumnCount", - "getColumnIndex", - "getColumnType", - "ofResultSet", - "equals", - "hashCode"); - ReplaceableForwardingResultSet subject = createSubject(); - subject.next(); - subject.close(); - // Test that all methods throw an SpannerException except the excluded methods when called on a - // closed ResultSet. - callMethods(subject, excludedMethods, SpannerException.class); - } - - @Test - public void testMethodCallAfterNextHasReturnedFalse() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - List excludedMethods = - Arrays.asList( - "getStats", - "next", - "close", - "getType", - "getColumnCount", - "getColumnIndex", - "getColumnType", - "ofResultSet", - "equals", - "hashCode"); - ReplaceableForwardingResultSet subject = createSubject(); - subject.next(); - subject.next(); - // Test that all methods throw an IndexOutOfBoundsException except the excluded methods when - // called after a call to ResultSet#next() has returned false. - callMethods(subject, excludedMethods, IndexOutOfBoundsException.class); - } - - private void callMethods( - ReplaceableForwardingResultSet subject, - List excludedMethods, - Class expectedException) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - for (Method method : ReplaceableForwardingResultSet.class.getDeclaredMethods()) { - if (Modifier.isPublic(method.getModifiers()) && !excludedMethods.contains(method.getName())) { - boolean exception = false; - int numberOfParameters = method.getParameterTypes().length; - Class firstParameterType = null; - if (numberOfParameters == 1) { - firstParameterType = method.getParameterTypes()[0]; - } - try { - switch (numberOfParameters) { - case 0: - method.invoke(subject); - break; - case 1: - if (firstParameterType == String.class) { - method.invoke(subject, "test"); - } else if (firstParameterType == int.class) { - method.invoke(subject, 0); - } else { - fail("unknown parameter type"); - } - break; - default: - fail("method with more than 1 parameter is unknown"); - } - } catch (InvocationTargetException e) { - if (e.getCause().getClass().equals(expectedException)) { - // expected - exception = true; - } else { - throw e; - } - } - assertThat( - method.getName() + " did not throw an IllegalStateException", exception, is(true)); - } - } - } - - @Test - public void testValidMethodCall() - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - ResultSet delegate = mock(ResultSet.class); - when(delegate.next()).thenReturn(true, true, false); - try (ReplaceableForwardingResultSet subject = new ReplaceableForwardingResultSet(delegate)) { - subject.next(); - - // Cloud Spanner result sets use zero-based column indices, as opposed to the one-based column - // indices used by JDBC. The subject.getBoolean(0) and further zero-based calls below should - // therefore not cause any exceptions. - subject.getBoolean(0); - verify(delegate).getBoolean(0); - subject.getBoolean("test0"); - verify(delegate).getBoolean("test0"); - subject.getBooleanArray(1); - verify(delegate).getBooleanArray(1); - subject.getBooleanArray("test1"); - verify(delegate).getBooleanArray("test1"); - subject.getBooleanList(2); - verify(delegate).getBooleanList(2); - subject.getBooleanList("test2"); - verify(delegate).getBooleanList("test2"); - - subject.getBytes(0); - verify(delegate).getBytes(0); - subject.getBytes("test0"); - verify(delegate).getBytes("test0"); - subject.getBytesList(2); - verify(delegate).getBytesList(2); - subject.getBytesList("test2"); - verify(delegate).getBytesList("test2"); - - subject.getDate(0); - verify(delegate).getDate(0); - subject.getDate("test0"); - verify(delegate).getDate("test0"); - subject.getDateList(2); - verify(delegate).getDateList(2); - subject.getDateList("test2"); - verify(delegate).getDateList("test2"); - - subject.getDouble(0); - verify(delegate).getDouble(0); - subject.getDouble("test0"); - verify(delegate).getDouble("test0"); - subject.getDoubleArray(1); - verify(delegate).getDoubleArray(1); - subject.getDoubleArray("test1"); - verify(delegate).getDoubleArray("test1"); - subject.getDoubleList(2); - verify(delegate).getDoubleList(2); - subject.getDoubleList("test2"); - verify(delegate).getDoubleList("test2"); - - subject.getLong(0); - verify(delegate).getLong(0); - subject.getLong("test0"); - verify(delegate).getLong("test0"); - subject.getLongArray(1); - verify(delegate).getLongArray(1); - subject.getLongArray("test1"); - verify(delegate).getLongArray("test1"); - subject.getLongList(2); - verify(delegate).getLongList(2); - subject.getLongList("test2"); - verify(delegate).getLongList("test2"); - - subject.getString(0); - verify(delegate).getString(0); - subject.getString("test0"); - verify(delegate).getString("test0"); - subject.getStringList(2); - verify(delegate).getStringList(2); - subject.getStringList("test2"); - verify(delegate).getStringList("test2"); - - subject.getStructList(0); - subject.getStructList("test0"); - - subject.getTimestamp(0); - verify(delegate).getTimestamp(0); - subject.getTimestamp("test0"); - verify(delegate).getTimestamp("test0"); - subject.getTimestampList(2); - verify(delegate).getTimestampList(2); - subject.getTimestampList("test2"); - verify(delegate).getTimestampList("test2"); - - subject.getColumnCount(); - verify(delegate).getColumnCount(); - subject.getColumnIndex("test"); - verify(delegate).getColumnIndex("test"); - subject.getColumnType(100); - verify(delegate).getColumnType(100); - subject.getColumnType("test"); - verify(delegate).getColumnType("test"); - subject.getCurrentRowAsStruct(); - verify(delegate).getCurrentRowAsStruct(); - subject.getType(); - verify(delegate).getType(); - subject.isNull(50); - verify(delegate).isNull(50); - subject.isNull("test"); - verify(delegate).isNull("test"); - - while (subject.next()) { - // ignore - } - subject.getStats(); - verify(delegate).getStats(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java deleted file mode 100644 index de32e0f5bc0e..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetReadOnlyStalenessSqlScriptTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SetReadOnlyStalenessSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } - - @Test - public void testSetReadOnlyStalenessScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("SetReadOnlyStalenessTest.sql", getClass()); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java deleted file mode 100644 index 90afdf05bafb..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SetStatementTimeoutSqlScriptTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019 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.NoCredentials; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SetStatementTimeoutSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setUri(ConnectionImplTest.URI) - .setCredentials(NoCredentials.getInstance()) - .build())); - } - } - - @Test - public void testSetStatementTimeoutScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("SetStatementTimeoutTest.sql", getClass()); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java deleted file mode 100644 index 720567c2ea8b..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleUseTransactionTest.java +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Key; -import com.google.cloud.spanner.KeySet; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; -import com.google.cloud.spanner.Options.QueryOption; -import com.google.cloud.spanner.Options.ReadOption; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Struct; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionRunner; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import com.google.cloud.spanner.jdbc.StatementParser.StatementType; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import com.google.spanner.v1.ResultSetStats; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; -import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class SingleUseTransactionTest { - private static final String VALID_QUERY = "SELECT * FROM FOO"; - private static final String INVALID_QUERY = "SELECT * FROM BAR"; - private static final String SLOW_QUERY = "SELECT * FROM SLOW_TABLE"; - private static final String VALID_UPDATE = "UPDATE FOO SET BAR=1"; - private static final String INVALID_UPDATE = "UPDATE BAR SET FOO=1"; - private static final String SLOW_UPDATE = "UPDATE SLOW_TABLE SET FOO=1"; - private static final long VALID_UPDATE_COUNT = 99L; - - @Rule public ExpectedException exception = ExpectedException.none(); - - private final StatementExecutor executor = new StatementExecutor(); - - private enum CommitBehavior { - SUCCEED, - FAIL, - ABORT; - } - - private static class SimpleTransactionManager implements TransactionManager { - private TransactionState state; - private Timestamp commitTimestamp; - private TransactionContext txContext; - private CommitBehavior commitBehavior; - - private SimpleTransactionManager(TransactionContext txContext, CommitBehavior commitBehavior) { - this.txContext = txContext; - this.commitBehavior = commitBehavior; - } - - @Override - public TransactionContext begin() { - state = TransactionState.STARTED; - return txContext; - } - - @Override - public void commit() { - switch (commitBehavior) { - case SUCCEED: - commitTimestamp = Timestamp.now(); - state = TransactionState.COMMITTED; - break; - case FAIL: - state = TransactionState.COMMIT_FAILED; - throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "commit failed"); - case ABORT: - state = TransactionState.COMMIT_FAILED; - commitBehavior = CommitBehavior.SUCCEED; - throw SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, "commit aborted"); - default: - throw new IllegalStateException(); - } - } - - @Override - public void rollback() { - state = TransactionState.ROLLED_BACK; - } - - @Override - public TransactionContext resetForRetry() { - return txContext; - } - - @Override - public Timestamp getCommitTimestamp() { - return commitTimestamp; - } - - @Override - public TransactionState getState() { - return state; - } - - @Override - public void close() { - if (state != TransactionState.COMMITTED) { - state = TransactionState.ROLLED_BACK; - } - } - } - - private static final class SimpleReadOnlyTransaction - implements com.google.cloud.spanner.ReadOnlyTransaction { - private Timestamp readTimestamp = null; - private final TimestampBound staleness; - - private SimpleReadOnlyTransaction(TimestampBound staleness) { - this.staleness = staleness; - } - - @Override - public ResultSet read( - String table, KeySet keys, Iterable columns, ReadOption... options) { - return null; - } - - @Override - public ResultSet readUsingIndex( - String table, String index, KeySet keys, Iterable columns, ReadOption... options) { - return null; - } - - @Override - public Struct readRow(String table, Key key, Iterable columns) { - return null; - } - - @Override - public Struct readRowUsingIndex(String table, String index, Key key, Iterable columns) { - return null; - } - - @Override - public ResultSet executeQuery(Statement statement, QueryOption... options) { - if (statement.equals(Statement.of(VALID_QUERY))) { - if (readTimestamp == null) { - switch (staleness.getMode()) { - case STRONG: - readTimestamp = Timestamp.now(); - break; - case READ_TIMESTAMP: - readTimestamp = staleness.getReadTimestamp(); - break; - case MIN_READ_TIMESTAMP: - readTimestamp = staleness.getMinReadTimestamp(); - break; - case EXACT_STALENESS: - Calendar cal = Calendar.getInstance(); - cal.add( - Calendar.MILLISECOND, (int) -staleness.getExactStaleness(TimeUnit.MILLISECONDS)); - readTimestamp = Timestamp.of(cal.getTime()); - break; - case MAX_STALENESS: - cal = Calendar.getInstance(); - cal.add( - Calendar.MILLISECOND, (int) -staleness.getMaxStaleness(TimeUnit.MILLISECONDS)); - readTimestamp = Timestamp.of(cal.getTime()); - break; - default: - throw new IllegalStateException(); - } - } - return mock(ResultSet.class); - } else if (statement.equals(Statement.of(SLOW_QUERY))) { - try { - Thread.sleep(10L); - } catch (InterruptedException e) { - // ignore - } - readTimestamp = Timestamp.now(); - return mock(ResultSet.class); - } else if (statement.equals(Statement.of(INVALID_QUERY))) { - throw SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid query"); - } else { - throw new IllegalArgumentException(); - } - } - - @Override - public ResultSet analyzeQuery(Statement statement, QueryAnalyzeMode queryMode) { - ResultSet rs = executeQuery(statement); - when(rs.getStats()).thenReturn(ResultSetStats.getDefaultInstance()); - return rs; - } - - @Override - public void close() {} - - @Override - public Timestamp getReadTimestamp() { - return readTimestamp; - } - } - - private DdlClient createDefaultMockDdlClient() { - try { - DdlClient ddlClient = mock(DdlClient.class); - @SuppressWarnings("unchecked") - final OperationFuture operation = - mock(OperationFuture.class); - when(operation.get()).thenReturn(null); - when(ddlClient.executeDdl(anyString())).thenCallRealMethod(); - when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); - return ddlClient; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private SingleUseTransaction createSubject() { - return createSubject( - createDefaultMockDdlClient(), - false, - TimestampBound.strong(), - AutocommitDmlMode.TRANSACTIONAL, - CommitBehavior.SUCCEED, - 0L); - } - - private SingleUseTransaction createSubjectWithTimeout(long timeout) { - return createSubject( - createDefaultMockDdlClient(), - false, - TimestampBound.strong(), - AutocommitDmlMode.TRANSACTIONAL, - CommitBehavior.SUCCEED, - timeout); - } - - private SingleUseTransaction createSubject(AutocommitDmlMode dmlMode) { - return createSubject( - createDefaultMockDdlClient(), - false, - TimestampBound.strong(), - dmlMode, - CommitBehavior.SUCCEED, - 0L); - } - - private SingleUseTransaction createSubject(CommitBehavior commitBehavior) { - return createSubject( - createDefaultMockDdlClient(), - false, - TimestampBound.strong(), - AutocommitDmlMode.TRANSACTIONAL, - commitBehavior, - 0L); - } - - private SingleUseTransaction createDdlSubject(DdlClient ddlClient) { - return createSubject( - ddlClient, - false, - TimestampBound.strong(), - AutocommitDmlMode.TRANSACTIONAL, - CommitBehavior.SUCCEED, - 0L); - } - - private SingleUseTransaction createReadOnlySubject(TimestampBound staleness) { - return createSubject( - createDefaultMockDdlClient(), - true, - staleness, - AutocommitDmlMode.TRANSACTIONAL, - CommitBehavior.SUCCEED, - 0L); - } - - private SingleUseTransaction createSubject( - DdlClient ddlClient, - boolean readOnly, - TimestampBound staleness, - AutocommitDmlMode dmlMode, - final CommitBehavior commitBehavior, - long timeout) { - DatabaseClient dbClient = mock(DatabaseClient.class); - com.google.cloud.spanner.ReadOnlyTransaction singleUse = - new SimpleReadOnlyTransaction(staleness); - when(dbClient.singleUseReadOnlyTransaction(staleness)).thenReturn(singleUse); - - TransactionContext txContext = mock(TransactionContext.class); - when(txContext.executeUpdate(Statement.of(VALID_UPDATE))).thenReturn(VALID_UPDATE_COUNT); - when(txContext.executeUpdate(Statement.of(SLOW_UPDATE))) - .thenAnswer( - new Answer() { - @Override - public Long answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(10L); - return VALID_UPDATE_COUNT; - } - }); - when(txContext.executeUpdate(Statement.of(INVALID_UPDATE))) - .thenThrow( - SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update")); - SimpleTransactionManager txManager = new SimpleTransactionManager(txContext, commitBehavior); - when(dbClient.transactionManager()).thenReturn(txManager); - - when(dbClient.executePartitionedUpdate(Statement.of(VALID_UPDATE))) - .thenReturn(VALID_UPDATE_COUNT); - when(dbClient.executePartitionedUpdate(Statement.of(INVALID_UPDATE))) - .thenThrow( - SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update")); - - when(dbClient.readWriteTransaction()) - .thenAnswer( - new Answer() { - @Override - public TransactionRunner answer(InvocationOnMock invocation) throws Throwable { - TransactionRunner runner = - new TransactionRunner() { - private Timestamp commitTimestamp; - - @SuppressWarnings("unchecked") - @Override - public T run(TransactionCallable callable) { - if (commitBehavior == CommitBehavior.SUCCEED) { - this.commitTimestamp = Timestamp.now(); - return (T) Long.valueOf(1L); - } else if (commitBehavior == CommitBehavior.FAIL) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.UNKNOWN, "commit failed"); - } else { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.ABORTED, "commit aborted"); - } - } - - @Override - public Timestamp getCommitTimestamp() { - if (commitTimestamp == null) { - throw new IllegalStateException("no commit timestamp"); - } - return commitTimestamp; - } - - @Override - public TransactionRunner allowNestedTransaction() { - return this; - } - }; - return runner; - } - }); - - return SingleUseTransaction.newBuilder() - .setDatabaseClient(dbClient) - .setDdlClient(ddlClient) - .setAutocommitDmlMode(dmlMode) - .setReadOnly(readOnly) - .setReadOnlyStaleness(staleness) - .setStatementTimeout( - timeout == 0L - ? StatementExecutor.StatementTimeout.nullTimeout() - : StatementExecutor.StatementTimeout.of(timeout, TimeUnit.MILLISECONDS)) - .withStatementExecutor(executor) - .build(); - } - - private ParsedStatement createParsedDdl(String sql) { - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.DDL); - when(statement.getStatement()).thenReturn(Statement.of(sql)); - when(statement.getSqlWithoutComments()).thenReturn(sql); - return statement; - } - - private ParsedStatement createParsedQuery(String sql) { - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.QUERY); - when(statement.isQuery()).thenReturn(true); - when(statement.getStatement()).thenReturn(Statement.of(sql)); - return statement; - } - - private ParsedStatement createParsedUpdate(String sql) { - ParsedStatement statement = mock(ParsedStatement.class); - when(statement.getType()).thenReturn(StatementType.UPDATE); - when(statement.isUpdate()).thenReturn(true); - when(statement.getStatement()).thenReturn(Statement.of(sql)); - return statement; - } - - private List getTestTimestampBounds() { - return Arrays.asList( - TimestampBound.strong(), - TimestampBound.ofReadTimestamp(Timestamp.now()), - TimestampBound.ofMinReadTimestamp(Timestamp.now()), - TimestampBound.ofExactStaleness(1L, TimeUnit.SECONDS), - TimestampBound.ofMaxStaleness(100L, TimeUnit.MILLISECONDS)); - } - - @Test - public void testCommit() { - SingleUseTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.commit(); - } - - @Test - public void testRollback() { - SingleUseTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.rollback(); - } - - @Test - public void testRunBatch() { - SingleUseTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.runBatch(); - } - - @Test - public void testAbortBatch() { - SingleUseTransaction subject = createSubject(); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.abortBatch(); - } - - @Test - public void testExecuteDdl() { - String sql = "CREATE TABLE FOO"; - ParsedStatement ddl = createParsedDdl(sql); - DdlClient ddlClient = createDefaultMockDdlClient(); - SingleUseTransaction subject = createDdlSubject(ddlClient); - subject.executeDdl(ddl); - verify(ddlClient).executeDdl(sql); - } - - @Test - public void testExecuteQuery() { - for (TimestampBound staleness : getTestTimestampBounds()) { - for (AnalyzeMode analyzeMode : AnalyzeMode.values()) { - SingleUseTransaction subject = createReadOnlySubject(staleness); - ResultSet rs = subject.executeQuery(createParsedQuery(VALID_QUERY), analyzeMode); - assertThat(rs, is(notNullValue())); - assertThat(subject.getReadTimestamp(), is(notNullValue())); - assertThat( - subject.getState(), - is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - while (rs.next()) { - // just loop to the end to get stats - } - if (analyzeMode == AnalyzeMode.NONE) { - assertThat(rs.getStats(), is(nullValue())); - } else { - assertThat(rs.getStats(), is(notNullValue())); - } - } - } - for (TimestampBound staleness : getTestTimestampBounds()) { - SingleUseTransaction subject = createReadOnlySubject(staleness); - boolean expectedException = false; - try { - subject.executeQuery(createParsedQuery(INVALID_QUERY), AnalyzeMode.NONE); - } catch (SpannerException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertThat( - subject.getState(), - is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); - } - } - - @Test - public void testExecuteQueryWithOptionsTest() { - String sql = "SELECT * FROM FOO"; - QueryOption option = Options.prefetchChunks(10000); - ParsedStatement parsedStatement = mock(ParsedStatement.class); - when(parsedStatement.getType()).thenReturn(StatementType.QUERY); - when(parsedStatement.isQuery()).thenReturn(true); - Statement statement = Statement.of(sql); - when(parsedStatement.getStatement()).thenReturn(statement); - DatabaseClient client = mock(DatabaseClient.class); - com.google.cloud.spanner.ReadOnlyTransaction tx = - mock(com.google.cloud.spanner.ReadOnlyTransaction.class); - when(tx.executeQuery(Statement.of(sql), option)).thenReturn(mock(ResultSet.class)); - when(client.singleUseReadOnlyTransaction(TimestampBound.strong())).thenReturn(tx); - - SingleUseTransaction transaction = - SingleUseTransaction.newBuilder() - .setDatabaseClient(client) - .setDdlClient(mock(DdlClient.class)) - .setAutocommitDmlMode(AutocommitDmlMode.TRANSACTIONAL) - .withStatementExecutor(executor) - .setReadOnlyStaleness(TimestampBound.strong()) - .build(); - assertThat( - transaction.executeQuery(parsedStatement, AnalyzeMode.NONE, option), is(notNullValue())); - } - - @Test - public void testExecuteUpdate_Transactional_Valid() { - ParsedStatement update = createParsedUpdate(VALID_UPDATE); - SingleUseTransaction subject = createSubject(); - long updateCount = subject.executeUpdate(update); - assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - assertThat( - subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - } - - @Test - public void testExecuteUpdate_Transactional_Invalid() { - ParsedStatement update = createParsedUpdate(INVALID_UPDATE); - SingleUseTransaction subject = createSubject(); - exception.expect( - SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "invalid update")); - subject.executeUpdate(update); - } - - @Test - public void testExecuteUpdate_Transactional_Valid_FailedCommit() { - ParsedStatement update = createParsedUpdate(VALID_UPDATE); - SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); - exception.expect( - SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); - subject.executeUpdate(update); - } - - @Test - public void testExecuteUpdate_Transactional_Valid_AbortedCommit() { - ParsedStatement update = createParsedUpdate(VALID_UPDATE); - SingleUseTransaction subject = createSubject(CommitBehavior.ABORT); - // even though the transaction aborts at first, it will be retried and eventually succeed - long updateCount = subject.executeUpdate(update); - assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - assertThat( - subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - } - - @Test - public void testExecuteUpdate_Partitioned_Valid() { - ParsedStatement update = createParsedUpdate(VALID_UPDATE); - SingleUseTransaction subject = createSubject(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - long updateCount = subject.executeUpdate(update); - assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); - assertThat( - subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - } - - @Test - public void testExecuteUpdate_Partitioned_Invalid() { - ParsedStatement update = createParsedUpdate(INVALID_UPDATE); - SingleUseTransaction subject = createSubject(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - exception.expect( - SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "invalid update")); - subject.executeUpdate(update); - } - - @Test - public void testWrite() { - SingleUseTransaction subject = createSubject(); - subject.write(Mutation.newInsertBuilder("FOO").build()); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - assertThat( - subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - } - - @Test - public void testWriteFail() { - SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); - exception.expect( - SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); - subject.write(Mutation.newInsertBuilder("FOO").build()); - } - - @Test - public void testWriteIterable() { - SingleUseTransaction subject = createSubject(); - Mutation mutation = Mutation.newInsertBuilder("FOO").build(); - subject.write(Arrays.asList(mutation, mutation)); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - assertThat( - subject.getState(), is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMITTED)); - } - - @Test - public void testWriteIterableFail() { - SingleUseTransaction subject = createSubject(CommitBehavior.FAIL); - Mutation mutation = Mutation.newInsertBuilder("FOO").build(); - exception.expect( - SpannerExceptionMatcher.matchCodeAndMessage(ErrorCode.UNKNOWN, "commit failed")); - subject.write(Arrays.asList(mutation, mutation)); - } - - @Test - public void testMultiUse() { - for (TimestampBound staleness : getTestTimestampBounds()) { - SingleUseTransaction subject = createReadOnlySubject(staleness); - ResultSet rs = subject.executeQuery(createParsedQuery(VALID_QUERY), AnalyzeMode.NONE); - assertThat(rs, is(notNullValue())); - assertThat(subject.getReadTimestamp(), is(notNullValue())); - boolean expectedException = false; - try { - subject.executeQuery(createParsedQuery(VALID_QUERY), AnalyzeMode.NONE); - } catch (IllegalStateException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - } - - String sql = "CREATE TABLE FOO"; - ParsedStatement ddl = createParsedDdl(sql); - DdlClient ddlClient = createDefaultMockDdlClient(); - SingleUseTransaction subject = createDdlSubject(ddlClient); - subject.executeDdl(ddl); - verify(ddlClient).executeDdl(sql); - boolean expectedException = false; - try { - subject.executeDdl(ddl); - } catch (IllegalStateException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - - ParsedStatement update = createParsedUpdate(VALID_UPDATE); - subject = createSubject(); - long updateCount = subject.executeUpdate(update); - assertThat(updateCount, is(equalTo(VALID_UPDATE_COUNT))); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - expectedException = false; - try { - subject.executeUpdate(update); - } catch (IllegalStateException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - - subject = createSubject(); - subject.write(Mutation.newInsertBuilder("FOO").build()); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - expectedException = false; - try { - subject.write(Mutation.newInsertBuilder("FOO").build()); - } catch (IllegalStateException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - - subject = createSubject(); - Mutation mutation = Mutation.newInsertBuilder("FOO").build(); - subject.write(Arrays.asList(mutation, mutation)); - assertThat(subject.getCommitTimestamp(), is(notNullValue())); - expectedException = false; - try { - subject.write(Arrays.asList(mutation, mutation)); - } catch (IllegalStateException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - } - - @Test - public void testExecuteQueryWithTimeout() { - SingleUseTransaction subject = createSubjectWithTimeout(1L); - try { - subject.executeQuery(createParsedQuery(SLOW_QUERY), AnalyzeMode.NONE); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { - throw e; - } - } - assertThat( - subject.getState(), - is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getReadTimestamp(); - } - - @Test - public void testExecuteUpdateWithTimeout() { - SingleUseTransaction subject = createSubjectWithTimeout(1L); - boolean timeoutException = false; - try { - subject.executeUpdate(createParsedUpdate(SLOW_UPDATE)); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { - throw e; - } - timeoutException = true; - } - assertThat(timeoutException, is(true)); - assertThat( - subject.getState(), - is(com.google.cloud.spanner.jdbc.UnitOfWork.UnitOfWorkState.COMMIT_FAILED)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getCommitTimestamp(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java deleted file mode 100644 index 81cb883201e2..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerExceptionMatcher.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2019 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.ErrorCode; -import com.google.cloud.spanner.SpannerException; -import com.google.common.base.Preconditions; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; - -public final class SpannerExceptionMatcher extends BaseMatcher { - private final ErrorCode errorCode; - private final String message; - - public static SpannerExceptionMatcher matchCode(ErrorCode errorCode) { - Preconditions.checkNotNull(errorCode); - return new SpannerExceptionMatcher(errorCode, null); - } - - public static SpannerExceptionMatcher matchCodeAndMessage(ErrorCode errorCode, String message) { - Preconditions.checkNotNull(errorCode); - Preconditions.checkNotNull(message); - return new SpannerExceptionMatcher(errorCode, message); - } - - private SpannerExceptionMatcher(ErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } - - @Override - public boolean matches(Object item) { - if (item instanceof SpannerException) { - SpannerException exception = (SpannerException) item; - if (message == null) { - return exception.getErrorCode().equals(errorCode); - } - return exception.getErrorCode().equals(errorCode) - && exception.getMessage().equals(errorCode.name() + ": " + message); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(SpannerException.class.getName() + " with code " + errorCode.name()); - if (message != null) { - description.appendText(" - " + SpannerException.class.getName() + " with message " + message); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java deleted file mode 100644 index fd6e901eb018..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerPoolTest.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.auth.oauth2.GoogleCredentials; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.jdbc.ConnectionImpl.LeakedConnectionException; -import com.google.cloud.spanner.jdbc.SpannerPool.CheckAndCloseSpannersMode; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.logging.Handler; -import java.util.logging.Logger; -import java.util.logging.StreamHandler; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SpannerPoolTest { - private static final String URI = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - private ConnectionImpl connection1 = mock(ConnectionImpl.class); - private ConnectionImpl connection2 = mock(ConnectionImpl.class); - private ConnectionImpl connection3 = mock(ConnectionImpl.class); - private GoogleCredentials credentials1 = mock(GoogleCredentials.class); - private GoogleCredentials credentials2 = mock(GoogleCredentials.class); - private ConnectionOptions options1 = mock(ConnectionOptions.class); - private ConnectionOptions options2 = mock(ConnectionOptions.class); - private ConnectionOptions options3 = mock(ConnectionOptions.class); - private ConnectionOptions options4 = mock(ConnectionOptions.class); - - private SpannerPool createSubjectAndMocks() { - return createSubjectAndMocks(0L); - } - - private SpannerPool createSubjectAndMocks(long closeSpannerAfterMillisecondsUnused) { - SpannerPool pool = - new SpannerPool(closeSpannerAfterMillisecondsUnused) { - @Override - Spanner createSpanner(SpannerPoolKey key) { - return mock(Spanner.class); - } - }; - - when(options1.getCredentials()).thenReturn(credentials1); - when(options1.getProjectId()).thenReturn("test-project-1"); - when(options2.getCredentials()).thenReturn(credentials2); - when(options2.getProjectId()).thenReturn("test-project-1"); - - when(options3.getCredentials()).thenReturn(credentials1); - when(options3.getProjectId()).thenReturn("test-project-2"); - when(options4.getCredentials()).thenReturn(credentials2); - when(options4.getProjectId()).thenReturn("test-project-2"); - - return pool; - } - - @AfterClass - public static void closeSpannerPool() { - SpannerPool.closeSpannerPool(); - } - - @Test - public void testGetSpanner() { - SpannerPool pool = createSubjectAndMocks(); - Spanner spanner1; - Spanner spanner2; - - // assert equal - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options1, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - spanner1 = pool.getSpanner(options2, connection1); - spanner2 = pool.getSpanner(options2, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - spanner1 = pool.getSpanner(options3, connection1); - spanner2 = pool.getSpanner(options3, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - spanner1 = pool.getSpanner(options4, connection1); - spanner2 = pool.getSpanner(options4, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - - // assert not equal - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options2, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options3, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options4, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - spanner1 = pool.getSpanner(options2, connection1); - spanner2 = pool.getSpanner(options3, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - spanner1 = pool.getSpanner(options2, connection1); - spanner2 = pool.getSpanner(options4, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - spanner1 = pool.getSpanner(options3, connection1); - spanner2 = pool.getSpanner(options4, connection2); - assertThat(spanner1, not(equalTo(spanner2))); - } - - @Test - public void testRemoveConnection() { - SpannerPool pool = createSubjectAndMocks(); - Spanner spanner1; - Spanner spanner2; - - // assert equal - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options1, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - // one connection removed, assert that we would still get the same Spanner - pool.removeConnection(options1, connection1); - spanner1 = pool.getSpanner(options1, connection1); - assertThat(spanner1, is(equalTo(spanner2))); - // remove two connections, assert that we would still get the same Spanner, as Spanners are not - // directly closed and removed. - pool.removeConnection(options1, connection1); - pool.removeConnection(options1, connection2); - spanner1 = pool.getSpanner(options1, connection1); - assertThat(spanner1, is(equalTo(spanner2))); - // remove the last connection again - pool.removeConnection(options1, connection1); - } - - private static Logger log = Logger.getLogger(SpannerPool.class.getName()); - private static OutputStream logCapturingStream; - private static StreamHandler customLogHandler; - - private void attachLogCapturer() { - logCapturingStream = new ByteArrayOutputStream(); - Logger currentLogger = log; - Handler[] handlers = new Handler[0]; - while (handlers.length == 0 && currentLogger != null) { - handlers = currentLogger.getHandlers(); - currentLogger = currentLogger.getParent(); - } - if (handlers.length == 0) { - throw new IllegalStateException("no handlers found for logger"); - } - customLogHandler = new StreamHandler(logCapturingStream, handlers[0].getFormatter()); - log.addHandler(customLogHandler); - } - - public String getTestCapturedLog() throws IOException { - customLogHandler.flush(); - return logCapturingStream.toString(); - } - - @Test - public void testRemoveConnectionOptionsNotRegistered() throws IOException { - attachLogCapturer(); - final String expectedLogPart = "There is no Spanner registered for ConnectionOptions"; - SpannerPool pool = createSubjectAndMocks(); - pool.getSpanner(options1, connection1); - pool.removeConnection(options2, connection1); - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog.contains(expectedLogPart), is(true)); - } - - @Test - public void testRemoveConnectionConnectionNotRegistered() throws IOException { - attachLogCapturer(); - final String expectedLogPart = "There are no connections registered for ConnectionOptions"; - SpannerPool pool = createSubjectAndMocks(); - pool.getSpanner(options1, connection1); - pool.removeConnection(options1, connection2); - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog.contains(expectedLogPart), is(true)); - } - - @Test - public void testRemoveConnectionConnectionAlreadyRemoved() throws IOException { - attachLogCapturer(); - final String expectedLogPart = "There are no connections registered for ConnectionOptions"; - SpannerPool pool = createSubjectAndMocks(); - pool.getSpanner(options1, connection1); - pool.removeConnection(options1, connection1); - pool.removeConnection(options1, connection1); - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog.contains(expectedLogPart), is(true)); - } - - @Test - public void testCloseSpanner() throws IOException { - SpannerPool pool = createSubjectAndMocks(); - Spanner spanner = pool.getSpanner(options1, connection1); - // verify that closing is not possible until all connections have been removed - boolean exception = false; - try { - pool.checkAndCloseSpanners(); - } catch (SpannerException e) { - exception = e.getErrorCode() == ErrorCode.FAILED_PRECONDITION; - } - assertThat(exception, is(true)); - - // remove the connection and verify that it is possible to close - pool.removeConnection(options1, connection1); - pool.checkAndCloseSpanners(); - verify(spanner).close(); - - final String expectedLogPart = - "WARNING: There is/are 1 connection(s) still open. Close all connections before stopping the application"; - Spanner spanner2 = pool.getSpanner(options1, connection1); - pool.checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog.contains(expectedLogPart), is(true)); - verify(spanner2, never()).close(); - - // remove the connection and verify that it is possible to close - pool.removeConnection(options1, connection1); - pool.checkAndCloseSpanners(CheckAndCloseSpannersMode.WARN); - verify(spanner2).close(); - } - - @Test - public void testLeakedConnection() throws IOException { - ConnectionOptions options = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(); - // create an actual connection object but not in a try-with-resources block - Connection connection = options.getConnection(); - // try to close the application which should fail - try { - ConnectionOptions.closeSpanner(); - fail("missing expected exception"); - } catch (SpannerException e) { - assertThat(e.getErrorCode(), is(equalTo(ErrorCode.FAILED_PRECONDITION))); - } - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog.contains(LeakedConnectionException.class.getName()), is(true)); - assertThat(capturedLog.contains("testLeakedConnection"), is(true)); - // Now close the connection to avoid trouble with other test cases. - connection.close(); - } - - @Test - public void testCloseUnusedSpanners() { - SpannerPool pool = createSubjectAndMocks(); - Spanner spanner1; - Spanner spanner2; - Spanner spanner3; - - // create two connections that use the same Spanner - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options1, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - - // all spanners are in use, this should have no effect - pool.closeUnusedSpanners(-1L); - verify(spanner1, never()).close(); - - // close one connection. This should also have no effect. - pool.removeConnection(options1, connection1); - pool.closeUnusedSpanners(-1L); - verify(spanner1, never()).close(); - - // close the other connection as well, the Spanner object should now be closed. - pool.removeConnection(options1, connection2); - pool.closeUnusedSpanners(-1L); - verify(spanner1).close(); - - // create three connections that use two different Spanners - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options2, connection2); - spanner3 = pool.getSpanner(options2, connection3); - assertThat(spanner1, not(equalTo(spanner2))); - assertThat(spanner2, is(equalTo(spanner3))); - - // all spanners are in use, this should have no effect - pool.closeUnusedSpanners(-1L); - verify(spanner1, never()).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection1. That should also mark spanner1 as no longer in use - pool.removeConnection(options1, connection1); - pool.closeUnusedSpanners(-1L); - verify(spanner1).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection2. That should have no effect, as connection3 is still using spanner2 - pool.removeConnection(options2, connection2); - pool.closeUnusedSpanners(-1L); - verify(spanner1).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection3. Now all should be closed. - pool.removeConnection(options2, connection3); - pool.closeUnusedSpanners(-1L); - verify(spanner1).close(); - verify(spanner2).close(); - verify(spanner3).close(); - } - - /** Allow the automatic close test to be run multiple times to ensure it is stable */ - private static final int NUMBER_OF_AUTOMATIC_CLOSE_TEST_RUNS = 1; - - private static final long TEST_AUTOMATIC_CLOSE_TIMEOUT = 2L; - private static final long SLEEP_BEFORE_VERIFICATION = 100L; - - @Test - public void testAutomaticCloser() throws InterruptedException { - for (int testRun = 0; testRun < NUMBER_OF_AUTOMATIC_CLOSE_TEST_RUNS; testRun++) { - // create a pool that will close unused spanners after 5 milliseconds - SpannerPool pool = createSubjectAndMocks(TEST_AUTOMATIC_CLOSE_TIMEOUT); - Spanner spanner1; - Spanner spanner2; - Spanner spanner3; - - // create two connections that use the same Spanner - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options1, connection2); - assertThat(spanner1, is(equalTo(spanner2))); - - // all spanners are in use, this should have no effect - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1, never()).close(); - - // close one connection. This should also have no effect. - pool.removeConnection(options1, connection1); - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1, never()).close(); - - // close the other connection as well, the Spanner object should now be closed. - pool.removeConnection(options1, connection2); - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1).close(); - - // create three connections that use two different Spanners - spanner1 = pool.getSpanner(options1, connection1); - spanner2 = pool.getSpanner(options2, connection2); - spanner3 = pool.getSpanner(options2, connection3); - assertThat(spanner1, not(equalTo(spanner2))); - assertThat(spanner2, is(equalTo(spanner3))); - - // all spanners are in use, this should have no effect - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1, never()).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection1. That should also mark spanner1 as no longer in use - pool.removeConnection(options1, connection1); - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection2. That should have no effect, as connection3 is still using spanner2 - pool.removeConnection(options2, connection2); - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1).close(); - verify(spanner2, never()).close(); - verify(spanner3, never()).close(); - - // close connection3. Now all should be closed. - pool.removeConnection(options2, connection3); - Thread.sleep(SLEEP_BEFORE_VERIFICATION); - verify(spanner1).close(); - verify(spanner2).close(); - verify(spanner3).close(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java deleted file mode 100644 index df683b5ffb59..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlScriptVerifier.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; - -/** - * SQL script verifier implementation for Spanner {@link com.google.cloud.spanner.jdbc.Connection} - * - * @see AbstractSqlScriptVerifier for more information - */ -public class SqlScriptVerifier extends AbstractSqlScriptVerifier { - - static class ConnectionGenericStatementResult extends GenericStatementResult { - private final StatementResult result; - - private ConnectionGenericStatementResult(StatementResult result) { - this.result = result; - } - - @Override - protected ResultType getResultType() { - return result.getResultType(); - } - - @Override - protected GenericResultSet getResultSet() { - return new ConnectionGenericResultSet(result.getResultSet()); - } - - @Override - protected long getUpdateCount() { - return result.getUpdateCount(); - } - } - - static class ConnectionGenericResultSet extends GenericResultSet { - private final ResultSet resultSet; - - private ConnectionGenericResultSet(ResultSet resultSet) { - this.resultSet = resultSet; - } - - @Override - protected boolean next() { - return resultSet.next(); - } - - @Override - protected Object getValue(String col) { - if (resultSet.isNull(col)) { - return null; - } - Type type = resultSet.getColumnType(col); - switch (type.getCode()) { - case ARRAY: - return getArrayValue(resultSet, col, type.getArrayElementType()); - case BOOL: - return resultSet.getBoolean(col); - case BYTES: - return resultSet.getBytes(col); - case DATE: - return resultSet.getDate(col); - case FLOAT64: - return resultSet.getDouble(col); - case INT64: - return resultSet.getLong(col); - case STRING: - return resultSet.getString(col); - case TIMESTAMP: - return resultSet.getTimestamp(col); - case STRUCT: - throw new IllegalArgumentException("type struct not supported"); - } - throw new IllegalArgumentException("unknown type: " + type); - } - - private Object getArrayValue(ResultSet rs, String col, Type type) { - switch (type.getCode()) { - case BOOL: - return rs.getBooleanList(col); - case BYTES: - return rs.getBytesList(col); - case DATE: - return rs.getDateList(col); - case FLOAT64: - return rs.getDoubleList(col); - case INT64: - return rs.getLongList(col); - case STRING: - return rs.getStringList(col); - case STRUCT: - return rs.getStructList(col); - case TIMESTAMP: - return rs.getTimestampList(col); - case ARRAY: - throw new IllegalArgumentException("array of array not supported"); - } - throw new IllegalArgumentException("unknown type: " + type); - } - - @Override - protected int getColumnCount() throws Exception { - return resultSet.getColumnCount(); - } - - @Override - protected Object getFirstValue() throws Exception { - return getValue(resultSet.getType().getStructFields().get(0).getName()); - } - } - - public static class SpannerGenericConnection extends GenericConnection { - private final Connection connection; - - public static SpannerGenericConnection of(Connection connection) { - return new SpannerGenericConnection(connection); - } - - private SpannerGenericConnection(Connection connection) { - this.connection = connection; - } - - @Override - protected GenericStatementResult execute(String sql) { - return new ConnectionGenericStatementResult(connection.execute(Statement.of(sql))); - } - - @Override - public void close() throws Exception { - if (this.connection != null) { - this.connection.close(); - } - } - } - - public SqlScriptVerifier() { - this(null); - } - - public SqlScriptVerifier(GenericConnectionProvider provider) { - super(provider); - } - - @Override - protected void verifyExpectedException( - String statement, Exception e, String code, String messagePrefix) { - assertThat(e instanceof SpannerException, is(true)); - SpannerException spannerException = (SpannerException) e; - assertThat( - statement + " resulted in " + spannerException.toString(), - spannerException.getErrorCode(), - is(equalTo(ErrorCode.valueOf(code)))); - if (messagePrefix != null) { - assertThat( - statement, - e.getMessage(), - startsWith(messagePrefix.substring(1, messagePrefix.length() - 1))); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java deleted file mode 100644 index 875ca0a08e48..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SqlTestScriptsGenerator.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019 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; - -/** Class that runs all generators of SQL test scripts for the Connection API */ -public class SqlTestScriptsGenerator { - - /** Main method for generating the test script */ - public static void main(String[] args) throws Exception { - ClientSideStatementsTest.generateTestScript(); - ConnectionImplGeneratedSqlScriptTest.generateTestScript(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java deleted file mode 100644 index 1344a0f33346..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementParserTest.java +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.StatementParser.ParsedStatement; -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.junit.Test; - -public class StatementParserTest { - public static final String COPYRIGHT_PATTERN = - "\\/\\*\n" - + " \\* Copyright \\d{4} 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"; - private final StatementParser parser = StatementParser.INSTANCE; - private static final Pattern EXPECT_PATTERN = Pattern.compile("(?is)\\s*(?:@EXPECT)\\s+'(.*)'"); - - @Test - public void testRemoveComments() { - List statements = readStatementsFromFile("CommentsTest.sql"); - String currentlyExpected = ""; - for (String statement : statements) { - String sql = statement.trim(); - if (sql.startsWith("@EXPECT")) { - Matcher matcher = EXPECT_PATTERN.matcher(sql); - if (matcher.matches()) { - currentlyExpected = matcher.group(1); - } else { - throw new IllegalArgumentException("Unknown @EXPECT statement: " + sql); - } - } else { - assertThat( - StatementParser.removeCommentsAndTrim(statement), is(equalTo(currentlyExpected))); - } - } - - assertThat(StatementParser.removeCommentsAndTrim(""), is(equalTo(""))); - assertThat( - StatementParser.removeCommentsAndTrim("SELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); - assertThat( - StatementParser.removeCommentsAndTrim("-- This is a one line comment\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); - assertThat( - StatementParser.removeCommentsAndTrim( - "/* This is a simple multi line comment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); - assertThat( - StatementParser.removeCommentsAndTrim( - "/* This is a \nmulti line comment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); - assertThat( - StatementParser.removeCommentsAndTrim( - "/* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); - } - - @Test - public void testStatementWithCommentContainingSlash() { - String sql = - "/*\n" - + " * Script for testing invalid/unrecognized statements\n" - + " */\n" - + "\n" - + "-- MERGE into test comment MERGE -- \n" - + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO Singers s\n" - + "/*** test ****/" - + "USING (VALUES (1, 'John', 'Doe')) v\n" - + "ON v.column1 = s.SingerId\n" - + "WHEN NOT MATCHED \n" - + " INSERT VALUES (v.column1, v.column2, v.column3)\n" - + "WHEN MATCHED\n" - + " UPDATE SET FirstName = v.column2,\n" - + " LastName = v.column3;"; - String sqlWithoutComments = - "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO Singers s\n" - + "USING (VALUES (1, 'John', 'Doe')) v\n" - + "ON v.column1 = s.SingerId\n" - + "WHEN NOT MATCHED \n" - + " INSERT VALUES (v.column1, v.column2, v.column3)\n" - + "WHEN MATCHED\n" - + " UPDATE SET FirstName = v.column2,\n" - + " LastName = v.column3"; - ParsedStatement statement = parser.parse(Statement.of(sql)); - assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); - } - - @Test - public void testStatementWithCommentContainingSlashAndNoAsteriskOnNewLine() { - String sql = - "/*\n" - + " * Script for testing invalid/unrecognized statements\n" - + " foo bar baz" - + " */\n" - + "\n" - + "-- MERGE INTO test comment MERGE\n" - + "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO Singers s\n" - + "USING (VALUES (1, 'John', 'Doe')) v\n" - + "ON v.column1 = s.SingerId\n" - + "-- test again --\n" - + "WHEN NOT MATCHED \n" - + " INSERT VALUES (v.column1, v.column2, v.column3)\n" - + "WHEN MATCHED\n" - + " UPDATE SET FirstName = v.column2,\n" - + " LastName = v.column3;"; - String sqlWithoutComments = - "@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement'\n" - + "MERGE INTO Singers s\n" - + "USING (VALUES (1, 'John', 'Doe')) v\n" - + "ON v.column1 = s.SingerId\n" - + "\nWHEN NOT MATCHED \n" - + " INSERT VALUES (v.column1, v.column2, v.column3)\n" - + "WHEN MATCHED\n" - + " UPDATE SET FirstName = v.column2,\n" - + " LastName = v.column3"; - ParsedStatement statement = parser.parse(Statement.of(sql)); - assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); - } - - @Test - public void testStatementWithHashTagSingleLineComment() { - assertThat( - parser - .parse(Statement.of("# this is a comment\nselect * from foo")) - .getSqlWithoutComments(), - is(equalTo("select * from foo"))); - assertThat( - parser.parse(Statement.of("select * from foo\n#this is a comment")).getSqlWithoutComments(), - is(equalTo("select * from foo"))); - assertThat( - parser - .parse(Statement.of("select *\nfrom foo # this is a comment\nwhere bar=1")) - .getSqlWithoutComments(), - is(equalTo("select *\nfrom foo \nwhere bar=1"))); - } - - @Test - public void testIsDdlStatement() { - assertFalse(parser.isDdlStatement("")); - assertFalse(parser.isDdlStatement("random text")); - assertFalse(parser.isDdlStatement("CREATETABLE")); - assertFalse(parser.isDdlStatement("CCREATE TABLE")); - assertFalse(parser.isDdlStatement("SELECT 1")); - assertFalse(parser.isDdlStatement("SELECT FOO FROM BAR")); - assertFalse(parser.isDdlStatement("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); - assertFalse(parser.isDdlStatement("UPDATE FOO SET NAME='NAME' WHERE ID=1")); - assertFalse(parser.isDdlStatement("DELETE FROM FOO")); - - assertTrue( - parser.isDdlStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertTrue(parser.isDdlStatement("alter table foo add Description string(100)")); - assertTrue(parser.isDdlStatement("drop table foo")); - assertTrue(parser.isDdlStatement("Create index BAR on foo (name)")); - - assertTrue( - parser - .parse( - Statement.of( - "\t\tCREATE\n\t TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "\n\n\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "-- this is a comment\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "-- SELECT in a single line comment \nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/* SELECT in a multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/** SELECT in a java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - } - - @Test - public void testIsQuery() { - assertFalse(parser.isQuery("")); - assertFalse(parser.isQuery("random text")); - assertFalse(parser.isQuery("SELECT1")); - assertFalse(parser.isQuery("SSELECT 1")); - assertTrue(parser.isQuery("SELECT 1")); - assertTrue(parser.isQuery("select 1")); - assertTrue(parser.isQuery("SELECT foo FROM bar WHERE id=@id")); - assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); - assertFalse(parser.isQuery("UPDATE FOO SET NAME='NAME' WHERE ID=1")); - assertFalse(parser.isQuery("DELETE FROM FOO")); - assertFalse(parser.isQuery("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertFalse(parser.isQuery("alter table foo add Description string(100)")); - assertFalse(parser.isQuery("drop table foo")); - assertFalse(parser.isQuery("Create index BAR on foo (name)")); - assertTrue(parser.isQuery("select * from foo")); - assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); - - assertTrue( - parser.isQuery( - "WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" - + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" - + "SELECT * FROM subQ1\n" - + "UNION ALL\n" - + "SELECT * FROM subQ2")); - assertTrue( - parser.isQuery( - "with subQ1 AS (SELECT SchoolID FROM Roster),\n" - + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" - + "select * FROM subQ1\n" - + "UNION ALL\n" - + "SELECT * FROM subQ2")); - assertTrue( - parser - .parse( - Statement.of( - "-- this is a comment\nwith foo as (select * from bar)\nselect * from foo")) - .isQuery()); - - assertTrue(parser.parse(Statement.of("-- this is a comment\nselect * from foo")).isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nSELECT ID, NAME\nFROM\tTEST\n\tWHERE ID=1")) - .isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nselect max(id) from test")) - .isQuery()); - assertTrue( - parser.parse(Statement.of("-- INSERT in a single line comment \n select 1")).isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/* UPDATE in a multi line comment\n* with more information on the next line\n*/\nSELECT 1")) - .isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/** DELETE in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- UPDATE test\nSELECT 1")) - .isQuery()); - } - - @Test - public void testQueryHints() { - // Valid query hints. - assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); - assertTrue(parser.isQuery("@ {JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); - assertTrue(parser.isQuery("@{ JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); - assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN } SELECT * FROM PersonsTable")); - assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN}\nSELECT * FROM PersonsTable")); - assertTrue(parser.isQuery("@{\nJOIN_METHOD = HASH_JOIN \t}\n\t SELECT * FROM PersonsTable")); - assertTrue( - parser.isQuery( - "@{JOIN_METHOD=HASH_JOIN}\n -- Single line comment\nSELECT * FROM PersonsTable")); - assertTrue( - parser.isQuery( - "@{JOIN_METHOD=HASH_JOIN}\n /* Multi line comment\n with more comments\n */SELECT * FROM PersonsTable")); - assertTrue( - parser.isQuery( - "@{JOIN_METHOD=HASH_JOIN} WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" - + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" - + "SELECT * FROM subQ1\n" - + "UNION ALL\n" - + "SELECT * FROM subQ2")); - - // Invalid query hints. - assertFalse(parser.isQuery("@{JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); - assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); - assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); - } - - @Test - public void testIsUpdate_InsertStatements() { - assertFalse(parser.isUpdateStatement("")); - assertFalse(parser.isUpdateStatement("random text")); - assertFalse(parser.isUpdateStatement("INSERTINTO FOO (ID) VALUES (1)")); - assertFalse(parser.isUpdateStatement("IINSERT INTO FOO (ID) VALUES (1)")); - assertTrue(parser.isUpdateStatement("INSERT INTO FOO (ID) VALUES (1)")); - assertTrue(parser.isUpdateStatement("insert into foo (id) values (1)")); - assertTrue(parser.isUpdateStatement("INSERT into Foo (id)\nSELECT id FROM bar WHERE id=@id")); - assertFalse(parser.isUpdateStatement("SELECT 1")); - assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); - assertFalse( - parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); - assertFalse(parser.isUpdateStatement("drop table foo")); - assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); - assertFalse(parser.isUpdateStatement("select * from foo")); - assertTrue(parser.isUpdateStatement("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); - assertTrue( - parser - .parse(Statement.of("-- this is a comment\ninsert into foo (id) values (1)")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nINSERT INTO FOO\n(ID)\tVALUES\n\t(1)")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nInsert intO foo (id) select 1")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "-- SELECT in a single line comment \n insert into foo (id) values (1)")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nINSERT INTO FOO (ID) VALUES (1)")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\ninsert into foo (id) values (1)")) - .isUpdate()); - } - - @Test - public void testIsUpdate_UpdateStatements() { - assertFalse(parser.isUpdateStatement("")); - assertFalse(parser.isUpdateStatement("random text")); - assertFalse(parser.isUpdateStatement("UPDATEFOO SET NAME='foo' WHERE ID=1")); - assertFalse(parser.isUpdateStatement("UUPDATE FOO SET NAME='foo' WHERE ID=1")); - assertTrue(parser.isUpdateStatement("UPDATE FOO SET NAME='foo' WHERE ID=1")); - assertTrue(parser.isUpdateStatement("update foo set name='foo' where id=1")); - assertTrue( - parser.isUpdateStatement("update foo set name=\n(SELECT name FROM bar WHERE id=@id)")); - assertFalse(parser.isUpdateStatement("SELECT 1")); - assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); - assertFalse( - parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); - assertFalse(parser.isUpdateStatement("drop table foo")); - assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); - assertFalse(parser.isUpdateStatement("select * from foo")); - assertTrue( - parser.isUpdateStatement( - "UPDATE FOO SET NAME=(SELECT NAME FROM FOO) WHERE ID=(SELECT ID+1 FROM FOO)")); - - assertTrue( - parser - .parse(Statement.of("-- this is a comment\nupdate foo set name='foo' where id=@id")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nUPDATE FOO\nSET NAME=\t'foo'\n\tWHERE ID=1")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nUPDATE FOO SET NAME=(select 'bar')")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of("-- SELECT in a single line comment \n update foo set name='bar'")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nUPDATE FOO SET NAME='BAR'")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\nupdate foo set bar='foo'")) - .isUpdate()); - } - - @Test - public void testIsUpdate_DeleteStatements() { - assertFalse(parser.isUpdateStatement("")); - assertFalse(parser.isUpdateStatement("random text")); - assertFalse(parser.isUpdateStatement("DELETEFROM FOO WHERE ID=1")); - assertFalse(parser.isUpdateStatement("DDELETE FROM FOO WHERE ID=1")); - assertTrue(parser.isUpdateStatement("DELETE FROM FOO WHERE ID=1")); - assertTrue(parser.isUpdateStatement("delete from foo where id=1")); - assertTrue( - parser.isUpdateStatement( - "delete from foo where name=\n(SELECT name FROM bar WHERE id=@id)")); - assertFalse(parser.isUpdateStatement("SELECT 1")); - assertFalse(parser.isUpdateStatement("SELECT NAME FROM FOO WHERE ID=1")); - assertFalse( - parser.isUpdateStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertFalse(parser.isUpdateStatement("alter table foo add Description string(100)")); - assertFalse(parser.isUpdateStatement("drop table foo")); - assertFalse(parser.isUpdateStatement("Create index BAR on foo (name)")); - assertFalse(parser.isUpdateStatement("select * from foo")); - assertTrue( - parser.isUpdateStatement( - "UPDATE FOO SET NAME=(SELECT NAME FROM FOO) WHERE ID=(SELECT ID+1 FROM FOO)")); - - assertTrue( - parser - .parse(Statement.of("-- this is a comment\ndelete from foo where id=@id")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nDELETE FROM FOO\n\n\tWHERE ID=1")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nDELETE FROM FOO WHERE NAME=(select 'bar')")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "-- SELECT in a single line comment \n delete from foo where name='bar'")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/* CREATE in a multi line comment\n* with more information on the next line\n*/\nDELETE FROM FOO WHERE NAME='BAR'")) - .isUpdate()); - assertTrue( - parser - .parse( - Statement.of( - "/** DROP in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- SELECT test\ndelete from foo where bar='foo'")) - .isUpdate()); - } - - @Test - public void testParseStatementsWithNoParameters() throws CompileException { - for (ClientSideStatementImpl statement : getAllStatements()) { - if (statement.getSetStatement() == null) { - for (String testStatement : statement.getExampleStatements()) { - testParseStatement(testStatement, statement.getClass()); - } - } - } - } - - @Test - public void testParseStatementsWithOneParameterAtTheEnd() throws CompileException { - for (ClientSideStatementImpl statement : getAllStatements()) { - if (statement.getSetStatement() != null) { - for (String testStatement : statement.getExampleStatements()) { - testParseStatementWithOneParameterAtTheEnd(testStatement, statement.getClass()); - } - } - } - } - - private Set getAllStatements() throws CompileException { - return ClientSideStatements.INSTANCE.getCompiledStatements(); - } - - private void assertParsing( - String value, Class statementClass) { - assertThat(this.parse(value), is(equalTo(statementClass))); - } - - private void testParseStatement( - String statement, Class statementClass) { - assertThat( - "\"" + statement + "\" should be " + statementClass.getName(), - this.parse(statement), - is(equalTo(statementClass))); - assertParsing(upper(statement), statementClass); - assertParsing(lower(statement), statementClass); - assertParsing(withSpaces(statement), statementClass); - assertParsing(withTabs(statement), statementClass); - assertParsing(withLinefeeds(statement), statementClass); - assertParsing(withLeadingSpaces(statement), statementClass); - assertParsing(withLeadingTabs(statement), statementClass); - assertParsing(withLeadingLinefeeds(statement), statementClass); - assertParsing(withTrailingSpaces(statement), statementClass); - assertParsing(withTrailingTabs(statement), statementClass); - assertParsing(withTrailingLinefeeds(statement), statementClass); - - assertThat(parse(withInvalidPrefix(statement)), is(nullValue())); - assertThat(parse(withInvalidSuffix(statement)), is(nullValue())); - - assertNull(parse(withPrefix("%", statement))); - assertNull(parse(withPrefix("_", statement))); - assertNull(parse(withPrefix("&", statement))); - assertNull(parse(withPrefix("$", statement))); - assertNull(parse(withPrefix("@", statement))); - assertNull(parse(withPrefix("!", statement))); - assertNull(parse(withPrefix("*", statement))); - assertNull(parse(withPrefix("(", statement))); - assertNull(parse(withPrefix(")", statement))); - - assertThat( - withSuffix("%", statement) + " is not a valid statement", - parse(withSuffix("%", statement)), - is(nullValue())); - assertNull(parse(withSuffix("_", statement))); - assertNull(parse(withSuffix("&", statement))); - assertNull(parse(withSuffix("$", statement))); - assertNull(parse(withSuffix("@", statement))); - assertNull(parse(withSuffix("!", statement))); - assertNull(parse(withSuffix("*", statement))); - assertNull(parse(withSuffix("(", statement))); - assertNull(parse(withSuffix(")", statement))); - } - - private void testParseStatementWithOneParameterAtTheEnd( - String statement, Class statementClass) { - assertThat( - "\"" + statement + "\" should be " + statementClass.getName(), - this.parse(statement), - is(equalTo(statementClass))); - assertParsing(upper(statement), statementClass); - assertParsing(lower(statement), statementClass); - assertParsing(withSpaces(statement), statementClass); - assertParsing(withTabs(statement), statementClass); - assertParsing(withLinefeeds(statement), statementClass); - assertParsing(withLeadingSpaces(statement), statementClass); - assertParsing(withLeadingTabs(statement), statementClass); - assertParsing(withLeadingLinefeeds(statement), statementClass); - assertParsing(withTrailingSpaces(statement), statementClass); - assertParsing(withTrailingTabs(statement), statementClass); - assertParsing(withTrailingLinefeeds(statement), statementClass); - - assertNull(parse(withInvalidPrefix(statement))); - assertParsing(withInvalidSuffix(statement), statementClass); - - assertNull(parse(withPrefix("%", statement))); - assertNull(parse(withPrefix("_", statement))); - assertNull(parse(withPrefix("&", statement))); - assertNull(parse(withPrefix("$", statement))); - assertNull(parse(withPrefix("@", statement))); - assertNull(parse(withPrefix("!", statement))); - assertNull(parse(withPrefix("*", statement))); - assertNull(parse(withPrefix("(", statement))); - assertNull(parse(withPrefix(")", statement))); - - assertParsing(withSuffix("%", statement), statementClass); - assertParsing(withSuffix("_", statement), statementClass); - assertParsing(withSuffix("&", statement), statementClass); - assertParsing(withSuffix("$", statement), statementClass); - assertParsing(withSuffix("@", statement), statementClass); - assertParsing(withSuffix("!", statement), statementClass); - assertParsing(withSuffix("*", statement), statementClass); - assertParsing(withSuffix("(", statement), statementClass); - assertParsing(withSuffix(")", statement), statementClass); - } - - @SuppressWarnings("unchecked") - private Class parse(String statement) { - ClientSideStatementImpl optional = parser.parseClientSideStatement(statement); - return optional != null ? (Class) optional.getClass() : null; - } - - private String upper(String statement) { - return statement.toUpperCase(); - } - - private String lower(String statement) { - return statement.toLowerCase(); - } - - private String withLeadingSpaces(String statement) { - return " " + statement; - } - - private String withLeadingTabs(String statement) { - return "\t\t\t" + statement; - } - - private String withLeadingLinefeeds(String statement) { - return "\n\n\n" + statement; - } - - private String withTrailingSpaces(String statement) { - return statement + " "; - } - - private String withTrailingTabs(String statement) { - return statement + "\t\t"; - } - - private String withTrailingLinefeeds(String statement) { - return statement + "\n\n"; - } - - private String withSpaces(String statement) { - return statement.replaceAll(" ", " "); - } - - private String withTabs(String statement) { - return statement.replaceAll(" ", "\t"); - } - - private String withLinefeeds(String statement) { - return statement.replaceAll(" ", "\n"); - } - - private String withInvalidPrefix(String statement) { - return "foo " + statement; - } - - private String withInvalidSuffix(String statement) { - return statement + " bar"; - } - - private String withPrefix(String prefix, String statement) { - return prefix + statement; - } - - private String withSuffix(String suffix, String statement) { - return statement + suffix; - } - - private List readStatementsFromFile(String filename) { - File file = new File(getClass().getResource(filename).getFile()); - StringBuilder builder = new StringBuilder(); - try (Scanner scanner = new Scanner(file)) { - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - builder.append(line).append("\n"); - } - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - String script = builder.toString().replaceAll(COPYRIGHT_PATTERN, ""); - String[] array = script.split(";"); - List res = new ArrayList<>(array.length); - for (String statement : array) { - if (statement != null && statement.trim().length() > 0) { - res.add(statement); - } - } - return res; - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java deleted file mode 100644 index ea0b751a61c8..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResultImplTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.jdbc.StatementResult.ClientSideStatementType; -import com.google.cloud.spanner.jdbc.StatementResult.ResultType; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class StatementResultImplTest { - @Rule public ExpectedException exception = ExpectedException.none(); - - @Test - public void testNoResultGetResultSet() { - StatementResult subject = StatementResultImpl.noResult(); - assertThat(subject.getResultType(), is(equalTo(ResultType.NO_RESULT))); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getResultSet(); - } - - @Test - public void testNoResultGetUpdateCount() { - StatementResult subject = StatementResultImpl.noResult(); - assertThat(subject.getResultType(), is(equalTo(ResultType.NO_RESULT))); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getUpdateCount(); - } - - @Test - public void testResultSetGetResultSet() { - StatementResult subject = StatementResultImpl.of(mock(ResultSet.class)); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat(subject.getResultSet(), is(notNullValue())); - } - - @Test - public void testResultSetGetUpdateCount() { - StatementResult subject = StatementResultImpl.of(mock(ResultSet.class)); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getUpdateCount(); - } - - @Test - public void testUpdateCountGetResultSet() { - StatementResult subject = StatementResultImpl.of(1L); - assertThat(subject.getResultType(), is(equalTo(ResultType.UPDATE_COUNT))); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - subject.getResultSet(); - } - - @Test - public void testUpdateCountGetUpdateCount() { - StatementResult subject = StatementResultImpl.of(1L); - assertThat(subject.getResultType(), is(equalTo(ResultType.UPDATE_COUNT))); - assertThat(subject.getUpdateCount(), is(notNullValue())); - } - - @Test - public void testBooleanResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet("foo", Boolean.TRUE, ClientSideStatementType.SHOW_AUTOCOMMIT); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), is(equalTo(ClientSideStatementType.SHOW_AUTOCOMMIT))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat(subject.getResultSet().getBoolean("foo"), is(true)); - assertThat(subject.getResultSet().next(), is(false)); - } - - @Test - public void testLongResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet("foo", 10L, ClientSideStatementType.SHOW_READ_ONLY_STALENESS); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), - is(equalTo(ClientSideStatementType.SHOW_READ_ONLY_STALENESS))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat(subject.getResultSet().getLong("foo"), is(equalTo(10L))); - assertThat(subject.getResultSet().next(), is(false)); - } - - @Test - public void testLongArrayResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet( - "foo", new long[] {1L, 2L, 3L}, ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), - is(equalTo(ClientSideStatementType.SHOW_RETRY_ABORTS_INTERNALLY))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat(subject.getResultSet().getLongArray("foo"), is(equalTo(new long[] {1L, 2L, 3L}))); - assertThat(subject.getResultSet().next(), is(false)); - } - - @Test - public void testStringResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet( - "foo", "bar", ClientSideStatementType.SHOW_READ_ONLY_STALENESS); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), - is(equalTo(ClientSideStatementType.SHOW_READ_ONLY_STALENESS))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat(subject.getResultSet().getString("foo"), is(equalTo("bar"))); - assertThat(subject.getResultSet().next(), is(false)); - } - - @Test - public void testEnumResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet( - "foo", TransactionMode.READ_ONLY_TRANSACTION, ClientSideStatementType.SHOW_READONLY); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), is(equalTo(ClientSideStatementType.SHOW_READONLY))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat( - subject.getResultSet().getString("foo"), - is(equalTo(TransactionMode.READ_ONLY_TRANSACTION.toString()))); - assertThat(subject.getResultSet().next(), is(false)); - } - - @Test - public void testTimestampResultSetGetResultSet() { - StatementResult subject = - StatementResultImpl.resultSet( - "foo", - Timestamp.ofTimeSecondsAndNanos(10L, 10), - ClientSideStatementType.SHOW_READ_TIMESTAMP); - assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET))); - assertThat( - subject.getClientSideStatementType(), - is(equalTo(ClientSideStatementType.SHOW_READ_TIMESTAMP))); - assertThat(subject.getResultSet(), is(notNullValue())); - assertThat(subject.getResultSet().next(), is(true)); - assertThat( - subject.getResultSet().getTimestamp("foo"), - is(equalTo(Timestamp.ofTimeSecondsAndNanos(10L, 10)))); - assertThat(subject.getResultSet().next(), is(false)); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java deleted file mode 100644 index 5a6fb740c859..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementTimeoutTest.java +++ /dev/null @@ -1,1192 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.api.core.ApiFuture; -import com.google.api.core.ApiFutures; -import com.google.api.gax.longrunning.OperationFuture; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.DatabaseClient; -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.ReadOnlyTransaction; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Spanner; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.TransactionManager.TransactionState; -import com.google.cloud.spanner.jdbc.AbstractConnectionImplTest.ConnectionConsumer; -import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Matchers; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -@RunWith(JUnit4.class) -public class StatementTimeoutTest { - private static final String URI = - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; - private static final String SLOW_SELECT = "SELECT foo FROM bar"; - private static final String INVALID_SELECT = "SELECT FROM bar"; // missing columns / * - private static final String FAST_SELECT = "SELECT fast_column FROM fast_table"; - private static final String SLOW_DDL = "CREATE TABLE foo"; - private static final String FAST_DDL = "CREATE TABLE fast_table"; - private static final String SLOW_UPDATE = "UPDATE foo SET col1=1 WHERE id=2"; - private static final String FAST_UPDATE = "UPDATE fast_table SET foo=1 WHERE bar=2"; - - /** Execution time for statements that have been defined as slow. */ - private static final long EXECUTION_TIME_SLOW_STATEMENT = 10_000L; - /** - * This timeout should be high enough that it will never be exceeded, even on a slow build - * environment, but still significantly lower than the expected execution time of the slow - * statements. - */ - private static final long TIMEOUT_FOR_FAST_STATEMENTS = 1000L; - - /** - * This timeout should be low enough that it will not make the test case unnecessarily slow, but - * still high enough that it would normally not be exceeded for a statement that is executed - * directly. - */ - private static final long TIMEOUT_FOR_SLOW_STATEMENTS = 20L; - /** - * The number of milliseconds to wait before cancelling a query should be high enough to not cause - * flakiness on a slow environment, but at the same time low enough that it does not slow down the - * test case unnecessarily. - */ - private static final int WAIT_BEFORE_CANCEL = 100; - - private enum CommitRollbackBehavior { - FAST, - SLOW_COMMIT, - SLOW_ROLLBACK; - } - - @Rule public ExpectedException expected = ExpectedException.none(); - - private static final class DelayedQueryExecution implements Answer { - @Override - public ResultSet answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); - return mock(ResultSet.class); - } - } - - private DdlClient createDefaultMockDdlClient(final long waitForMillis) { - try { - DdlClient ddlClient = mock(DdlClient.class); - UpdateDatabaseDdlMetadata metadata = UpdateDatabaseDdlMetadata.getDefaultInstance(); - ApiFuture futureMetadata = ApiFutures.immediateFuture(metadata); - @SuppressWarnings("unchecked") - final OperationFuture operation = - mock(OperationFuture.class); - if (waitForMillis > 0L) { - when(operation.get()) - .thenAnswer( - new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(waitForMillis); - return null; - } - }); - } else { - when(operation.get()).thenReturn(null); - } - when(operation.getMetadata()).thenReturn(futureMetadata); - when(ddlClient.executeDdl(SLOW_DDL)).thenCallRealMethod(); - when(ddlClient.executeDdl(anyListOf(String.class))).thenReturn(operation); - - @SuppressWarnings("unchecked") - final OperationFuture fastOperation = - mock(OperationFuture.class); - when(fastOperation.isDone()).thenReturn(true); - when(fastOperation.get()).thenReturn(null); - when(fastOperation.getMetadata()).thenReturn(futureMetadata); - when(ddlClient.executeDdl(FAST_DDL)).thenReturn(fastOperation); - when(ddlClient.executeDdl(Arrays.asList(FAST_DDL))).thenReturn(fastOperation); - return ddlClient; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private ConnectionImpl createConnection(ConnectionOptions options) { - return createConnection(options, CommitRollbackBehavior.FAST); - } - - /** - * Creates a connection on which the statements {@link StatementTimeoutTest#SLOW_SELECT} and - * {@link StatementTimeoutTest#SLOW_DDL} will take at least 10,000 milliseconds - */ - private ConnectionImpl createConnection( - ConnectionOptions options, final CommitRollbackBehavior commitRollbackBehavior) { - DatabaseClient dbClient = mock(DatabaseClient.class); - Spanner spanner = mock(Spanner.class); - SpannerPool spannerPool = mock(SpannerPool.class); - when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) - .thenReturn(spanner); - DdlClient ddlClient = createDefaultMockDdlClient(EXECUTION_TIME_SLOW_STATEMENT); - final ResultSet invalidResultSet = mock(ResultSet.class); - when(invalidResultSet.next()) - .thenThrow( - SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "invalid query")); - - ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); - when(singleUseReadOnlyTx.executeQuery(Statement.of(SLOW_SELECT))) - .thenAnswer(new DelayedQueryExecution()); - when(singleUseReadOnlyTx.executeQuery(Statement.of(FAST_SELECT))) - .thenReturn(mock(ResultSet.class)); - when(singleUseReadOnlyTx.executeQuery(Statement.of(INVALID_SELECT))) - .thenReturn(invalidResultSet); - when(dbClient.singleUseReadOnlyTransaction(Matchers.any(TimestampBound.class))) - .thenReturn(singleUseReadOnlyTx); - - ReadOnlyTransaction readOnlyTx = mock(ReadOnlyTransaction.class); - when(readOnlyTx.executeQuery(Statement.of(SLOW_SELECT))) - .thenAnswer(new DelayedQueryExecution()); - when(readOnlyTx.executeQuery(Statement.of(FAST_SELECT))).thenReturn(mock(ResultSet.class)); - when(readOnlyTx.executeQuery(Statement.of(INVALID_SELECT))).thenReturn(invalidResultSet); - when(dbClient.readOnlyTransaction(Matchers.any(TimestampBound.class))).thenReturn(readOnlyTx); - - when(dbClient.transactionManager()) - .thenAnswer( - new Answer() { - @Override - public TransactionManager answer(InvocationOnMock invocation) throws Throwable { - TransactionManager txManager = mock(TransactionManager.class); - when(txManager.getState()).thenReturn(null, TransactionState.STARTED); - when(txManager.begin()) - .thenAnswer( - new Answer() { - @Override - public TransactionContext answer(InvocationOnMock invocation) - throws Throwable { - TransactionContext txContext = mock(TransactionContext.class); - when(txContext.executeQuery(Statement.of(SLOW_SELECT))) - .thenAnswer(new DelayedQueryExecution()); - when(txContext.executeQuery(Statement.of(FAST_SELECT))) - .thenReturn(mock(ResultSet.class)); - when(txContext.executeQuery(Statement.of(INVALID_SELECT))) - .thenReturn(invalidResultSet); - when(txContext.executeUpdate(Statement.of(SLOW_UPDATE))) - .thenAnswer( - new Answer() { - @Override - public Long answer(InvocationOnMock invocation) - throws Throwable { - Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); - return 1L; - } - }); - when(txContext.executeUpdate(Statement.of(FAST_UPDATE))).thenReturn(1L); - return txContext; - } - }); - if (commitRollbackBehavior == CommitRollbackBehavior.SLOW_COMMIT) { - doAnswer( - new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); - return null; - } - }) - .when(txManager) - .commit(); - } - if (commitRollbackBehavior == CommitRollbackBehavior.SLOW_ROLLBACK) { - doAnswer( - new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); - return null; - } - }) - .when(txManager) - .rollback(); - } - - return txManager; - } - }); - when(dbClient.executePartitionedUpdate(Statement.of(FAST_UPDATE))).thenReturn(1L); - when(dbClient.executePartitionedUpdate(Statement.of(SLOW_UPDATE))) - .thenAnswer( - new Answer() { - @Override - public Long answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(EXECUTION_TIME_SLOW_STATEMENT); - return 1L; - } - }); - return new ConnectionImpl(options, spannerPool, ddlClient, dbClient); - } - - @Test - public void testTimeoutExceptionReadOnlyAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testTimeoutExceptionReadOnlyAutocommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionReadOnlyTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testTimeoutExceptionReadOnlyTransactionMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // do a rollback without any chance of a timeout - connection.clearStatementTimeout(); - connection.rollback(); - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitSlowUpdate() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.execute(Statement.of(SLOW_UPDATE)); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitSlowUpdateMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.execute(Statement.of(SLOW_UPDATE)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new update that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.execute(Statement.of(FAST_UPDATE)).getUpdateCount(), is(equalTo(1L))); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitSlowCommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(), - CommitRollbackBehavior.SLOW_COMMIT)) { - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - // First verify that the fast update does not timeout when in transactional mode (as it is the - // commit that is slow). - connection.setAutocommit(false); - connection.execute(Statement.of(FAST_UPDATE)); - connection.rollback(); - - // Then verify that the update does timeout when executed in autocommit mode, as the commit - // gRPC call will be slow. - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - connection.setAutocommit(true); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.execute(Statement.of(FAST_UPDATE)); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitSlowCommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(), - CommitRollbackBehavior.SLOW_COMMIT)) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.execute(Statement.of(FAST_UPDATE)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionReadWriteAutocommitPartitioned() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC); - // first verify that the fast update does not timeout - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - connection.execute(Statement.of(FAST_UPDATE)); - - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.execute(Statement.of(SLOW_UPDATE)); - } - } - - @Test - public void testTimeoutExceptionReadWriteTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testTimeoutExceptionReadWriteTransactionMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - // Assert that multiple statements after each other will timeout the first time, and then - // throw a SpannerException with code FAILED_PRECONDITION. - boolean timedOut = false; - for (int i = 0; i < 2; i++) { - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - if (i == 0) { - assertThat(e.getErrorCode(), is(equalTo(ErrorCode.DEADLINE_EXCEEDED))); - timedOut = true; - } else { - assertThat(e.getErrorCode(), is(equalTo(ErrorCode.FAILED_PRECONDITION))); - } - } - } - assertThat(timedOut, is(true)); - // do a rollback without any chance of a timeout - connection.clearStatementTimeout(); - connection.rollback(); - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionReadWriteTransactionalSlowCommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(), - CommitRollbackBehavior.SLOW_COMMIT)) { - connection.setAutocommit(false); - - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - connection.executeQuery(Statement.of(FAST_SELECT)); - - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.commit(); - } - } - - @Test - public void testTimeoutExceptionReadWriteTransactionalSlowRollback() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(), - CommitRollbackBehavior.SLOW_ROLLBACK)) { - connection.setAutocommit(false); - - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - connection.executeQuery(Statement.of(FAST_SELECT)); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.rollback(); - } - } - - private static final class ConnectionReadOnlyAutocommit implements ConnectionConsumer { - @Override - public void accept(Connection t) { - t.setReadOnly(true); - } - } - - @Test - public void testInterruptedExceptionReadOnlyAutocommit() - throws InterruptedException, ExecutionException { - testInterruptedException(new ConnectionReadOnlyAutocommit()); - } - - private static final class ConnectionReadOnlyTransactional implements ConnectionConsumer { - @Override - public void accept(Connection t) { - t.setReadOnly(true); - t.setAutocommit(false); - } - } - - @Test - public void testInterruptedExceptionReadOnlyTransactional() - throws InterruptedException, ExecutionException { - testInterruptedException(new ConnectionReadOnlyTransactional()); - } - - private static final class ConnectionReadWriteAutocommit implements ConnectionConsumer { - @Override - public void accept(Connection t) {} - } - - @Test - public void testInterruptedExceptionReadWriteAutocommit() - throws InterruptedException, ExecutionException { - testInterruptedException(new ConnectionReadWriteAutocommit()); - } - - private static final class ConnectionReadWriteTransactional implements ConnectionConsumer { - @Override - public void accept(Connection t) { - t.setAutocommit(false); - } - } - - @Test - public void testInterruptedExceptionReadWriteTransactional() - throws InterruptedException, ExecutionException { - testInterruptedException(new ConnectionReadWriteTransactional()); - } - - private void testInterruptedException(final ConnectionConsumer consumer) - throws InterruptedException, ExecutionException { - ExecutorService executor = Executors.newSingleThreadExecutor(); - Future future = - executor.submit( - new Callable() { - @Override - public Boolean call() throws Exception { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - consumer.accept(connection); - connection.setStatementTimeout(10000L, TimeUnit.MILLISECONDS); - - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - if (e.getErrorCode() == ErrorCode.CANCELLED) { - return Boolean.TRUE; - } else { - return Boolean.FALSE; - } - } - return Boolean.FALSE; - } - }); - // wait a little bit to ensure that the task has started - Thread.sleep(10L); - executor.shutdownNow(); - assertThat(future.get(), is(true)); - } - - @Test - public void testInvalidQueryReadOnlyAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setUri(URI) - .setCredentials(NoCredentials.getInstance()) - .build())) { - connection.setReadOnly(true); - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); - connection.executeQuery(Statement.of(INVALID_SELECT)); - } - } - - @Test - public void testInvalidQueryReadOnlyTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); - connection.executeQuery(Statement.of(INVALID_SELECT)); - } - } - - @Test - public void testInvalidQueryReadWriteAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); - connection.executeQuery(Statement.of(INVALID_SELECT)); - } - } - - @Test - public void testInvalidQueryReadWriteTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.INVALID_ARGUMENT)); - connection.executeQuery(Statement.of(INVALID_SELECT)); - } - } - - @Test - public void testCancelReadOnlyAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testCancelReadOnlyAutocommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - boolean cancelled = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - cancelled = e.getErrorCode() == ErrorCode.CANCELLED; - } - assertThat(cancelled, is(true)); - - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testCancelReadOnlyTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setAutocommit(false); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testCancelReadOnlyTransactionalMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setReadOnly(true); - connection.setAutocommit(false); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - boolean cancelled = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - cancelled = e.getErrorCode() == ErrorCode.CANCELLED; - } - assertThat(cancelled, is(true)); - - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - // rollback and do another fast query - connection.rollback(); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testCancelReadWriteAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testCancelReadWriteAutocommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - boolean cancelled = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - cancelled = e.getErrorCode() == ErrorCode.CANCELLED; - } - assertThat(cancelled, is(true)); - - // try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testCancelReadWriteAutocommitSlowUpdate() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.execute(Statement.of(SLOW_UPDATE)); - } - } - - @Test - public void testCancelReadWriteAutocommitSlowCommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build(), - CommitRollbackBehavior.SLOW_COMMIT)) { - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.execute(Statement.of(FAST_UPDATE)); - } - } - - @Test - public void testCancelReadWriteTransactional() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.executeQuery(Statement.of(SLOW_SELECT)); - } - } - - @Test - public void testCancelReadWriteTransactionalMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - boolean cancelled = false; - try { - connection.executeQuery(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - cancelled = e.getErrorCode() == ErrorCode.CANCELLED; - } - assertThat(cancelled, is(true)); - // Rollback the transaction as it is no longer usable. - connection.rollback(); - - // Try to do a new query that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.executeQuery(Statement.of(FAST_SELECT)), is(notNullValue())); - } - } - - @Test - public void testCancelDdlBatch() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.startBatchDdl(); - connection.execute(Statement.of(SLOW_DDL)); - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.runBatch(); - } - } - - @Test - public void testCancelDdlAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - Executors.newSingleThreadScheduledExecutor() - .schedule( - new Runnable() { - @Override - public void run() { - connection.cancel(); - } - }, - WAIT_BEFORE_CANCEL, - TimeUnit.MILLISECONDS); - - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.CANCELLED)); - connection.execute(Statement.of(SLOW_DDL)); - } - } - - @Test - public void testTimeoutExceptionDdlAutocommit() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.execute(Statement.of(SLOW_DDL)); - } - } - - @Test - public void testTimeoutExceptionDdlAutocommitMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - try { - connection.execute(Statement.of(SLOW_DDL)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new DDL statement that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); - } - } - - @Test - public void testTimeoutExceptionDdlBatch() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.startBatchDdl(); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - - // the following statement will NOT timeout as the statement is only buffered locally - connection.execute(Statement.of(SLOW_DDL)); - // the commit sends the statement to the server and should timeout - expected.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - connection.runBatch(); - } - } - - @Test - public void testTimeoutExceptionDdlBatchMultipleStatements() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - connection.setAutocommit(false); - connection.setStatementTimeout(TIMEOUT_FOR_SLOW_STATEMENTS, TimeUnit.MILLISECONDS); - - // assert that multiple statements after each other also time out - for (int i = 0; i < 2; i++) { - boolean timedOut = false; - connection.startBatchDdl(); - connection.execute(Statement.of(SLOW_DDL)); - try { - connection.runBatch(); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - // try to do a new DDL statement that is fast. - connection.setStatementTimeout(TIMEOUT_FOR_FAST_STATEMENTS, TimeUnit.MILLISECONDS); - connection.startBatchDdl(); - assertThat(connection.execute(Statement.of(FAST_DDL)), is(notNullValue())); - connection.runBatch(); - } - } - - @Test - public void testTimeoutDifferentTimeUnits() { - try (Connection connection = - createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(URI) - .build())) { - for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { - connection.setStatementTimeout(1L, unit); - boolean timedOut = false; - try { - connection.execute(Statement.of(SLOW_SELECT)); - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java deleted file mode 100644 index 60df4fddaa84..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionModeConverterTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019 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.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.jdbc.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.jdbc.ClientSideStatementValueConverters.TransactionModeConverter; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class TransactionModeConverterTest { - - @Test - public void testConvert() throws CompileException { - String allowedValues = - ReadOnlyStalenessConverterTest.getAllowedValues(TransactionModeConverter.class); - assertThat(allowedValues, is(notNullValue())); - TransactionModeConverter converter = new TransactionModeConverter(allowedValues); - assertThat( - converter.convert("read write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat( - converter.convert("READ WRITE"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat( - converter.convert("Read Write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat( - converter.convert("read write"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat( - converter.convert("READ\nWRITE"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - assertThat( - converter.convert("Read\tWrite"), is(equalTo(TransactionMode.READ_WRITE_TRANSACTION))); - - assertThat(converter.convert("read only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat(converter.convert("READ ONLY"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat(converter.convert("Read Only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat( - converter.convert("read only"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat(converter.convert("READ\nONLY"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - assertThat(converter.convert("Read\tOnly"), is(equalTo(TransactionMode.READ_ONLY_TRANSACTION))); - - assertThat(converter.convert(""), is(nullValue())); - assertThat(converter.convert(" "), is(nullValue())); - assertThat(converter.convert("random string"), is(nullValue())); - assertThat(converter.convert("read_write"), is(nullValue())); - assertThat(converter.convert("Read_Write"), is(nullValue())); - assertThat(converter.convert("READ_WRITE"), is(nullValue())); - assertThat(converter.convert("read_only"), is(nullValue())); - assertThat(converter.convert("Read_Only"), is(nullValue())); - assertThat(converter.convert("READ_ONLY"), is(nullValue())); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java deleted file mode 100644 index 1349636600c3..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITBulkConnectionTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Test opening multiple generic (not JDBC) Spanner connections. */ -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -public class ITBulkConnectionTest extends ITAbstractSpannerTest { - private static final int NUMBER_OF_TEST_CONNECTIONS = 250; - - @Test - public void testBulkCreateConnectionsSingleThreaded() { - List connections = new ArrayList<>(); - for (int i = 0; i < NUMBER_OF_TEST_CONNECTIONS; i++) { - connections.add(createConnection()); - } - for (ITConnection connection : connections) { - try (ResultSet rs = connection.executeQuery(Statement.of("select 1"))) { - assertThat(rs.next(), is(true)); - assertThat(connection.getReadTimestamp(), is(notNullValue())); - } - } - for (ITConnection connection : connections) { - connection.close(); - } - // close Spanner instances explicitly. This method will throw an exception if there are any - // connections still open in the pool - closeSpanner(); - } - - @Test - public void testBulkCreateConnectionsMultiThreaded() throws InterruptedException { - ExecutorService executor = Executors.newFixedThreadPool(50); - for (int i = 0; i < NUMBER_OF_TEST_CONNECTIONS; i++) { - executor.submit( - new Callable() { - @Override - public Void call() throws Exception { - try (ITConnection connection = createConnection()) { - try (ResultSet rs = connection.executeQuery(Statement.of("select 1"))) { - assertThat(rs.next(), is(true)); - assertThat(connection.getReadTimestamp(), is(notNullValue())); - } - } - return null; - } - }); - } - executor.shutdown(); - executor.awaitTermination(10L, TimeUnit.SECONDS); - // close Spanner instances explicitly. This method will throw an exception if there are any - // connections still open in the pool - closeSpanner(); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java deleted file mode 100644 index 1642c26bf57f..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITDdlTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Execute DDL statements using the generic connection API. */ -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -public class ITDdlTest extends ITAbstractSpannerTest { - - @Test - public void testSqlScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class); - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index 4fe79a3febd6..0b192127d7ef 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -17,9 +17,9 @@ package com.google.cloud.spanner.jdbc.it; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 8e72aa24b7c9..0516a1448bf0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -21,9 +21,9 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlException; -import com.google.cloud.spanner.jdbc.SpannerPool; import com.google.rpc.Code; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.sql.Connection; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 163f555e0fb1..db5c84246d68 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -18,10 +18,10 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import java.math.BigInteger; import java.sql.Connection; import java.sql.SQLException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index fdc8bb890d03..e6a296285afc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -22,10 +22,10 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 29b0b054d5e9..244e9f1db4de 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -17,10 +17,10 @@ package com.google.cloud.spanner.jdbc.it; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import java.sql.Connection; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index 87f5abec468d..07a1ab8f9559 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -22,10 +22,10 @@ import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java deleted file mode 100644 index 599a9cf6595d..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadOnlySpannerTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.Options; -import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SpannerExceptionMatcher; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import java.math.BigInteger; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This test class runs a SQL script for testing a connection in read-only mode, but also contains a - * number of separate test methods that cannot be expressed in a pure SQL test. - */ -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -public class ITReadOnlySpannerTest extends ITAbstractSpannerTest { - private static final Logger logger = Logger.getLogger(ITReadOnlySpannerTest.class.getName()); - private static final long TEST_ROWS_COUNT = 1000L; - - @Rule public ExpectedException exception = ExpectedException.none(); - - @Override - protected void appendConnectionUri(StringBuilder url) { - url.append(";readOnly=true"); - } - - @Before - public void createTestTables() throws Exception { - try (ITConnection connection = createConnection()) { - if (!(tableExists(connection, "NUMBERS") && tableExists(connection, "PRIME_NUMBERS"))) { - // create tables - SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile( - "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class); - - // fill tables with data - connection.setAutocommit(false); - connection.setReadOnly(false); - for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { - connection.bufferedWrite( - Mutation.newInsertBuilder("NUMBERS") - .set("number") - .to(number) - .set("name") - .to(Long.toBinaryString(number)) - .build()); - } - for (long number = 1L; number <= TEST_ROWS_COUNT; number++) { - if (BigInteger.valueOf(number).isProbablePrime(Integer.MAX_VALUE)) { - connection.bufferedWrite( - Mutation.newInsertBuilder("PRIME_NUMBERS") - .set("prime_number") - .to(number) - .set("binary_representation") - .to(Long.toBinaryString(number)) - .build()); - } - } - connection.commit(); - } - } - } - - @Test - public void testSqlScript() throws Exception { - // Wait 100ms to ensure that staleness tests in the script succeed. - Thread.sleep(100L); - SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); - } - - @Test - public void testStatementTimeoutTransactional() throws Exception { - try (ITConnection connection = createConnection()) { - connection.beginTransaction(); - connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - try (ResultSet rs = - connection.executeQuery( - Statement.of( - "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) {} - // should never be reached - connection.commit(); - } - } - - @Test - public void testStatementTimeoutTransactionalMultipleStatements() throws Exception { - long startTime = System.currentTimeMillis(); - try (ITConnection connection = createConnection()) { - connection.beginTransaction(); - for (int i = 0; i < 3; i++) { - boolean timedOut = false; - connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); - try (ResultSet rs = - connection.executeQuery( - Statement.of( - "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) { - } catch (SpannerException e) { - timedOut = e.getErrorCode() == ErrorCode.DEADLINE_EXCEEDED; - } - assertThat(timedOut, is(true)); - } - connection.commit(); - } - long endTime = System.currentTimeMillis(); - long executionTime = endTime - startTime; - if (executionTime > 25L) { - logger.warning("Total test execution time exceeded 25 milliseconds: " + executionTime); - } else { - logger.info("Total test execution time: " + executionTime); - } - } - - @Test - public void testStatementTimeoutAutocommit() throws Exception { - try (ITConnection connection = createConnection()) { - assertThat(connection.isAutocommit(), is(true)); - connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.DEADLINE_EXCEEDED)); - try (ResultSet rs = - connection.executeQuery( - Statement.of( - "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"))) {} - } - } - - @Test - public void testAnalyzeQuery() { - try (ITConnection connection = createConnection()) { - for (QueryAnalyzeMode mode : QueryAnalyzeMode.values()) { - try (ResultSet rs = - connection.analyzeQuery( - Statement.of( - "SELECT (SELECT COUNT(*) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"), - mode)) { - // next has not yet returned false - assertThat(rs.getStats(), is(nullValue())); - while (rs.next()) { - // ignore - } - assertThat(rs.getStats(), is(notNullValue())); - } - } - } - } - - @Test - public void testQueryWithOptions() { - try (ITConnection connection = createConnection()) { - try (ResultSet rs = - connection.executeQuery( - Statement.of( - "SELECT (SELECT CAST(COUNT(*) AS FLOAT64) FROM PRIME_NUMBERS)/(SELECT COUNT(*) FROM NUMBERS) AS PRIME_NUMBER_RATIO"), - Options.prefetchChunks(100000))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getDouble(0), is(notNullValue())); - assertThat(rs.next(), is(false)); - } - } - } - - @Test - public void testMultipleOpenResultSets() throws InterruptedException { - try (ITConnection connection = createConnection()) { - final ResultSet rs1 = connection.executeQuery(Statement.of("SELECT * FROM PRIME_NUMBERS")); - final ResultSet rs2 = connection.executeQuery(Statement.of("SELECT * FROM NUMBERS")); - ExecutorService exec = Executors.newFixedThreadPool(2); - exec.submit( - new Runnable() { - @Override - public void run() { - while (rs1.next()) {} - } - }); - exec.submit( - new Runnable() { - @Override - public void run() { - while (rs2.next()) {} - } - }); - exec.shutdown(); - exec.awaitTermination(1000L, TimeUnit.SECONDS); - rs1.close(); - rs2.close(); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java deleted file mode 100644 index 14834cc69319..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITReadWriteAutocommitSpannerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; - -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerBatchUpdateException; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.junit.runners.MethodSorters; - -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class ITReadWriteAutocommitSpannerTest extends ITAbstractSpannerTest { - - @Rule public ExpectedException exception = ExpectedException.none(); - - @Override - protected void appendConnectionUri(StringBuilder uri) { - uri.append(";autocommit=true"); - } - - @Override - public boolean doCreateDefaultTestTable() { - return true; - } - - @Test - public void test01_SqlScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile( - "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class); - } - - @Test - public void test02_WriteMutation() throws Exception { - try (ITConnection connection = createConnection()) { - connection.write( - Mutation.newInsertBuilder("TEST").set("ID").to(9999L).set("NAME").to("FOO").build()); - assertThat(connection.getCommitTimestamp(), is(notNullValue())); - } - } - - @Test - public void test03_MultipleStatements_WithTimeouts() throws InterruptedException { - try (ITConnection connection = createConnection()) { - // do an insert that should succeed - assertThat( - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1000, 'test')")), - is(equalTo(1L))); - // check that the insert succeeded - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1000"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("test"))); - assertThat(rs.next(), is(false)); - } - - // do an update that should time out - connection.setStatementTimeout(1L, TimeUnit.MILLISECONDS); - try { - connection.executeUpdate(Statement.of("UPDATE TEST SET NAME='test18' WHERE ID=1000")); - } catch (SpannerException e) { - if (e.getErrorCode() != ErrorCode.DEADLINE_EXCEEDED) { - throw e; - } - } - // remove the timeout setting - connection.clearStatementTimeout(); - - // do a delete that should succeed - connection.executeUpdate(Statement.of("DELETE FROM TEST WHERE ID=1000")); - // verify that the delete did succeed - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1000"))) { - assertThat(rs.next(), is(false)); - } - } - } - - @Test - public void test04_BatchUpdate() { - try (ITConnection connection = createConnection()) { - long[] updateCounts = - connection.executeBatchUpdate( - Arrays.asList( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (10, 'Batch value 1')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (11, 'Batch value 2')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (12, 'Batch value 3')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (13, 'Batch value 4')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (14, 'Batch value 5')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (15, 'Batch value 6')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (16, 'Batch value 7')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (17, 'Batch value 8')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (18, 'Batch value 9')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (19, 'Batch value 10')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (20, 'Batch value 11')"))); - assertThat( - updateCounts, is(equalTo(new long[] {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L}))); - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=10 AND ID<=20"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(0), is(equalTo(11L))); - } - } - } - - @Test - public void test05_BatchUpdateWithException() { - try (ITConnection con1 = createConnection(); - ITConnection con2 = createConnection()) { - try { - con1.executeBatchUpdate( - Arrays.asList( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (21, 'Batch value 1')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (22, 'Batch value 2')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (23, 'Batch value 3')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (24, 'Batch value 4')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (25, 'Batch value 5')"), - Statement.of("INSERT INTO TEST_NOT_FOUND (ID, NAME) VALUES (26, 'Batch value 6')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (27, 'Batch value 7')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (28, 'Batch value 8')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (29, 'Batch value 9')"), - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (30, 'Batch value 10')"))); - fail("Missing batch update exception"); - } catch (SpannerBatchUpdateException e) { - assertThat(e.getUpdateCounts(), is(equalTo(new long[] {1L, 1L, 1L, 1L, 1L}))); - } - // Verify that the values cannot be read on the connection that did the insert. - try (ResultSet rs = - con1.executeQuery(Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=21 AND ID<=30"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(0), is(equalTo(0L))); - } - // Verify that the values can also not be read on another connection. - try (ResultSet rs = - con2.executeQuery(Statement.of("SELECT COUNT(*) FROM TEST WHERE ID>=21 AND ID<=30"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(0), is(equalTo(0L))); - } - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java deleted file mode 100644 index d981a3685077..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlMusicScriptTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import java.util.ArrayList; -import java.util.List; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.junit.runners.MethodSorters; - -/** - * Integration test that runs one long sql script using the default Singers/Albums/Songs/Concerts - * data model - */ -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class ITSqlMusicScriptTest extends ITAbstractSpannerTest { - private static final String SCRIPT_FILE = "ITSqlMusicScriptTest.sql"; - - @Test - public void test01_RunScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(); - try (GenericConnection connection = SpannerGenericConnection.of(createConnection())) { - verifier.verifyStatementsInFile(connection, SCRIPT_FILE, SqlScriptVerifier.class); - } - } - - @Test - public void test02_RunAbortedTest() { - final long SINGER_ID = 2L; - final long VENUE_ID = 68L; - final long NUMBER_OF_SINGERS = 30L; - final long NUMBER_OF_ALBUMS = 60L; - final long NUMBER_OF_SONGS = 149L; - final long NUMBER_OF_CONCERTS = 100L; - long numberOfSongs = 0L; - AbortInterceptor interceptor = new AbortInterceptor(0.0D); - try (ITConnection connection = createConnection(interceptor)) { - connection.setAutocommit(false); - connection.setRetryAbortsInternally(true); - // Read all data from the different music tables in the transaction - // The previous test deleted the first two Singers records. - long expectedId = 3L; - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM Singers ORDER BY SingerId"))) { - while (rs.next()) { - assertThat(rs.getLong("SingerId"), is(equalTo(expectedId))); - expectedId++; - } - } - assertThat(expectedId, is(equalTo(NUMBER_OF_SINGERS + 1L))); - expectedId = 3L; - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM Albums ORDER BY AlbumId"))) { - while (rs.next()) { - assertThat(rs.getLong("AlbumId"), is(equalTo(expectedId))); - expectedId++; - // 31 and 32 were deleted by the first test script. - if (expectedId == 31L || expectedId == 32L) { - expectedId = 33L; - } - } - } - assertThat(expectedId, is(equalTo(NUMBER_OF_ALBUMS + 1L))); - expectedId = 1L; - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM Songs ORDER BY TrackId"))) { - while (rs.next()) { - assertThat(rs.getLong("TrackId"), is(equalTo(expectedId))); - expectedId++; - numberOfSongs++; - // 40, 64, 76, 86 and 96 were deleted by the first test script. - if (expectedId == 40L - || expectedId == 64L - || expectedId == 76L - || expectedId == 86L - || expectedId == 96L) { - expectedId++; - } - } - } - assertThat(expectedId, is(equalTo(NUMBER_OF_SONGS + 1L))); - // Concerts are not in the table hierarchy, so no records have been deleted. - expectedId = 1L; - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT * FROM Concerts ORDER BY VenueId"))) { - while (rs.next()) { - assertThat(rs.getLong("VenueId"), is(equalTo(expectedId))); - expectedId++; - } - } - assertThat(expectedId, is(equalTo(NUMBER_OF_CONCERTS + 1L))); - - // make one small concurrent change in a different transaction - List originalPrices; - List newPrices; - try (ITConnection connection2 = createConnection()) { - assertThat(connection2.isAutocommit(), is(true)); - try (ResultSet rs = - connection2.executeQuery( - Statement.newBuilder( - "SELECT TicketPrices FROM Concerts WHERE SingerId=@singer AND VenueId=@venue") - .bind("singer") - .to(SINGER_ID) - .bind("venue") - .to(VENUE_ID) - .build())) { - assertThat(rs.next(), is(true)); - originalPrices = rs.getLongList(0); - // increase one of the prices by 1 - newPrices = new ArrayList<>(originalPrices); - newPrices.set(1, originalPrices.get(1) + 1); - connection2.executeUpdate( - Statement.newBuilder( - "UPDATE Concerts SET TicketPrices=@prices WHERE SingerId=@singer AND VenueId=@venue") - .bind("prices") - .toInt64Array(newPrices) - .bind("singer") - .to(SINGER_ID) - .bind("venue") - .to(VENUE_ID) - .build()); - } - } - - // try to add a new song and then try to commit, but trigger an abort on commit - connection.bufferedWrite( - Mutation.newInsertBuilder("Songs") - .set("SingerId") - .to(3L) - .set("AlbumId") - .to(3L) - .set("TrackId") - .to(1L) - .set("SongName") - .to("Aborted") - .set("Duration") - .to(1L) - .set("SongGenre") - .to("Unknown") - .build()); - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // the transaction retry should fail because of the concurrent modification - boolean expectedException = false; - try { - connection.commit(); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - // verify that the commit aborted, an internal retry was started and then aborted because of - // the concurrent modification - assertThat(expectedException, is(true)); - // verify that the prices were changed - try (ResultSet rs = - connection.executeQuery( - Statement.newBuilder( - "SELECT TicketPrices FROM Concerts WHERE SingerId=@singer AND VenueId=@venue") - .bind("singer") - .to(SINGER_ID) - .bind("venue") - .to(VENUE_ID) - .build())) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLongList(0), is(equalTo(newPrices))); - } - // verify that the new song was not written to the database - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) FROM Songs"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(0), is(equalTo(numberOfSongs))); - } - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java deleted file mode 100644 index 9f60ae6ccb00..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSqlScriptTest.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier.SpannerGenericConnection; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.junit.runners.MethodSorters; - -/** - * Integration test that creates and fills a test database entirely using only sql scripts, and then - * performs all possible operations on this test database using only sql scripts. This test uses the - * generic connection API. - */ -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class ITSqlScriptTest extends ITAbstractSpannerTest { - private static final String CREATE_TABLES_FILE = "ITSqlScriptTest_CreateTables.sql"; - private static final String INSERT_AND_VERIFY_TEST_DATA = "ITSqlScriptTest_InsertTestData.sql"; - private static final String TEST_GET_READ_TIMESTAMP = "ITSqlScriptTest_TestGetReadTimestamp.sql"; - private static final String TEST_GET_COMMIT_TIMESTAMP = - "ITSqlScriptTest_TestGetCommitTimestamp.sql"; - private static final String TEST_TEMPORARY_TRANSACTIONS = - "ITSqlScriptTest_TestTemporaryTransactions.sql"; - private static final String TEST_TRANSACTION_MODE = "ITSqlScriptTest_TestTransactionMode.sql"; - private static final String TEST_TRANSACTION_MODE_READ_ONLY = - "ITSqlScriptTest_TestTransactionMode_ReadOnly.sql"; - private static final String TEST_READ_ONLY_STALENESS = - "ITSqlScriptTest_TestReadOnlyStaleness.sql"; - private static final String TEST_AUTOCOMMIT_DML_MODE = - "ITSqlScriptTest_TestAutocommitDmlMode.sql"; - private static final String TEST_AUTOCOMMIT_READ_ONLY = - "ITSqlScriptTest_TestAutocommitReadOnly.sql"; - private static final String TEST_STATEMENT_TIMEOUT = "ITSqlScriptTest_TestStatementTimeout.sql"; - private static final String TEST_SET_STATEMENTS = "ITSqlScriptTest_TestSetStatements.sql"; - private static final String TEST_INVALID_STATEMENTS = "ITSqlScriptTest_TestInvalidStatements.sql"; - - private final SqlScriptVerifier verifier = new SqlScriptVerifier(); - - @Test - public void test01_CreateTables() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class); - } - } - - @Test - public void test02_InsertTestData() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - INSERT_AND_VERIFY_TEST_DATA, - SqlScriptVerifier.class); - } - } - - @Test - public void test03_TestGetReadTimestamp() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_GET_READ_TIMESTAMP, - SqlScriptVerifier.class); - } - } - - @Test - public void test04_TestGetCommitTimestamp() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_GET_COMMIT_TIMESTAMP, - SqlScriptVerifier.class); - } - } - - @Test - public void test05_TestTemporaryTransactions() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_TEMPORARY_TRANSACTIONS, - SqlScriptVerifier.class); - } - } - - @Test - public void test06_TestTransactionMode() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), TEST_TRANSACTION_MODE, SqlScriptVerifier.class); - } - } - - @Test - public void test07_TestTransactionModeReadOnly() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_TRANSACTION_MODE_READ_ONLY, - SqlScriptVerifier.class); - } - } - - @Test - public void test08_TestReadOnlyStaleness() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_READ_ONLY_STALENESS, - SqlScriptVerifier.class); - } - } - - @Test - public void test09_TestAutocommitDmlMode() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_AUTOCOMMIT_DML_MODE, - SqlScriptVerifier.class); - } - } - - @Test - public void test10_TestAutocommitReadOnly() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_AUTOCOMMIT_READ_ONLY, - SqlScriptVerifier.class); - } - } - - @Test - public void test11_TestStatementTimeout() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), TEST_STATEMENT_TIMEOUT, SqlScriptVerifier.class); - } - } - - @Test - public void test12_TestSetStatements() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class); - } - } - - @Test - public void test13_TestInvalidStatements() throws Exception { - try (ITConnection connection = createConnection()) { - verifier.verifyStatementsInFile( - SpannerGenericConnection.of(connection), - TEST_INVALID_STATEMENTS, - SqlScriptVerifier.class); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java deleted file mode 100644 index 219d2153adac..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionModeTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.IntegrationTest; -import com.google.cloud.spanner.Key; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.SpannerExceptionMatcher; -import com.google.cloud.spanner.jdbc.SqlScriptVerifier; -import java.util.Arrays; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@Category(IntegrationTest.class) -@RunWith(JUnit4.class) -public class ITTransactionModeTest extends ITAbstractSpannerTest { - @Rule public ExpectedException exception = ExpectedException.none(); - - @Override - public void appendConnectionUri(StringBuilder uri) { - uri.append("?autocommit=false"); - } - - @Override - public boolean doCreateDefaultTestTable() { - return true; - } - - @Test - public void testSqlScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new ITConnectionProvider()); - verifier.verifyStatementsInFile("ITTransactionModeTest.sql", SqlScriptVerifier.class); - } - - @Test - public void testDoAllowBufferedWriteInReadWriteTransaction() { - try (ITConnection connection = createConnection()) { - assertThat(connection.isAutocommit(), is(false)); - connection.bufferedWrite( - Mutation.newInsertBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST").build()); - connection.commit(); - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST"))); - assertThat(rs.next(), is(false)); - } - connection.bufferedWrite( - Mutation.newUpdateBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST2").build()); - connection.commit(); - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST2"))); - assertThat(rs.next(), is(false)); - } - connection.bufferedWrite(Mutation.delete("TEST", Key.of(1L))); - connection.commit(); - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT NAME FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(false)); - } - } - } - - @Test - public void testDoAllowBufferedWriteIterableInReadWriteTransaction() { - try (ITConnection connection = createConnection()) { - assertThat(connection.isAutocommit(), is(false)); - connection.bufferedWrite( - Arrays.asList( - Mutation.newInsertBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST-1").build(), - Mutation.newInsertBuilder("TEST").set("ID").to(2L).set("NAME").to("TEST-2").build())); - connection.commit(); - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST-1"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST-2"))); - assertThat(rs.next(), is(false)); - } - connection.bufferedWrite( - Arrays.asList( - Mutation.newUpdateBuilder("TEST").set("ID").to(1L).set("NAME").to("TEST-1-2").build(), - Mutation.newUpdateBuilder("TEST") - .set("ID") - .to(2L) - .set("NAME") - .to("TEST-2-2") - .build())); - connection.commit(); - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST-1-2"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("TEST-2-2"))); - assertThat(rs.next(), is(false)); - } - connection.bufferedWrite( - Arrays.asList(Mutation.delete("TEST", Key.of(1L)), Mutation.delete("TEST", Key.of(2L)))); - connection.commit(); - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT NAME FROM TEST WHERE ID IN (1,2) ORDER BY ID"))) { - assertThat(rs.next(), is(false)); - } - } - } - - @Test - public void testDoNotAllowBufferedWriteInReadOnlyTransaction() { - try (ITConnection connection = createConnection()) { - connection.execute(Statement.of("SET TRANSACTION READ ONLY")); - assertThat(connection.isAutocommit(), is(false)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); - } - } - - @Test - public void testDoNotAllowBufferedWriteIterableInReadOnlyTransaction() { - try (ITConnection connection = createConnection()) { - connection.execute(Statement.of("SET TRANSACTION READ ONLY")); - assertThat(connection.isAutocommit(), is(false)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.bufferedWrite( - Arrays.asList( - Mutation.newInsertBuilder("FOO").set("ID").to(1L).build(), - Mutation.newInsertBuilder("FOO").set("ID").to(2L).build())); - } - } - - @Test - public void testDoNotAllowBufferedWriteInDdlBatch() { - try (ITConnection connection = createConnection()) { - connection.startBatchDdl(); - assertThat(connection.isAutocommit(), is(false)); - assertThat(connection.isDdlBatchActive(), is(true)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); - } - } - - @Test - public void testDoNotAllowBufferedWriteIterableInDdlBatch() { - try (ITConnection connection = createConnection()) { - connection.startBatchDdl(); - assertThat(connection.isAutocommit(), is(false)); - assertThat(connection.isDdlBatchActive(), is(true)); - exception.expect(SpannerExceptionMatcher.matchCode(ErrorCode.FAILED_PRECONDITION)); - connection.bufferedWrite( - Arrays.asList( - Mutation.newInsertBuilder("FOO").set("ID").to(1L).build(), - Mutation.newInsertBuilder("FOO").set("ID").to(2L).build())); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java deleted file mode 100644 index e3fc90c4e6f4..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITTransactionRetryTest.java +++ /dev/null @@ -1,1567 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.jdbc.it; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import com.google.cloud.Timestamp; -import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; -import com.google.cloud.spanner.AbortedException; -import com.google.cloud.spanner.KeySet; -import com.google.cloud.spanner.Mutation; -import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.SpannerException; -import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.jdbc.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.TransactionRetryListener; -import java.sql.Connection; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * This integration test tests the different scenarios for automatically retrying read/write - * transactions, both when possible and when the transaction must abort because of a concurrent - * update. - */ -@RunWith(JUnit4.class) -public class ITTransactionRetryTest extends ITAbstractSpannerTest { - private static final Logger logger = Logger.getLogger(ITTransactionRetryTest.class.getName()); - - @Rule public TestName testName = new TestName(); - - @Override - protected void appendConnectionUri(StringBuilder uri) { - uri.append(";autocommit=false;retryAbortsInternally=true"); - } - - @Override - public boolean doCreateDefaultTestTable() { - return true; - } - - /** Clear the test table before each test run */ - @Before - public void clearTable() { - try (ITConnection connection = createConnection()) { - connection.bufferedWrite(Mutation.delete("TEST", KeySet.all())); - connection.commit(); - } - } - - @Before - public void clearStatistics() { - RETRY_STATISTICS.clear(); - } - - @Before - public void logStart() { - logger.fine( - "--------------------------------------------------------------\n" - + testName.getMethodName() - + " started"); - } - - @After - public void logFinished() { - logger.fine( - "--------------------------------------------------------------\n" - + testName.getMethodName() - + " finished"); - } - - /** Simple data structure to keep track of retry statistics */ - private static class RetryStatistics { - private int totalRetryAttemptsStarted; - private int totalRetryAttemptsFinished; - private int totalSuccessfulRetries; - private int totalErroredRetries; - private int totalNestedAborts; - private int totalMaxAttemptsExceeded; - private int totalConcurrentModifications; - - private void clear() { - totalRetryAttemptsStarted = 0; - totalRetryAttemptsFinished = 0; - totalSuccessfulRetries = 0; - totalErroredRetries = 0; - totalNestedAborts = 0; - totalMaxAttemptsExceeded = 0; - totalConcurrentModifications = 0; - } - } - - /** - * Static to allow access from the {@link CountTransactionRetryListener}. Statistics are - * automatically cleared before each test case. - */ - public static final RetryStatistics RETRY_STATISTICS = new RetryStatistics(); - - /** - * Simple {@link TransactionRetryListener} that keeps track of the total count of the different - * transaction retry events of a {@link Connection}. Note that as {@link - * TransactionRetryListener}s are instantiated once per connection, the listener keeps track of - * the total statistics of a connection and not only of the last transaction. - */ - public static class CountTransactionRetryListener implements TransactionRetryListener { - - @Override - public void retryStarting(Timestamp transactionStarted, long transactionId, int retryAttempt) { - RETRY_STATISTICS.totalRetryAttemptsStarted++; - } - - @Override - public void retryFinished( - Timestamp transactionStarted, long transactionId, int retryAttempt, RetryResult result) { - RETRY_STATISTICS.totalRetryAttemptsFinished++; - switch (result) { - case RETRY_ABORTED_AND_MAX_ATTEMPTS_EXCEEDED: - RETRY_STATISTICS.totalMaxAttemptsExceeded++; - break; - case RETRY_ABORTED_AND_RESTARTING: - RETRY_STATISTICS.totalNestedAborts++; - break; - case RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION: - RETRY_STATISTICS.totalConcurrentModifications++; - break; - case RETRY_ERROR: - RETRY_STATISTICS.totalErroredRetries++; - break; - case RETRY_SUCCESSFUL: - RETRY_STATISTICS.totalSuccessfulRetries++; - break; - default: - break; - } - } - } - - /** Test successful retry when the commit aborts */ - @Test - public void testCommitAborted() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // do an insert - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // do a commit that will first abort, and then on retry will succeed - connection.commit(); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= 1, is(true)); - assertThat(RETRY_STATISTICS.totalRetryAttemptsFinished >= 1, is(true)); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - assertThat(RETRY_STATISTICS.totalErroredRetries, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalConcurrentModifications, is(equalTo(0))); - assertThat(RETRY_STATISTICS.totalMaxAttemptsExceeded, is(equalTo(0))); - // verify that the insert succeeded - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry when an insert statement aborts */ - @Test - public void testInsertAborted() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // do an insert that will abort - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - // do a commit - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that the insert succeeded - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry when an update statement aborts */ - @Test - public void testUpdateAborted() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // insert a test record - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // do an update that will abort - connection.executeUpdate(Statement.of("UPDATE TEST SET NAME='update aborted' WHERE ID=1")); - // do a commit - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that the update succeeded - try (ResultSet rs = - connection.executeQuery( - Statement.of( - "SELECT COUNT(*) AS C FROM TEST WHERE ID=1 AND NAME='update aborted'"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry when a query aborts */ - @Test - public void testQueryAborted() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // insert a test record - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - // do a query that will abort - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - // do a commit - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that the update succeeded - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry when a call to {@link ResultSet#next()} aborts */ - @Test - public void testNextCallAborted() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // do a query - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - // the first record should be accessible without any problems - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(1L))); - - // indicate that the next statement should abort - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(2L))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // there should be only two records - assertThat(rs.next(), is(false)); - } - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that the transaction succeeded - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(2L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry after multiple aborts */ - @Test - public void testMultipleAborts() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // do three inserts which all will abort and retry - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 3, is(true)); - assertThat( - RETRY_STATISTICS.totalNestedAborts, - is(equalTo(RETRY_STATISTICS.totalSuccessfulRetries - 3))); - // verify that the insert succeeded - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(3L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** - * Tests that a transaction retry can be successful after a select, as long as the select returns - * the same results during the retry - */ - @Test - public void testAbortAfterSelect() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // verify that the there is no test record - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(0L))); - assertThat(rs.next(), is(false)); - } - // insert a test record - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - // select the test record - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(1L))); - assertThat(rs.getString("NAME"), is(equalTo("test 1"))); - assertThat(rs.next(), is(false)); - } - // do another insert that will abort and retry - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the first test record again - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(1L))); - assertThat(rs.getString("NAME"), is(equalTo("test 1"))); - assertThat(rs.next(), is(false)); - } - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - } - } - - /** - * Test a successful retry when a {@link ResultSet} has been consumed half way. The {@link - * ResultSet} should still be at the same position and still behave as if the original transaction - * did not abort. - */ - @Test - public void testAbortWithResultSetHalfway() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - // iterate one step - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(1L))); - // do another insert that will abort and retry - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - // iterate another step - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(2L))); - // ensure we are at the end of the result set - assertThat(rs.next(), is(false)); - } - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that all the inserts succeeded - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(3L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** Test successful retry after a {@link ResultSet} has been fully consumed. */ - @Test - public void testAbortWithResultSetFullyConsumed() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records and iterate over them - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing, just consume the result set - } - } - // do another insert that will abort and retry - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - // verify that all the inserts succeeded - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(3L))); - assertThat(rs.next(), is(false)); - } - } - } - - @Test - public void testAbortWithConcurrentInsert() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records and consume the entire result set - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing - } - } - // open a new connection and transaction and do an additional insert - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertRetryStatistics(1, 1, 0); - } - } - - @Test - public void testAbortWithConcurrentDelete() { - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // open a new connection and select the two test records - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // select the test records and consume the entire result set - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing - } - } - // open a new connection and transaction and remove one of the test records - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("DELETE FROM TEST WHERE ID=1")); - connection2.commit(); - } - // now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertRetryStatistics(1, 1, 0); - } - } - - @Test - public void testAbortWithConcurrentUpdate() { - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // open a new connection and select the two test records - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // select the test records and consume the entire result set - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing - } - } - // open a new connection and transaction and update one of the test records - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("UPDATE TEST SET NAME='test updated' WHERE ID=2")); - connection2.commit(); - } - // now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertRetryStatistics(1, 1, 0); - } - } - - /** - * Test that shows that a transaction retry is possible even when there is a concurrent insert - * that has an impact on a query that has been executed, as long as the user hasn't actually seen - * the relevant part of the result of the query - */ - @Test - public void testAbortWithUnseenConcurrentInsert() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records and consume part of the result set - ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID")); - assertThat(rs.next(), is(true)); - assertThat(rs.next(), is(true)); - // Open a new connection and transaction and do an additional insert. This insert will be - // included in a retry of the above query, but this has not yet been 'seen' by the user, - // hence is not a problem for retrying the transaction. - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // now try to do an insert that will abort. The retry should still succeed. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted; - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= currentRetryCount + 1, is(true)); - // Consume the rest of the result set. The insert by the other transaction should now be - // included in the result set as the transaction retried. Although this means that the result - // is different after a retry, it is not different as seen by the user, as the user didn't - // know that the result set did not have any more results before the transaction retry. - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(3L))); - // record with id 4 should not be visible, as it was added to the transaction after the query - // was executed - assertThat(rs.next(), is(false)); - rs.close(); - connection.commit(); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= 1, is(true)); - } - } - - /** - * This test shows what happens when an abort occurs on a call to {@link ResultSet#next()} on a - * {@link ResultSet} that has an concurrent insert. As long as the user hasn't consumed the {@link - * ResultSet} so far that the concurrent insert has been seen, the retry will succeed. When the - * user has consumed the {@link ResultSet} to the point where the concurrent insert is visible, - * the retry will fail. - */ - @Test - public void testAbortWithUnseenConcurrentInsertAbortOnNext() { - // no calls to next(), this should succeed - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(0) >= 1, is(true)); - // 1 call to next() should also succeed, as there were 2 records in the original result set - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(1) >= 1, is(true)); - // 2 calls to next() should also succeed, as there were 2 records in the original result set and - // the user doesn't know yet that the next call to next() will return true instead of false - // after the concurrent insert - assertThat(testAbortWithUnseenConcurrentInsertAbortOnNext(2) >= 1, is(true)); - - boolean expectedException = false; - try { - // 3 calls to next() should fail, as the user would now see the inserted record - testAbortWithUnseenConcurrentInsertAbortOnNext(3); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - } - - private int testAbortWithUnseenConcurrentInsertAbortOnNext(int callsToNext) - throws AbortedDueToConcurrentModificationException { - int retries = 0; - clearTable(); - clearStatistics(); - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - int totalRecordsSeen = 0; - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records and consume part or all of the result set - ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID")); - for (int counter = 0; counter < callsToNext; counter++) { - if (rs.next()) { - totalRecordsSeen++; - } - } - // Open a new connection and transaction and do an additional insert. This insert will be - // included in a retry of the above query. Any transaction retry will fail/succeed depending - // on whether the user has consumed enough of the result set to potentially have seen this - // insert. - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // Now consume the rest of the result set, but trigger a transaction retry by aborting the - // first next() call. Without a retry, the result set should only contain 2 records. With a - // successful retry, the result set contains 3 results. The retry will only succeed as long - // as the user has not consumed enough of the result set to know whether there should have - // been a record with ID 3 or not. - - // First verify that the transaction has not yet retried. - int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted; - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - - // Try to consume the rest of the result set. - // This will fail with an AbortedDueToConcurrentModificationException if the retry fails. - while (rs.next()) { - totalRecordsSeen++; - if (totalRecordsSeen == 3) { - assertThat(rs.getLong("ID"), is(equalTo(3L))); - } - } - // Verify that the transaction retried. - assertThat(RETRY_STATISTICS.totalSuccessfulRetries > currentRetryCount, is(true)); - rs.close(); - connection.commit(); - retries = RETRY_STATISTICS.totalSuccessfulRetries; - } - return retries; - } - - /** - * Test that shows that a transaction that has aborted is considered to be rolled back, and new - * statements will be executed in a new transaction - */ - @Test - public void testAbortWithConcurrentInsertAndContinue() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // Select the test records and consume the entire result set. - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing - } - } - // Open a new connection and transaction and do an additional insert - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // Now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertRetryStatistics(1, 1, 0); - // the next statement should be in a new transaction as the previous transaction rolled back - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - // there should be one record from the transaction on connection2 - assertThat(rs.next(), is(true)); - assertThat(rs.next(), is(false)); - } - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. The transaction aborts at commit - *
    2. A retry starts and succeeds - *
    3. The commit is applied again and aborts again - *
    4. The retry is started again and then succeeds - *
    - */ - @Test - public void testAbortTwiceOnCommit() { - AbortInterceptor interceptor = - new AbortInterceptor(0) { - private int commitCount = 0; - - @Override - protected boolean shouldAbort(String statement, ExecutionStep step) { - if ("COMMIT".equalsIgnoreCase(statement)) { - commitCount++; - return commitCount <= 2; - } - return false; - } - }; - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - connection.commit(); - // Assert that the transaction was retried twice. - assertRetryStatistics(2, 0, 2); - // Verify that the insert succeeded. - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. The transaction aborts at commit - *
    2. A retry starts and then aborts at the insert statement - *
    3. The retry is restarted and then succeeds - *
    - */ - @Test - public void testNestedAbortOnInsert() { - AbortInterceptor interceptor = - new AbortInterceptor(0) { - private int commitCount = 0; - private int insertCount = 0; - - @Override - protected boolean shouldAbort(String statement, ExecutionStep step) { - if ("COMMIT".equalsIgnoreCase(statement)) { - commitCount++; - return commitCount == 1; - } else if (statement.startsWith("INSERT INTO TEST")) { - insertCount++; - return insertCount == 2; - } - return false; - } - }; - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - connection.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')")); - connection.commit(); - // Assert that the transaction was retried (a restarted retry is counted as one successful - // retry). - assertRetryStatistics(2, 0, 1); - assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); - // Verify that the insert succeeded. - try (ResultSet rs = - connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(1L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. The transaction aborts at commit - *
    2. A retry starts and then aborts at a next call in a result set - *
    3. The retry is restarted and then succeeds - *
    - */ - @Test - public void testNestedAbortOnNextCall() { - AbortInterceptor interceptor = - new AbortInterceptor(0) { - private int nextCallsDuringRetry = 0; - private int commitCount = 0; - - @Override - protected boolean shouldAbort(String statement, ExecutionStep step) { - if ("COMMIT".equalsIgnoreCase(statement)) { - // Note that commit always has ExecutionStep == EXECUTE_STATEMENT, as a commit can - // never - // really be retried (it is always the last statement in a transaction, and if it - // fails - // because of an aborted exception, the entire transaction is retried, and the commit - // statement is then applied again). - commitCount++; - return commitCount == 1; - } else if (statement.equals("SELECT * FROM TEST ORDER BY ID") - && step == ExecutionStep.RETRY_NEXT_ON_RESULT_SET) { - nextCallsDuringRetry++; - return nextCallsDuringRetry == 1; - } - return false; - } - }; - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // Insert two test records. - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // Select the test records. - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - // Iterate one step. This step should abort during the retry the first time. - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(1L))); - // Do another insert that will not be visible to the result set. - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - // iterate another step - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("ID"), is(equalTo(2L))); - // Ensure we are at the end of the result set. - assertThat(rs.next(), is(false)); - } - connection.commit(); - // Verify that the transaction retried. - assertRetryStatistics(2, 0, 1); - assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); - // Verify that all the inserts succeeded. - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(3L))); - assertThat(rs.next(), is(false)); - } - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. Transaction 1 does two inserts in table TEST - *
    2. Transaction 1 selects all records from table TEST - *
    3. Transaction 2 inserts a record into TEST - *
    4. Transaction 1 does another insert into TEST that aborts - *
    5. Transaction 1 starts a retry that aborts at the SELECT statement (i.e. before the - * concurrent modification has been seen) - *
    6. Transaction 1 restarts the retry that now aborts due to a concurrent modification - * exception - *
    - */ - @Test - public void testNestedAbortWithConcurrentInsert() { - AbortInterceptor interceptor = - new AbortInterceptor(0) { - private boolean alreadyAborted = false; - - @Override - protected boolean shouldAbort(String statement, ExecutionStep step) { - // Abort during retry on the select statement. - if (!alreadyAborted - && statement.equals("SELECT * FROM TEST ORDER BY ID") - && step == ExecutionStep.RETRY_STATEMENT) { - alreadyAborted = true; - return true; - } - return super.shouldAbort(statement, step); - } - }; - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert two test records - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - // select the test records and consume the entire result set - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing - } - } - // open a new connection and transaction and do an additional insert - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // Now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertThat(expectedException, is(true)); - assertRetryStatistics(2, 1, 0); - assertThat(RETRY_STATISTICS.totalNestedAborts > 0, is(true)); - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit - *
    2. Transaction 1 updates the names of all records in the TEST table - *
    3. Transaction 2 inserts a record in the TEST table and commits - *
    4. Transaction 1 does another insert into TEST that aborts - *
    5. Transaction 1 starts a retry that aborts due to a concurrent modification exception as - * the number of updated records will be different - *
    - */ - @Test - public void testAbortWithDifferentUpdateCount() { - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // open a new connection and update one of the records - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - connection.executeUpdate( - Statement.of("UPDATE TEST SET NAME='test update that will fail' WHERE TRUE")); - // open a new connection and transaction and update the same test record - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - connection2.commit(); - } - // Now try to do an insert that will abort. The retry should now fail as there has been a - // concurrent modification. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (4, 'test 4')")); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - assertRetryStatistics(1, 1, 0); - assertThat(expectedException, is(true)); - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit - *
    2. Try to query a non-existing table. This will lead to an exception. - *
    3. Query all the records from the TEST table and consume the result set - *
    4. Insert another record into TEST that aborts - *
    5. The transaction successfully retries - *
    - */ - @Test - public void testAbortWithExceptionOnSelect() { - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // do a select that will fail - boolean expectedException = false; - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { - while (rs.next()) { - // do nothing - } - } catch (SpannerException e) { - // expected - expectedException = true; - } - assertThat(expectedException, is(true)); - // do a select that will succeed - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // now try to do an insert that will abort. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - assertRetryStatistics(1, 0, 1); - } - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit. - *
    2. Try to query the non-existing table FOO. This will lead to an exception. - *
    3. Query all the records from the TEST table and consume the result set. - *
    4. Open another connection and create the table FOO. - *
    5. Insert another record into TEST that aborts. - *
    6. The transaction is internally retried. The retry fails as the SELECT statement on FOO - * will now succeed. - *
    - */ - @Test - public void testAbortWithExceptionOnSelectAndConcurrentModification() { - boolean abortedDueToConcurrentModification = false; - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // do a select that will fail - boolean expectedException = false; - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { - while (rs.next()) { - // do nothing - } - } catch (SpannerException e) { - // expected - expectedException = true; - } - assertThat(expectedException, is(true)); - // do a select that will succeed - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // CREATE FOO - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute( - Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - } - // Now try to do an insert that will abort. The subsequent retry will fail as the SELECT * - // FROM FOO now returns a result. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - abortedDueToConcurrentModification = true; - } - } - // DROP FOO regardless of the result to avoid any interference with other test cases - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute(Statement.of("DROP TABLE FOO")); - } - assertThat(abortedDueToConcurrentModification, is(true)); - assertRetryStatistics(1, 1, 0); - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit. - *
    2. Try to insert a record in the non-existing table FOO. This will lead to an exception. - *
    3. Query all the records from the TEST table and consume the result set. - *
    4. Open another connection and create the table FOO. - *
    5. Insert another record into TEST that aborts. - *
    6. The transaction is internally retried. The retry fails as the insert statement on FOO - * will now succeed. - *
    - */ - @Test - public void testAbortWithExceptionOnInsertAndConcurrentModification() { - boolean abortedDueToConcurrentModification = false; - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // do an insert that will fail - boolean expectedException = false; - try { - connection.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); - } catch (SpannerException e) { - // expected - expectedException = true; - } - assertThat(expectedException, is(true)); - // do a select that will succeed - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // CREATE FOO - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute( - Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - } - // Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO - // FOO now succeeds. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - abortedDueToConcurrentModification = true; - } - } - // DROP FOO regardless of the result to avoid any interference with other test cases - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute(Statement.of("DROP TABLE FOO")); - } - assertThat(abortedDueToConcurrentModification, is(true)); - assertRetryStatistics(1, 1, 0); - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit. - *
    2. Create the table FOO and insert a test record. - *
    3. Query the table FOO. - *
    4. Query all the records from the TEST table and consume the result set. - *
    5. Open another connection and drop the table FOO. - *
    6. Insert another record into TEST that aborts. - *
    7. The transaction is internally retried. The retry fails as the SELECT statement on FOO - * will now fail. - *
    - */ - @Test - public void testAbortWithDroppedTableConcurrentModification() { - boolean abortedDueToConcurrentModification = false; - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // CREATE FOO - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute( - Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO"))) { - while (rs.next()) { - // do nothing - } - } - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // DROP FOO using a different connection - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute(Statement.of("DROP TABLE FOO")); - } - // Now try to do an insert that will abort. The subsequent retry will fail as the SELECT * - // FROM FOO now fails. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - abortedDueToConcurrentModification = true; - } - } - assertThat(abortedDueToConcurrentModification, is(true)); - assertRetryStatistics(1, 1, 0); - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit. - *
    2. Create the table FOO and insert a test record and commit. - *
    3. Insert another record into the table FOO. - *
    4. Query all the records from the TEST table and consume the result set. - *
    5. Open another connection and drop the table FOO. - *
    6. Insert another record into TEST that aborts. - *
    7. The transaction is internally retried. The retry fails as the INSERT statement on FOO - * will now fail. - *
    - */ - @Test - public void testAbortWithInsertOnDroppedTableConcurrentModification() { - boolean abortedDueToConcurrentModification = false; - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // CREATE FOO - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute( - Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert a record into FOO - connection.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (2, 'test 2')")); - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // DROP FOO using a different connection - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute(Statement.of("DROP TABLE FOO")); - } - // Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO - // FOO now fails. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - try { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')")); - } catch (AbortedDueToConcurrentModificationException e) { - abortedDueToConcurrentModification = true; - } - } - assertThat(abortedDueToConcurrentModification, is(true)); - assertRetryStatistics(1, 1, 0); - } - - /** - * Test that shows the following: - * - *
      - *
    1. Insert two records into table TEST and commit. - *
    2. Create the table FOO and insert two test records and commit. - *
    3. Query all the records from the TEST table and consume the result set. - *
    4. Query all the records from the FOO table and consume only part of the result set. - *
    5. Open another connection and drop the table FOO. - *
    6. Try to consume the rest of the FOO result set. This aborts. - *
    7. The transaction is internally retried. The retry fails as the SELECT statement on FOO - * will now fail. - *
    - */ - @Test - public void testAbortWithCursorHalfwayDroppedTableConcurrentModification() { - boolean abortedDueToConcurrentModification = false; - AbortInterceptor interceptor = new AbortInterceptor(0); - // first insert two test records - try (ITConnection connection = createConnection()) { - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')")); - connection.commit(); - } - // CREATE FOO - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute( - Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (1, 'test 1')")); - connection2.executeUpdate(Statement.of("INSERT INTO FOO (ID, NAME) VALUES (2, 'test 2')")); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST"))) { - while (rs.next()) { - // do nothing - } - } - // SELECT FROM FOO and consume part of the result set - ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM FOO")); - assertThat(rs.next(), is(true)); - // DROP FOO using a different connection - try (ITConnection connection2 = createConnection()) { - connection2.setAutocommit(true); - connection2.execute(Statement.of("DROP TABLE FOO")); - } - // try to continue to consume the result set, but this will now abort. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - try { - // This will fail as the retry will not succeed. - rs.next(); - } catch (AbortedDueToConcurrentModificationException e) { - abortedDueToConcurrentModification = true; - } finally { - rs.close(); - } - } - assertThat(abortedDueToConcurrentModification, is(true)); - assertRetryStatistics(1, 1, 0); - } - - /** Test the successful retry of a transaction with a large {@link ResultSet} */ - @Test - public void testRetryLargeResultSet() { - final int NUMBER_OF_TEST_RECORDS = 100000; - final long UPDATED_RECORDS = 1000L; - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = createConnection()) { - // insert test records - for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) { - connection.bufferedWrite( - Mutation.newInsertBuilder("TEST").set("ID").to(i).set("NAME").to("test " + i).build()); - if (i % 1000 == 0) { - connection.commit(); - } - } - connection.commit(); - } - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // select the test records and iterate over them - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing, just consume the result set - } - } - // Do an update that will abort and retry. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - connection.executeUpdate( - Statement.newBuilder("UPDATE TEST SET NAME='updated' WHERE ID<@max_id") - .bind("max_id") - .to(UPDATED_RECORDS) - .build()); - connection.commit(); - // verify that the update succeeded - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE NAME='updated'"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(UPDATED_RECORDS))); - assertThat(rs.next(), is(false)); - } - // Verify that the transaction retried. - assertRetryStatistics(1, 0, 1); - } - } - - /** Test the successful retry of a transaction with a high chance of multiple aborts */ - @Test - public void testRetryHighAbortRate() { - final int NUMBER_OF_TEST_RECORDS = 10000; - final long UPDATED_RECORDS = 1000L; - // abort on 25% of all statements - AbortInterceptor interceptor = new AbortInterceptor(0.25D); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // insert test records - for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) { - connection.bufferedWrite( - Mutation.newInsertBuilder("TEST").set("ID").to(i).set("NAME").to("test " + i).build()); - if (i % 1000 == 0) { - connection.commit(); - } - } - connection.commit(); - // select the test records and iterate over them - // reduce the abort rate to 0.01% as each next() call could abort - interceptor.setProbability(0.0001D); - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - while (rs.next()) { - // do nothing, just consume the result set - } - } - // increase the abort rate to 50% - interceptor.setProbability(0.50D); - connection.executeUpdate( - Statement.newBuilder("UPDATE TEST SET NAME='updated' WHERE ID<@max_id") - .bind("max_id") - .to(UPDATED_RECORDS) - .build()); - connection.commit(); - // verify that the update succeeded - try (ResultSet rs = - connection.executeQuery( - Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE NAME='updated'"))) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong("C"), is(equalTo(UPDATED_RECORDS))); - assertThat(rs.next(), is(false)); - } - connection.commit(); - } catch (AbortedException e) { - // This could happen if the number of aborts exceeds the max number of retries. - logger.log(Level.FINE, "testRetryHighAbortRate aborted because of too many retries", e); - } - logger.fine("Total number of retries started: " + RETRY_STATISTICS.totalRetryAttemptsStarted); - logger.fine("Total number of retries finished: " + RETRY_STATISTICS.totalRetryAttemptsFinished); - logger.fine("Total number of retries successful: " + RETRY_STATISTICS.totalSuccessfulRetries); - logger.fine("Total number of retries aborted: " + RETRY_STATISTICS.totalNestedAborts); - logger.fine( - "Total number of times the max retry count was exceeded: " - + RETRY_STATISTICS.totalMaxAttemptsExceeded); - } - - @Test - public void testAbortWithConcurrentInsertOnEmptyTable() { - AbortInterceptor interceptor = new AbortInterceptor(0); - try (ITConnection connection = - createConnection(interceptor, new CountTransactionRetryListener())) { - // select the test records but do not consume the result set - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - // Open a new connection and transaction and do an insert. This insert will be - // included in a retry of the above query, but this has not yet been 'seen' by the user, - // hence is not a problem for retrying the transaction. - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection2.commit(); - } - // Now try to consume the result set, but the call to next() will throw an AbortedException. - // The retry should still succeed. - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - int currentSuccessfulRetryCount = RETRY_STATISTICS.totalSuccessfulRetries; - assertThat(rs.next(), is(true)); - assertThat( - RETRY_STATISTICS.totalSuccessfulRetries, is(equalTo(currentSuccessfulRetryCount + 1))); - assertThat(rs.next(), is(false)); - } - connection.commit(); - - // Now do the same, but this time we will consume the empty result set. The retry should now - // fail. - clearTable(); - clearStatistics(); - try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) { - assertThat(rs.next(), is(false)); - // Open a new connection and transaction and do an insert. This insert will be - // included in a retry of the above query, and this time it will cause the retry to fail. - try (ITConnection connection2 = createConnection()) { - connection2.executeUpdate( - Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')")); - connection2.commit(); - } - // this time the abort will occur on the call to commit() - interceptor.setProbability(1.0); - interceptor.setOnlyInjectOnce(true); - boolean expectedException = false; - try { - connection.commit(); - } catch (AbortedDueToConcurrentModificationException e) { - expectedException = true; - } - // No successful retries. - assertRetryStatistics(1, 1, 0); - assertThat(expectedException, is(true)); - } - } - } - - private void assertRetryStatistics( - int minAttemptsStartedExpected, - int concurrentModificationsExpected, - int successfulRetriesExpected) { - assertThat(RETRY_STATISTICS.totalRetryAttemptsStarted >= minAttemptsStartedExpected, is(true)); - assertThat( - RETRY_STATISTICS.totalConcurrentModifications, - is(equalTo(concurrentModificationsExpected))); - assertThat(RETRY_STATISTICS.totalSuccessfulRetries >= successfulRetriesExpected, is(true)); - } -} From 7331144e881f83480d21a4d053d9d9a3fe2be37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 27 May 2020 17:47:18 +0200 Subject: [PATCH 0157/1979] feat: publish shaded jar on maven central (#83) * feat: publish shaded jar on maven central * fix: fix dependency problems --- java-spanner-jdbc/pom.xml | 137 +++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 262795eaaa00..d833ecd354ed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -144,13 +144,21 @@ com.google.auth google-auth-library-oauth2-http
    + + com.google.auth + google-auth-library-credentials + com.google.cloud google-cloud-core - com.google.auth - google-auth-library-credentials + com.google.api.grpc + proto-google-cloud-spanner-v1 + + + com.google.api.grpc + grpc-google-cloud-spanner-v1 @@ -243,6 +251,64 @@
    + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + + shade + + + true + true + true + single-jar-with-dependencies + false + + + *:* + + + java:* + junit:* + + + + + + META-INF/services + java.sql.Driver + + + com.google.cloud.spanner.jdbc + ClientSideStatements.json + + + com.google.cloud.spanner.jdbc + *.sql + + + + META-INF/SIGNINGC.RSA + META-INF/SIGNINGC.SF + META-INF/DEPENDENCIES + META-INF/LICENSE + META-INF/LICENSE.txt + META-INF/NOTICE + META-INF/NOTICE.txt + + + + + + + @@ -296,73 +362,6 @@
    - - - build-jdbc-driver - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.3 - - - - shade - - - true - true - false - false - - - *:* - - - java:* - junit:* - - - - - - META-INF/services - java.sql.Driver - - - com.google.cloud.spanner.jdbc - ClientSideStatements.json - - - com.google.cloud.spanner.jdbc - *.sql - - - - META-INF/SIGNINGC.RSA - META-INF/SIGNINGC.SF - META-INF/DEPENDENCIES - META-INF/LICENSE - META-INF/LICENSE.txt - META-INF/NOTICE - META-INF/NOTICE.txt - - - - - - - - - - From 18d91e7df12404f9d7b795660291d29cdf0cfd4b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 4 Jun 2020 22:34:41 +0200 Subject: [PATCH 0158/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.1.0 (#145) This PR contains the following updates: | Package | Update | Change | |---|---|---| | org.apache.maven.plugins:maven-project-info-reports-plugin | minor | `3.0.0` -> `3.1.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d833ecd354ed..ca9fe62aad16 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -368,7 +368,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.0.0 + 3.1.0 From 1052ffcd22058e66e20cb7d30b74ef01916512e8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 4 Jun 2020 15:16:21 -0700 Subject: [PATCH 0159/1979] chore(java_templates): add default CODEOWNERS files for samples reviews (#146) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/cee9e42c-941c-49fe-b176-a9e83c067c7c/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/8b65daa222d193b689279162781baf0aa1f0ffd2 --- java-spanner-jdbc/.github/CODEOWNERS | 8 ++++++++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/CODEOWNERS diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS new file mode 100644 index 000000000000..6137bef2a259 --- /dev/null +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# Code owners file. +# This file controls who is tagged for review for any given pull request. + +# For syntax help see: +# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax + +# The java-samples-reviewers team is the default owner for samples changes +samples/**/*.java @googleapis/java-samples-reviewers diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 0faa79cc2fdb..74d10d7f5997 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "839e4dcc0ab9b1044cd0534195a44c37c2e37f14" + "sha": "2a7c53e5d503eefc42e7927e58430f8d24fe5b48" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5b48b0716a36ca069db3038da7e205c87a22ed19" + "sha": "8b65daa222d193b689279162781baf0aa1f0ffd2" } } ] From 9da4765ac3a9f6faf979006f17dfebecf3b3e01b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 5 Jun 2020 00:37:10 -0700 Subject: [PATCH 0160/1979] chore: turn on renovate-bot master issue for java repos (#147) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/5a6d8b4a-5d51-4aa7-bbe3-089dd415efba/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/cac9eef310652bf138dd76b716e4986e757d62ac --- java-spanner-jdbc/renovate.json | 3 ++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 2b2b2658b2a2..0fd3e3fc8395 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -76,5 +76,6 @@ "groupName": "jackson dependencies" } ], - "semanticCommits": true + "semanticCommits": true, + "masterIssue": true } \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 74d10d7f5997..ae7e460f8d14 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "2a7c53e5d503eefc42e7927e58430f8d24fe5b48" + "sha": "0b39d9f7784089763f4194478b276e8a8e17a041" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8b65daa222d193b689279162781baf0aa1f0ffd2" + "sha": "cac9eef310652bf138dd76b716e4986e757d62ac" } } ] From b9e4f33c3285a78a5556121bcbd54bcdcf3a982f Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 5 Jun 2020 22:24:58 -0700 Subject: [PATCH 0161/1979] build(java): skip lint on samples directory (#149) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/d76bfbb4-fde1-4909-a913-608cdb170a49/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/987270824bd26f6a8c716d5e2022057b8ae7b26e --- java-spanner-jdbc/.kokoro/build.sh | 4 +--- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 560e01957f33..d09a94e19cbe 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -51,9 +51,7 @@ test) RETURN_CODE=$? ;; lint) - mvn \ - -Penable-samples \ - com.coveo:fmt-maven-plugin:check + mvn com.coveo:fmt-maven-plugin:check RETURN_CODE=$? ;; javadoc) diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index ae7e460f8d14..367337e65d13 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "0b39d9f7784089763f4194478b276e8a8e17a041" + "sha": "bc476ac3505b1793f62d64026c2537ecbf227e2e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "cac9eef310652bf138dd76b716e4986e757d62ac" + "sha": "987270824bd26f6a8c716d5e2022057b8ae7b26e" } } ] From c299bffb170ddff586bf46cbcd9b798619f8d2d4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 9 Jun 2020 02:33:01 +0200 Subject: [PATCH 0162/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.2.4 (#144) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ca9fe62aad16..88330df28c23 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -254,7 +254,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.2.4 From 869fa5733d59ae7f26a813fd5a0623ba47d6d4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 9 Jun 2020 16:15:59 +0200 Subject: [PATCH 0163/1979] fix: ResultSet#get(...) methods should auto convert values (#143) * fix: ResultSet#get(...) methods should auto convert values * tests: add additional tests * tests: add more conversion tests * tests: add more timestamp tests * tests: add timestamp tests * review: process review comments --- .../spanner/jdbc/AbstractJdbcWrapper.java | 122 ++++ .../cloud/spanner/jdbc/JdbcResultSet.java | 443 ++++++++++--- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 19 + .../spanner/jdbc/AbstractJdbcWrapperTest.java | 134 ++++ .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 2 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 605 +++++++++++++++++- .../cloud/spanner/jdbc/JdbcStatementTest.java | 2 + .../spanner/jdbc/JdbcTypeConverterTest.java | 45 ++ .../jdbc/SpannerJdbcExceptionMatcher.java | 6 +- 9 files changed, 1272 insertions(+), 106 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index abfa0f58d8ad..aef5638e1f28 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -22,9 +22,11 @@ import java.sql.Date; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.sql.Wrapper; +import java.util.Calendar; /** Base class for all Cloud Spanner JDBC classes that implement the {@link Wrapper} interface. */ abstract class AbstractJdbcWrapper implements Wrapper { @@ -147,6 +149,126 @@ static float checkedCastToFloat(double val) throws SQLException { return (float) val; } + /** + * Parses the given string value as a long. Throws {@link SQLException} if the string is not a + * valid long value. + */ + static long parseLong(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return Long.valueOf(val); + } catch (NumberFormatException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a double. Throws {@link SQLException} if the string is not a + * valid double value. + */ + static double parseDouble(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return Double.valueOf(val); + } catch (NumberFormatException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a {@link Date} value. Throws {@link SQLException} if the + * string is not a valid {@link Date} value. + */ + static Date parseDate(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return JdbcTypeConverter.toSqlDate(com.google.cloud.Date.parseDate(val)); + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid date", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a {@link Date} value in the timezone of the given {@link + * Calendar}. Throws {@link SQLException} if the string is not a valid {@link Date} value. + */ + static Date parseDate(String val, Calendar cal) throws SQLException { + Preconditions.checkNotNull(val); + Preconditions.checkNotNull(cal); + try { + return JdbcTypeConverter.toSqlDate(com.google.cloud.Date.parseDate(val), cal); + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid date", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a {@link Time} value. Throws {@link SQLException} if the + * string is not a valid {@link Time} value. + */ + static Time parseTime(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return Time.valueOf(val); + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid time", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a {@link Time} value in the timezone of the given {@link + * Calendar}. Throws {@link SQLException} if the string is not a valid {@link Time} value. + */ + static Time parseTime(String val, Calendar cal) throws SQLException { + Preconditions.checkNotNull(val); + Preconditions.checkNotNull(cal); + try { + return JdbcTypeConverter.parseSqlTime(val, cal); + } catch (IllegalArgumentException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid time", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + + /** + * Parses the given string value as a {@link Timestamp} value. Throws {@link SQLException} if the + * string is not a valid {@link Timestamp} value. + */ + static Timestamp parseTimestamp(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return JdbcTypeConverter.toSqlTimestamp(com.google.cloud.Timestamp.parseTimestamp(val)); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid timestamp", val), + com.google.rpc.Code.INVALID_ARGUMENT, + e); + } + } + + /** + * Parses the given string value as a {@link Timestamp} value in the timezone of the given {@link + * Calendar}. Throws {@link SQLException} if the string is not a valid {@link Timestamp} value. + */ + static Timestamp parseTimestamp(String val, Calendar cal) throws SQLException { + Preconditions.checkNotNull(val); + Preconditions.checkNotNull(cal); + try { + return JdbcTypeConverter.setTimestampInCalendar( + com.google.cloud.Timestamp.parseTimestamp(val).toSqlTimestamp(), cal); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid timestamp", val), + com.google.rpc.Code.INVALID_ARGUMENT, + e); + } + } + /** Should return true if this object has been closed */ public abstract boolean isClosed() throws SQLException; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index e9532554d678..2e4014ba2c68 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -115,61 +115,219 @@ private boolean isNull(int columnIndex) { return wasNull; } - private boolean isNull(String columnName) { - wasNull = spanner.isNull(columnName); - return wasNull; + SQLException createInvalidToGetAs(String sqlType, Code type) { + return JdbcSqlExceptionFactory.of( + String.format("Invalid column type to get as %s: %s", sqlType, type.name()), + com.google.rpc.Code.INVALID_ARGUMENT); } @Override public String getString(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) ? null : spanner.getString(columnIndex - 1); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? null : String.valueOf(spanner.getBoolean(spannerIndex)); + case BYTES: + return isNull ? null : spanner.getBytes(spannerIndex).toBase64(); + case DATE: + return isNull ? null : spanner.getDate(spannerIndex).toString(); + case FLOAT64: + return isNull ? null : Double.toString(spanner.getDouble(spannerIndex)); + case INT64: + return isNull ? null : Long.toString(spanner.getLong(spannerIndex)); + case STRING: + return isNull ? null : spanner.getString(spannerIndex); + case TIMESTAMP: + return isNull ? null : spanner.getTimestamp(spannerIndex).toString(); + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("string", type); + } } @Override public boolean getBoolean(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) ? false : spanner.getBoolean(columnIndex - 1); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? false : spanner.getBoolean(spannerIndex); + case FLOAT64: + return isNull ? false : spanner.getDouble(spannerIndex) != 0D; + case INT64: + return isNull ? false : spanner.getLong(spannerIndex) != 0L; + case STRING: + return isNull ? false : Boolean.valueOf(spanner.getString(spannerIndex)); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("boolean", type); + } } @Override public byte getByte(int columnIndex) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); - return checkedCastToByte(val); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? (byte) 0 : (spanner.getBoolean(spannerIndex) ? (byte) 1 : 0); + case FLOAT64: + return isNull + ? (byte) 0 + : checkedCastToByte(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); + case INT64: + return isNull ? (byte) 0 : checkedCastToByte(spanner.getLong(spannerIndex)); + case STRING: + return isNull ? (byte) 0 : checkedCastToByte(parseLong(spanner.getString(spannerIndex))); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("byte", type); + } } @Override public short getShort(int columnIndex) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); - return checkedCastToShort(val); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (short) 1 : 0); + case FLOAT64: + return isNull + ? 0 + : checkedCastToShort(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); + case INT64: + return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); + case STRING: + return isNull ? 0 : checkedCastToShort(parseLong(spanner.getString(spannerIndex))); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("short", type); + } } @Override public int getInt(int columnIndex) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); - return checkedCastToInt(val); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? 1 : 0); + case FLOAT64: + return isNull + ? 0 + : checkedCastToInt(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); + case INT64: + return isNull ? 0 : checkedCastToInt(spanner.getLong(spannerIndex)); + case STRING: + return isNull ? 0 : checkedCastToInt(parseLong(spanner.getString(spannerIndex))); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("int", type); + } } @Override public long getLong(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) ? 0L : spanner.getLong(columnIndex - 1); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? 0L : (spanner.getBoolean(spannerIndex) ? 1L : 0L); + case FLOAT64: + return isNull ? 0L : Double.valueOf(spanner.getDouble(spannerIndex)).longValue(); + case INT64: + return isNull ? 0L : spanner.getLong(spannerIndex); + case STRING: + return isNull ? 0L : parseLong(spanner.getString(spannerIndex)); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("long", type); + } } @Override public float getFloat(int columnIndex) throws SQLException { checkClosedAndValidRow(); - double val = isNull(columnIndex) ? 0D : spanner.getDouble(columnIndex - 1); - return checkedCastToFloat(val); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (float) 1 : 0); + case FLOAT64: + return isNull ? 0 : checkedCastToFloat(spanner.getDouble(spannerIndex)); + case INT64: + return isNull ? 0 : checkedCastToFloat(spanner.getLong(spannerIndex)); + case STRING: + return isNull ? 0 : checkedCastToFloat(parseDouble(spanner.getString(spannerIndex))); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("float", type); + } } @Override public double getDouble(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) ? 0D : spanner.getDouble(columnIndex - 1); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case BOOL: + return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (double) 1 : 0); + case FLOAT64: + return isNull ? 0 : spanner.getDouble(spannerIndex); + case INT64: + return isNull ? 0 : spanner.getLong(spannerIndex); + case STRING: + return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); + case BYTES: + case DATE: + case STRUCT: + case TIMESTAMP: + case ARRAY: + default: + throw createInvalidToGetAs("double", type); + } } @Override @@ -181,25 +339,74 @@ public byte[] getBytes(int columnIndex) throws SQLException { @Override public Date getDate(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.toSqlDate(spanner.getDate(columnIndex - 1)); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case DATE: + return isNull ? null : JdbcTypeConverter.toSqlDate(spanner.getDate(spannerIndex)); + case STRING: + return isNull ? null : parseDate(spanner.getString(spannerIndex)); + case TIMESTAMP: + return isNull + ? null + : new Date(spanner.getTimestamp(spannerIndex).toSqlTimestamp().getTime()); + case BOOL: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("date", type); + } } @Override public Time getTime(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnIndex - 1)); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case STRING: + return isNull ? null : parseTime(spanner.getString(spannerIndex)); + case TIMESTAMP: + return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex)); + case BOOL: + case DATE: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("time", type); + } } @Override public Timestamp getTimestamp(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(columnIndex - 1)); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case DATE: + return isNull ? null : JdbcTypeConverter.toSqlTimestamp(spanner.getDate(spannerIndex)); + case STRING: + return isNull ? null : parseTimestamp(spanner.getString(spannerIndex)); + case TIMESTAMP: + return isNull ? null : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(spannerIndex)); + case BOOL: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("timestamp", type); + } } private InputStream getInputStream(String val, Charset charset) { @@ -230,102 +437,92 @@ public InputStream getBinaryStream(int columnIndex) throws SQLException { @Override public String getString(String columnLabel) throws SQLException { - checkClosedAndValidRow(); - return isNull(columnLabel) ? null : spanner.getString(columnLabel); + return getString(findColumn(columnLabel)); } @Override public boolean getBoolean(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) ? false : spanner.getBoolean(columnLabel); + return getBoolean(findColumn(columnLabel)); } @Override public byte getByte(String columnLabel) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); - return checkedCastToByte(val); + return getByte(findColumn(columnLabel)); } @Override public short getShort(String columnLabel) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); - return checkedCastToShort(val); + return getShort(findColumn(columnLabel)); } @Override public int getInt(String columnLabel) throws SQLException { checkClosedAndValidRow(); - long val = isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); - return checkedCastToInt(val); + return getInt(findColumn(columnLabel)); } @Override public long getLong(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) ? 0L : spanner.getLong(columnLabel); + return getLong(findColumn(columnLabel)); } @Override public float getFloat(String columnLabel) throws SQLException { checkClosedAndValidRow(); - double val = isNull(columnLabel) ? 0D : spanner.getDouble(columnLabel); - return checkedCastToFloat(val); + return getFloat(findColumn(columnLabel)); } @Override public double getDouble(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) ? 0D : spanner.getDouble(columnLabel); + return getDouble(findColumn(columnLabel)); } @Override public byte[] getBytes(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) ? null : spanner.getBytes(columnLabel).toByteArray(); + return getBytes(findColumn(columnLabel)); } @Override public Date getDate(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) ? null : JdbcTypeConverter.toSqlDate(spanner.getDate(columnLabel)); + return getDate(findColumn(columnLabel)); } @Override public Time getTime(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) - ? null - : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnLabel)); + return getTime(findColumn(columnLabel)); } @Override public Timestamp getTimestamp(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return isNull(columnLabel) - ? null - : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(columnLabel)); + return getTimestamp(findColumn(columnLabel)); } @Override public InputStream getAsciiStream(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return getInputStream(getString(columnLabel), StandardCharsets.US_ASCII); + return getAsciiStream(findColumn(columnLabel)); } @Override @Deprecated public InputStream getUnicodeStream(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return getInputStream(getString(columnLabel), StandardCharsets.UTF_16LE); + return getUnicodeStream(findColumn(columnLabel)); } @Override public InputStream getBinaryStream(String columnLabel) throws SQLException { checkClosedAndValidRow(); - byte[] val = getBytes(columnLabel); - return val == null ? null : new ByteArrayInputStream(val); + return getBinaryStream(findColumn(columnLabel)); } @Override @@ -342,8 +539,7 @@ public JdbcResultSetMetaData getMetaData() throws SQLException { @Override public Object getObject(String columnLabel) throws SQLException { checkClosedAndValidRow(); - Type type = spanner.getColumnType(columnLabel); - return isNull(columnLabel) ? null : getObject(type, columnLabel); + return getObject(findColumn(columnLabel)); } @Override @@ -353,10 +549,6 @@ public Object getObject(int columnIndex) throws SQLException { return isNull(columnIndex) ? null : getObject(type, columnIndex); } - private Object getObject(Type type, String columnLabel) throws SQLException { - return getObject(type, spanner.getColumnIndex(columnLabel) + 1); - } - private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.bool()) return getBoolean(columnIndex); if (type == Type.bytes()) return getBytes(columnIndex); @@ -390,9 +582,7 @@ public Reader getCharacterStream(int columnIndex) throws SQLException { @Override public Reader getCharacterStream(String columnLabel) throws SQLException { - checkClosedAndValidRow(); - String val = getString(columnLabel); - return val == null ? null : new StringReader(val); + return getCharacterStream(findColumn(columnLabel)); } @Override @@ -404,7 +594,7 @@ public BigDecimal getBigDecimal(int columnIndex) throws SQLException { @Override public BigDecimal getBigDecimal(String columnLabel) throws SQLException { checkClosedAndValidRow(); - return getBigDecimal(spanner.getColumnIndex(columnLabel) + 1, false, 0); + return getBigDecimal(findColumn(columnLabel), false, 0); } @Override @@ -418,36 +608,48 @@ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException @Deprecated public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { checkClosedAndValidRow(); - return getBigDecimal(spanner.getColumnIndex(columnLabel) + 1, true, scale); + return getBigDecimal(findColumn(columnLabel), true, scale); } private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) throws SQLException { - Type type = spanner.getColumnType(columnIndex - 1); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + boolean isNull = isNull(columnIndex); BigDecimal res; - if (isNull(columnIndex)) { - res = null; - } else { - if (type.getCode() == Code.STRING) { + switch (type) { + case BOOL: + res = + isNull + ? null + : (spanner.getBoolean(columnIndex - 1) ? BigDecimal.ONE : BigDecimal.ZERO); + break; + case FLOAT64: + res = isNull ? null : BigDecimal.valueOf(spanner.getDouble(spannerIndex)); + break; + case INT64: + res = isNull ? null : BigDecimal.valueOf(spanner.getLong(spannerIndex)); + break; + case STRING: try { - res = new BigDecimal(spanner.getString(columnIndex - 1)); + res = isNull ? null : new BigDecimal(spanner.getString(spannerIndex)); + break; } catch (NumberFormatException e) { throw JdbcSqlExceptionFactory.of( "The column does not contain a valid BigDecimal", com.google.rpc.Code.INVALID_ARGUMENT, e); } - } else if (type.getCode() == Code.INT64) { - res = BigDecimal.valueOf(spanner.getLong(columnIndex - 1)); - } else if (type.getCode() == Code.FLOAT64) { - res = BigDecimal.valueOf(spanner.getDouble(columnIndex - 1)); - } else { - throw JdbcSqlExceptionFactory.of( - "The column does not contain a valid BigDecimal", com.google.rpc.Code.INVALID_ARGUMENT); - } - if (fixedScale) { - res = res.setScale(scale, RoundingMode.HALF_UP); - } + case BYTES: + case DATE: + case TIMESTAMP: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("BigDecimal", type); + } + if (res != null && fixedScale) { + res = res.setScale(scale, RoundingMode.HALF_UP); } return res; } @@ -506,56 +708,99 @@ public Array getArray(int columnIndex) throws SQLException { @Override public Date getDate(int columnIndex, Calendar cal) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.toSqlDate(spanner.getDate(columnIndex - 1), cal); + if (isNull(columnIndex)) { + return null; + } + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case DATE: + return JdbcTypeConverter.toSqlDate(spanner.getDate(spannerIndex), cal); + case STRING: + return parseDate(spanner.getString(spannerIndex), cal); + case TIMESTAMP: + return new Date( + JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal).getTime()); + case BOOL: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("date", type); + } } @Override public Date getDate(String columnLabel, Calendar cal) throws SQLException { - checkClosedAndValidRow(); - return isNull(columnLabel) - ? null - : JdbcTypeConverter.toSqlDate(spanner.getDate(columnLabel), cal); + return getDate(findColumn(columnLabel), cal); } @Override public Time getTime(int columnIndex, Calendar cal) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnIndex - 1), cal); + boolean isNull = isNull(columnIndex); + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case STRING: + return isNull ? null : parseTime(spanner.getString(spannerIndex), cal); + case TIMESTAMP: + return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex), cal); + case BOOL: + case DATE: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("time", type); + } } @Override public Time getTime(String columnLabel, Calendar cal) throws SQLException { - checkClosedAndValidRow(); - return isNull(columnLabel) - ? null - : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(columnLabel), cal); + return getTime(findColumn(columnLabel), cal); } @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) - ? null - : JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(columnIndex - 1), cal); + if (isNull(columnIndex)) { + return null; + } + int spannerIndex = columnIndex - 1; + Code type = spanner.getColumnType(spannerIndex).getCode(); + switch (type) { + case DATE: + return JdbcTypeConverter.toSqlTimestamp(spanner.getDate(spannerIndex), cal); + case STRING: + return parseTimestamp(spanner.getString(spannerIndex), cal); + case TIMESTAMP: + return JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal); + case BOOL: + case FLOAT64: + case INT64: + case BYTES: + case STRUCT: + case ARRAY: + default: + throw createInvalidToGetAs("timestamp", type); + } } @Override public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - checkClosedAndValidRow(); - return isNull(columnLabel) - ? null - : JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(columnLabel), cal); + return getTimestamp(findColumn(columnLabel), cal); } @Override public URL getURL(int columnIndex) throws SQLException { checkClosedAndValidRow(); try { - return isNull(columnIndex) ? null : new URL(spanner.getString(columnIndex - 1)); + return isNull(columnIndex) ? null : new URL(getString(columnIndex)); } catch (MalformedURLException e) { throw JdbcSqlExceptionFactory.of( "Invalid URL: " + spanner.getString(columnIndex - 1), diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index a11cb5e899a1..e922e58598c9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -224,6 +224,14 @@ static java.sql.Timestamp toSqlTimestamp(Timestamp ts) { return ts == null ? null : ts.toSqlTimestamp(); } + static java.sql.Timestamp toSqlTimestamp(Date date) { + return date == null ? null : new java.sql.Timestamp(toSqlDate(date).getTime()); + } + + static java.sql.Timestamp toSqlTimestamp(Date date, Calendar cal) { + return date == null ? null : new java.sql.Timestamp(toSqlDate(date, cal).getTime()); + } + static java.sql.Timestamp getAsSqlTimestamp(Timestamp ts, Calendar cal) { return ts == null ? null : getTimestampInCalendar(ts.toSqlTimestamp(), cal); } @@ -334,6 +342,17 @@ static Time toSqlTime(Timestamp ts, Calendar cal) { return null; } + @SuppressWarnings("deprecation") + static java.sql.Time parseSqlTime(String val, Calendar cal) { + if (val != null) { + Time time = Time.valueOf(val); + cal.set(1970, 0, 1, time.getHours(), time.getMinutes(), time.getSeconds()); + cal.clear(Calendar.MILLISECOND); + return new java.sql.Time(cal.getTimeInMillis()); + } + return null; + } + static List toGoogleBytes(byte[][] bytes) { List res = new ArrayList<>(bytes.length); for (int index = 0; index < bytes.length; index++) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index 1a391dfb24f5..593466f754a2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -17,8 +17,15 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; +import com.google.cloud.Timestamp; +import com.google.rpc.Code; +import java.sql.Date; import java.sql.SQLException; +import java.sql.Time; +import java.util.Calendar; +import java.util.TimeZone; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -176,4 +183,131 @@ private boolean unwrapSucceeds(AbstractJdbcWrapper subject, Class iface) { return false; } } + + @Test + public void testParseDouble() throws SQLException { + assertThat(AbstractJdbcWrapper.parseDouble("3.14")).isEqualTo(3.14D); + try { + AbstractJdbcWrapper.parseDouble("not a number"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testParseDate() throws SQLException { + assertThat(AbstractJdbcWrapper.parseDate("2020-06-01")).isEqualTo(new Date(2020 - 1900, 5, 1)); + try { + AbstractJdbcWrapper.parseDate("01-06-2020"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @Test + public void testParseDateWithCalendar() throws SQLException { + assertThat( + AbstractJdbcWrapper.parseDate( + "2020-06-01", Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")))) + .isEqualTo( + new Date( + Timestamp.parseTimestamp("2020-06-01T00:00:00-07:00").toSqlTimestamp().getTime())); + assertThat( + AbstractJdbcWrapper.parseDate( + "2020-06-01", Calendar.getInstance(TimeZone.getTimeZone("Europe/Amsterdam")))) + .isEqualTo( + new Date( + Timestamp.parseTimestamp("2020-06-01T00:00:00+02:00").toSqlTimestamp().getTime())); + try { + AbstractJdbcWrapper.parseDate("01-06-2020", Calendar.getInstance()); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @SuppressWarnings("deprecation") + @Test + public void testParseTime() throws SQLException { + assertThat(AbstractJdbcWrapper.parseTime("10:31:05")).isEqualTo(new Time(10, 31, 5)); + try { + AbstractJdbcWrapper.parseTime("10.31.05"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @Test + public void testParseTimeWithCalendar() throws SQLException { + assertThat( + AbstractJdbcWrapper.parseTime( + "10:31:05", Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")))) + .isEqualTo( + new Time( + Timestamp.parseTimestamp("1970-01-01T10:31:05-08:00").toSqlTimestamp().getTime())); + assertThat( + AbstractJdbcWrapper.parseTime( + "10:31:05", Calendar.getInstance(TimeZone.getTimeZone("Pacific/Auckland")))) + .isEqualTo( + new Time( + Timestamp.parseTimestamp("1970-01-01T10:31:05+12:00").toSqlTimestamp().getTime())); + try { + AbstractJdbcWrapper.parseTime("10.31.05", Calendar.getInstance()); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @Test + public void testParseTimestamp() throws SQLException { + assertThat(AbstractJdbcWrapper.parseTimestamp("2020-06-01T10:31:05Z")) + .isEqualTo(Timestamp.parseTimestamp("2020-06-01T10:31:05Z").toSqlTimestamp()); + assertThat(AbstractJdbcWrapper.parseTimestamp("2020-06-01T10:31:05.123Z")) + .isEqualTo(Timestamp.parseTimestamp("2020-06-01T10:31:05.123Z").toSqlTimestamp()); + assertThat(AbstractJdbcWrapper.parseTimestamp("2020-06-01T10:31Z")) + .isEqualTo(Timestamp.parseTimestamp("2020-06-01T10:31:00Z").toSqlTimestamp()); + assertThat(AbstractJdbcWrapper.parseTimestamp("2020-06-01T10:31")) + .isEqualTo(Timestamp.parseTimestamp("2020-06-01T10:31:00Z").toSqlTimestamp()); + assertThat(AbstractJdbcWrapper.parseTimestamp("1970-01-01T00:00:00Z")) + .isEqualTo(Timestamp.ofTimeMicroseconds(0L).toSqlTimestamp()); + try { + AbstractJdbcWrapper.parseTimestamp("2020-06-01T10"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } + + @Test + public void testParseTimestampWithCalendar() throws SQLException { + assertThat( + AbstractJdbcWrapper.parseTimestamp( + "2020-02-01T10:31:05Z", + Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")))) + .isEqualTo(Timestamp.parseTimestamp("2020-02-01T10:31:05-08:00").toSqlTimestamp()); + assertThat( + AbstractJdbcWrapper.parseTimestamp( + "2020-06-01T10:31:05Z", + Calendar.getInstance(TimeZone.getTimeZone("Europe/Amsterdam")))) + .isEqualTo(Timestamp.parseTimestamp("2020-06-01T10:31:05+02:00").toSqlTimestamp()); + try { + AbstractJdbcWrapper.parseTimestamp( + "2020-06-01T10", Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"))); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 416721328519..1f886750c8c5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -29,6 +29,7 @@ import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; 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; @@ -36,7 +37,6 @@ import com.google.spanner.v1.TypeCode; import io.grpc.Server; import io.grpc.Status; -import io.grpc.Status.Code; import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 44eefa97010f..9429288d2fd3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -35,7 +35,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; -import io.grpc.Status.Code; +import com.google.rpc.Code; import java.io.IOException; import java.io.InputStream; import java.io.Reader; @@ -112,6 +112,19 @@ public class JdbcResultSetTest { private static final int URL_COLINDEX_NULL = 19; private static final int URL_COLINDEX_NOTNULL = 20; + private static final String STRING_COL_NUMBER = "STRING_COL_NUMBER"; + private static final int STRING_COLINDEX_NUMBER = 21; + private static final String STRING_NUMBER_VALUE = "123"; + private static final String STRING_COL_DATE = "STRING_COL_DATE"; + private static final int STRING_COLINDEX_DATE = 22; + private static final String STRING_DATE_VALUE = "2020-06-01"; + private static final String STRING_COL_TIMESTAMP = "STRING_COL_TIMESTAMP"; + private static final int STRING_COLINDEX_TIMESTAMP = 23; + private static final String STRING_TIMESTAMP_VALUE = "2020-06-01T10:31:15.123Z"; + private static final String STRING_COL_TIME = "STRING_COL_TIME"; + private static final int STRING_COLINDEX_TIME = 24; + private static final String STRING_TIME_VALUE = "10:31:15"; + private JdbcResultSet subject; static ResultSet getMockResultSet() { @@ -136,7 +149,11 @@ static ResultSet getMockResultSet() { StructField.of(ARRAY_COL_NULL, Type.array(Type.int64())), StructField.of(ARRAY_COL_NOT_NULL, Type.array(Type.int64())), StructField.of(URL_COL_NULL, Type.string()), - StructField.of(URL_COL_NOT_NULL, Type.string())), + StructField.of(URL_COL_NOT_NULL, Type.string()), + StructField.of(STRING_COL_NUMBER, Type.string()), + StructField.of(STRING_COL_DATE, Type.string()), + StructField.of(STRING_COL_TIMESTAMP, Type.string()), + StructField.of(STRING_COL_TIME, Type.string())), Arrays.asList( Struct.newBuilder() .set(STRING_COL_NULL) @@ -179,6 +196,14 @@ static ResultSet getMockResultSet() { .to((String) null) .set(URL_COL_NOT_NULL) .to(URL_VALUE) + .set(STRING_COL_NUMBER) + .to(STRING_NUMBER_VALUE) + .set(STRING_COL_DATE) + .to(STRING_DATE_VALUE) + .set(STRING_COL_TIMESTAMP) + .to(STRING_TIMESTAMP_VALUE) + .set(STRING_COL_TIME) + .to(STRING_TIME_VALUE) .build())); } @@ -242,6 +267,84 @@ public void testGetStringIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetStringIndexForBool() throws SQLException { + assertNotNull(subject.getString(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(String.valueOf(BOOLEAN_VALUE), subject.getString(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForInt64() throws SQLException { + assertNotNull(subject.getString(LONG_COLINDEX_NOTNULL)); + assertEquals(String.valueOf(LONG_VALUE), subject.getString(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForFloat64() throws SQLException { + assertNotNull(subject.getString(DOUBLE_COLINDEX_NOTNULL)); + assertEquals(String.valueOf(DOUBLE_VALUE), subject.getString(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForBytes() throws SQLException { + assertNotNull(subject.getString(BYTES_COLINDEX_NOTNULL)); + assertEquals(BYTES_VALUE.toBase64(), subject.getString(BYTES_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(BYTES_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForDate() throws SQLException { + assertNotNull(subject.getString(DATE_COLINDEX_NOTNULL)); + assertEquals(String.valueOf(DATE_VALUE), subject.getString(DATE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(DATE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForTimestamp() throws SQLException { + assertNotNull(subject.getString(TIMESTAMP_COLINDEX_NOTNULL)); + assertEquals(String.valueOf(TIMESTAMP_VALUE), subject.getString(TIMESTAMP_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(TIMESTAMP_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetStringIndexForArray() throws SQLException { + try { + subject.getString(ARRAY_COLINDEX_NOTNULL); + fail("missing SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + JdbcSqlException jse = (JdbcSqlException) e; + assertEquals(jse.getCode(), Code.INVALID_ARGUMENT); + } + } + + @Test + public void testGetStringIndexForNullArray() throws SQLException { + try { + subject.getString(ARRAY_COLINDEX_NULL); + fail("missing SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + JdbcSqlException jse = (JdbcSqlException) e; + assertEquals(jse.getCode(), Code.INVALID_ARGUMENT); + } + } + @Test public void testGetNStringIndex() throws SQLException { assertNotNull(subject.getNString(STRING_COLINDEX_NOTNULL)); @@ -284,15 +387,120 @@ public void testGetBooleanIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetBooleanIndexForLong() throws SQLException { + assertNotNull(subject.getBoolean(LONG_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertFalse(subject.getBoolean(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBooleanIndexForDouble() throws SQLException { + assertNotNull(subject.getBoolean(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertFalse(subject.getBoolean(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBooleanIndexForString() throws SQLException { + assertNotNull(subject.getBoolean(STRING_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertFalse(subject.getBoolean(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBooleanIndexForDate() throws SQLException { + try { + subject.getBoolean(DATE_COLINDEX_NOTNULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + try { + subject.getBoolean(DATE_COLINDEX_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + + @Test + public void testGetNullBooleanIndex() throws SQLException { + assertFalse(subject.getBoolean(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertFalse(subject.getBoolean(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertFalse(subject.getBoolean(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @Test public void testGetLongIndex() throws SQLException { assertNotNull(subject.getLong(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getLong(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); - assertEquals(0l, subject.getLong(LONG_COLINDEX_NULL)); + assertEquals(0L, subject.getLong(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetLongIndexForBool() throws SQLException { + assertNotNull(subject.getLong(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1L : 0L, subject.getLong(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0L, subject.getLong(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetLongIndexForFloat64() throws SQLException { + assertNotNull(subject.getLong(DOUBLE_COLINDEX_NOTNULL)); + assertEquals((long) DOUBLE_VALUE, subject.getLong(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertEquals(0L, subject.getLong(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetLongIndexForString() throws SQLException { + try { + subject.getLong(STRING_COLINDEX_NOTNULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); + } + } + + @Test + public void testGetLongIndexForNumberString() throws SQLException { + assertEquals( + Long.valueOf(STRING_NUMBER_VALUE).longValue(), subject.getLong(STRING_COLINDEX_NUMBER)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetLongIndexForNullString() throws SQLException { + assertEquals(0L, subject.getLong(STRING_COLINDEX_NULL)); assertTrue(subject.wasNull()); } + @Test + public void testGetLongIndexForTimestamp() throws SQLException { + try { + subject.getLong(TIMESTAMP_COLINDEX_NOTNULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); + } + } + @Test public void testGetDoubleIndex() throws SQLException { assertNotNull(subject.getDouble(DOUBLE_COLINDEX_NOTNULL)); @@ -302,6 +510,47 @@ public void testGetDoubleIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetDoubleIndexFromString() throws SQLException { + assertNotNull(subject.getDouble(STRING_COLINDEX_NUMBER)); + assertEquals( + Double.valueOf(STRING_NUMBER_VALUE).doubleValue(), + subject.getDouble(STRING_COLINDEX_NUMBER), + 0d); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getDouble(STRING_COLINDEX_NULL), 0d); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDoubleIndexFromBool() throws SQLException { + assertNotNull(subject.getDouble(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1d : 0d, subject.getDouble(BOOLEAN_COLINDEX_NOTNULL), 0d); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getDouble(BOOLEAN_COLINDEX_NULL), 0d); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDoubleIndexFromInt64() throws SQLException { + assertNotNull(subject.getDouble(LONG_COLINDEX_NOTNULL)); + assertEquals(LONG_VALUE, subject.getDouble(LONG_COLINDEX_NOTNULL), 0d); + assertFalse(subject.wasNull()); + assertEquals(0d, subject.getDouble(LONG_COLINDEX_NULL), 0d); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDoubleIndexFromTimestamp() throws SQLException { + try { + subject.getDouble(TIMESTAMP_COLINDEX_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); + } + } + @SuppressWarnings("deprecation") @Test public void testGetBigDecimalIndexAndScale() throws SQLException { @@ -336,6 +585,37 @@ public void testGetDateIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetDateIndexFromString() throws SQLException { + assertNotNull(subject.getDate(STRING_COLINDEX_DATE)); + assertEquals(java.sql.Date.valueOf(STRING_DATE_VALUE), subject.getDate(STRING_COLINDEX_DATE)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDateIndexFromTimestamp() throws SQLException { + assertNotNull(subject.getDate(TIMESTAMP_COLINDEX_NOTNULL)); + assertEquals( + new java.sql.Date(TIMESTAMP_VALUE.toSqlTimestamp().getTime()), + subject.getDate(TIMESTAMP_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getDate(TIMESTAMP_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetDateIndexFromInt64() { + try { + subject.getDate(LONG_COLINDEX_NOTNULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + @Test public void testGetTimeIndex() throws SQLException { assertNotNull(subject.getTime(TIME_COLINDEX_NOTNULL)); @@ -346,6 +626,15 @@ public void testGetTimeIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetTimeIndexFromString() throws SQLException { + assertNotNull(subject.getTime(STRING_COLINDEX_TIME)); + assertEquals(Time.valueOf(STRING_TIME_VALUE), subject.getTime(STRING_COLINDEX_TIME)); + assertFalse(subject.wasNull()); + assertNull(subject.getTime(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @Test public void testGetTimestampIndex() throws SQLException { assertNotNull(subject.getTimestamp(TIMESTAMP_COLINDEX_NOTNULL)); @@ -356,6 +645,36 @@ public void testGetTimestampIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetTimestampIndexFromString() throws SQLException { + assertNotNull(subject.getTimestamp(STRING_COLINDEX_TIMESTAMP)); + assertEquals( + Timestamp.parseTimestamp(STRING_TIMESTAMP_VALUE).toSqlTimestamp(), + subject.getTimestamp(STRING_COLINDEX_TIMESTAMP)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @SuppressWarnings("deprecation") + @Test + public void testGetTimestampIndexFromDate() throws SQLException { + assertNotNull(subject.getTimestamp(DATE_COLINDEX_NOTNULL)); + assertEquals( + new java.sql.Timestamp( + DATE_VALUE.getYear() - 1900, + DATE_VALUE.getMonth() - 1, + DATE_VALUE.getDayOfMonth(), + 0, + 0, + 0, + 0), + subject.getTimestamp(DATE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(DATE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @Test public void testGetStringLabel() throws SQLException { assertNotNull(subject.getString(STRING_COL_NOT_NULL)); @@ -591,6 +910,33 @@ public void testGetTimestampIndexCalendar() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetTimestampIndexCalendarFromString() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); + + assertNotNull(subject.getTimestamp(STRING_COLINDEX_TIMESTAMP, cal)); + assertEquals( + Timestamp.parseTimestamp(STRING_TIMESTAMP_VALUE.replace("Z", "-07:00")).toSqlTimestamp(), + subject.getTimestamp(STRING_COLINDEX_TIMESTAMP, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(STRING_COLINDEX_NULL, cal)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetTimestampIndexCalendarFromDate() throws SQLException { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); + + assertNotNull(subject.getTimestamp(DATE_COLINDEX_NOTNULL, cal)); + assertEquals( + Timestamp.parseTimestamp(String.format("%sT00:00:00-08:00", DATE_VALUE.toString())) + .toSqlTimestamp(), + subject.getTimestamp(DATE_COLINDEX_NOTNULL, cal)); + assertFalse(subject.wasNull()); + assertNull(subject.getTimestamp(DATE_COLINDEX_NULL, cal)); + assertTrue(subject.wasNull()); + } + @Test public void testGetTimestampLabelCalendar() throws SQLException { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); @@ -621,6 +967,47 @@ public void testGetByteIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetByteIndexFromString() throws SQLException { + assertNotNull(subject.getByte(STRING_COLINDEX_NUMBER)); + assertEquals( + Byte.valueOf(STRING_NUMBER_VALUE).byteValue(), subject.getByte(STRING_COLINDEX_NUMBER)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetByteIndexFromDouble() throws SQLException { + assertNotNull(subject.getByte(DOUBLE_COLINDEX_NOTNULL)); + assertEquals((byte) DOUBLE_VALUE, subject.getByte(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetByteIndexFromBoolean() throws SQLException { + assertNotNull(subject.getByte(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getByte(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetNullByteIndex() throws SQLException { + assertEquals(0, subject.getByte(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getByte(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getByte(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getByte(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + try { + subject.getByte(TIMESTAMP_COL_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + @Test public void testGetShortIndex() throws SQLException { assertNotNull(subject.getShort(LONG_COLINDEX_NOTNULL)); @@ -630,6 +1017,58 @@ public void testGetShortIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetShortIndexFromString() throws SQLException { + assertNotNull(subject.getShort(STRING_COLINDEX_NUMBER)); + assertEquals( + Short.valueOf(STRING_NUMBER_VALUE).shortValue(), subject.getShort(STRING_COLINDEX_NUMBER)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetShortIndexFromDouble() throws SQLException { + assertNotNull(subject.getShort(DOUBLE_COLINDEX_NOTNULL)); + assertEquals((short) DOUBLE_VALUE, subject.getShort(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetShortIndexFromBoolean() throws SQLException { + assertNotNull(subject.getShort(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getShort(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetShortIndexFromBytes() throws SQLException { + try { + subject.getShort(BYTES_COL_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + + @Test + public void testGetNullShortIndex() throws SQLException { + assertEquals(0, subject.getShort(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getShort(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getShort(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getShort(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + try { + subject.getShort(TIMESTAMP_COL_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + @Test public void testGetIntIndex() throws SQLException { assertNotNull(subject.getInt(LONG_COLINDEX_NOTNULL)); @@ -640,6 +1079,58 @@ public void testGetIntIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetIntIndexFromString() throws SQLException { + assertNotNull(subject.getInt(STRING_COLINDEX_NUMBER)); + assertEquals( + Integer.valueOf(STRING_NUMBER_VALUE).intValue(), subject.getInt(STRING_COLINDEX_NUMBER)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntIndexFromDouble() throws SQLException { + assertNotNull(subject.getInt(DOUBLE_COLINDEX_NOTNULL)); + assertEquals((int) DOUBLE_VALUE, subject.getInt(DOUBLE_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntIndexFromBoolean() throws SQLException { + assertNotNull(subject.getInt(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getInt(BOOLEAN_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntIndexFromTimestamp() throws SQLException { + try { + subject.getInt(TIMESTAMP_COL_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + + @Test + public void testGetNullIntIndex() throws SQLException { + assertEquals(0, subject.getInt(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getInt(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getInt(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(0, subject.getInt(STRING_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + try { + subject.getInt(TIMESTAMP_COL_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + } + @Test public void testGetFloatIndex() throws SQLException { assertNotNull(subject.getFloat(DOUBLE_COLINDEX_NOTNULL)); @@ -650,6 +1141,47 @@ public void testGetFloatIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetFloatIndexFromString() throws SQLException { + assertNotNull(subject.getFloat(STRING_COLINDEX_NUMBER)); + assertEquals( + Float.valueOf(STRING_NUMBER_VALUE).floatValue(), + subject.getFloat(STRING_COLINDEX_NUMBER), + 0f); + assertFalse(subject.wasNull()); + assertEquals(0f, subject.getFloat(STRING_COLINDEX_NULL), 0f); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetFloatIndexFromBool() throws SQLException { + assertNotNull(subject.getFloat(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(BOOLEAN_VALUE ? 1f : 0f, subject.getFloat(BOOLEAN_COLINDEX_NOTNULL), 0f); + assertFalse(subject.wasNull()); + assertEquals(0f, subject.getFloat(BOOLEAN_COLINDEX_NULL), 0f); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetFloatIndexFromInt64() throws SQLException { + assertNotNull(subject.getFloat(LONG_COLINDEX_NOTNULL)); + assertEquals(LONG_VALUE, subject.getFloat(LONG_COLINDEX_NOTNULL), 0f); + assertFalse(subject.wasNull()); + assertEquals(0f, subject.getFloat(LONG_COLINDEX_NULL), 0f); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetFloatIndexFromTimestamp() throws SQLException { + try { + subject.getFloat(TIMESTAMP_COLINDEX_NULL); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); + } + } + @Test public void testGetByteLabel() throws SQLException { assertNotNull(subject.getByte(LONG_COL_NOT_NULL)); @@ -858,6 +1390,73 @@ public void testGetAsciiStreamIndex() throws SQLException, IOException { assertTrue(subject.wasNull()); } + @Test + public void testGetAsciiStreamIndexForBool() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(BOOLEAN_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(BOOLEAN_COLINDEX_NOTNULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals( + String.valueOf(BOOLEAN_VALUE), new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(4, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(BOOLEAN_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamIndexForInt64() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(LONG_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(LONG_COLINDEX_NOTNULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(String.valueOf(LONG_VALUE), new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(1, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(LONG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamIndexForFloat64() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(DOUBLE_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(DOUBLE_COLINDEX_NOTNULL); + byte[] cbuf = new byte[20]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(String.valueOf(DOUBLE_VALUE), new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(13, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(DOUBLE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamIndexForDate() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(DATE_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(DATE_COLINDEX_NOTNULL); + byte[] cbuf = new byte[10]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals(String.valueOf(DATE_VALUE), new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(10, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(DATE_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetAsciiStreamIndexForTimestamp() throws SQLException, IOException { + assertNotNull(subject.getAsciiStream(TIMESTAMP_COLINDEX_NOTNULL)); + InputStream actual = subject.getAsciiStream(TIMESTAMP_COLINDEX_NOTNULL); + byte[] cbuf = new byte[100]; + int len = actual.read(cbuf, 0, cbuf.length); + assertEquals( + String.valueOf(TIMESTAMP_VALUE), new String(cbuf, 0, len, StandardCharsets.US_ASCII)); + assertEquals(30, len); + assertFalse(subject.wasNull()); + assertNull(subject.getAsciiStream(TIMESTAMP_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @SuppressWarnings("deprecation") @Test public void testGetUnicodeStreamIndex() throws SQLException, IOException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index c1b1e992fc6c..7349bfce72de 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.Connection; import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.connection.StatementResult; @@ -57,6 +58,7 @@ private JdbcStatement createStatement() { com.google.cloud.spanner.ResultSet resultSet = mock(com.google.cloud.spanner.ResultSet.class); when(resultSet.next()).thenReturn(true, false); + when(resultSet.getColumnType(0)).thenReturn(Type.int64()); when(resultSet.getLong(0)).thenReturn(1L); StatementResult selectResult = mock(StatementResult.class); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 870711d02fa4..58ef03a1c9ed 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -760,4 +760,49 @@ public void testToJavaByteArrays() { List output = toJavaByteArrays(input); assertThat(Arrays.deepEquals(expected.toArray(), output.toArray())).isTrue(); } + + @SuppressWarnings("deprecation") + @Test + public void testDateToSqlTimestamp() { + assertThat(JdbcTypeConverter.toSqlTimestamp(com.google.cloud.Date.fromYearMonthDay(2020, 6, 1))) + .isEqualTo(new Timestamp(2020 - 1900, 5, 1, 0, 0, 0, 0)); + } + + @Test + public void testDateToSqlTimestampWithCalendar() { + assertThat( + JdbcTypeConverter.toSqlTimestamp( + com.google.cloud.Date.fromYearMonthDay(2020, 6, 1), + Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")))) + .isEqualTo( + com.google.cloud.Timestamp.parseTimestamp("2020-06-01T00:00:00-07:00") + .toSqlTimestamp()); + assertThat( + JdbcTypeConverter.toSqlTimestamp( + com.google.cloud.Date.fromYearMonthDay(2020, 6, 1), + Calendar.getInstance(TimeZone.getTimeZone("Europe/Amsterdam")))) + .isEqualTo( + com.google.cloud.Timestamp.parseTimestamp("2020-06-01T00:00:00+02:00") + .toSqlTimestamp()); + } + + @Test + public void testParseSqlTimeWithCalendar() { + assertThat( + JdbcTypeConverter.parseSqlTime( + "10:31:15", Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")))) + .isEqualTo( + new Time( + com.google.cloud.Timestamp.parseTimestamp("1970-01-01T10:31:15-08:00") + .toSqlTimestamp() + .getTime())); + assertThat( + JdbcTypeConverter.parseSqlTime( + "10:31:15", Calendar.getInstance(TimeZone.getTimeZone("Europe/Amsterdam")))) + .isEqualTo( + new Time( + com.google.cloud.Timestamp.parseTimestamp("1970-01-01T10:31:15+01:00") + .toSqlTimestamp() + .getTime())); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java index 5a1663c871b6..4cd5e9b9be1b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.common.base.Preconditions; -import io.grpc.Status.Code; +import com.google.rpc.Code; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; @@ -52,9 +52,9 @@ public boolean matches(Object item) { if (exceptionClass.isAssignableFrom(item.getClass())) { JdbcSqlException exception = (JdbcSqlException) item; if (message == null) { - return exception.getErrorCode() == errorCode.value(); + return exception.getErrorCode() == errorCode.getNumber(); } - return exception.getErrorCode() == errorCode.value() + return exception.getErrorCode() == errorCode.getNumber() && exception.getMessage().endsWith(": " + message); } return false; From d37ed18a87cc1e1ab48333d188732a89dbc51ceb Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Jun 2020 04:57:58 +0200 Subject: [PATCH 0164/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.18 (#150) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 26df0156453c..ecdfc9e084db 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.17 + 1.0.18 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index db021acdaa70..a2399748cf50 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.17 + 1.0.18 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 79a9a78fcdd1..299de5d84939 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.17 + 1.0.18 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 27c094d84d91..e37ccdde01bc 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.17 + 1.0.18 From 9dfa2215683207bac8e945078f257cdb213511e6 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 11 Jun 2020 02:03:39 +0200 Subject: [PATCH 0165/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.8.0 (#151) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | minor | `0.6.0` -> `0.8.0` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.8.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​080-httpswwwgithubcomgoogleapisjava-shared-configcomparev070v080-2020-06-10) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.7.0...v0.8.0) ##### Features - revert "feat: mark auto-value-annotations scope as provided" ([#​154](https://www.github.com/googleapis/java-shared-config/issues/154)) ([88afb4e](https://www.github.com/googleapis/java-shared-config/commit/88afb4e7c57cb6e00929c098135314a926d9da30)) ### [`v0.7.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​070-httpswwwgithubcomgoogleapisjava-shared-configcomparev060v070-2020-06-10) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.6.0...v0.7.0) ##### Features - mark auto-value-annotations scope as provided ([#​151](https://www.github.com/googleapis/java-shared-config/issues/151)) ([44ea4cb](https://www.github.com/googleapis/java-shared-config/commit/44ea4cbbf92b4ad35ffaffb7a01a1bce05063daf)) ##### Bug Fixes - lock the google-java-format version used by formatter plugin ([#​149](https://www.github.com/googleapis/java-shared-config/issues/149)) ([d58c054](https://www.github.com/googleapis/java-shared-config/commit/d58c05437a4ea8767db2bebfcc405ec77aeb9705))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 88330df28c23..3ff57c48726a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.6.0 + 0.8.0 From c4a7f531856146f5ae546ba1f144a5a889b351cc Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 15 Jun 2020 22:35:30 +0200 Subject: [PATCH 0166/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.8.1 --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ff57c48726a..7668d82844f9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.8.0 + 0.8.1 From b7d35fc4459bdf0cce3f353d443a4cf2e628b228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 17 Jun 2020 06:25:56 +0200 Subject: [PATCH 0167/1979] fix: add missing documentation for connection properties (#155) Add documentation for properties that are supported for end users. This change does not add documentation for the userAgent property, as it is not a property that should be set by end users. This property should only be set by libraries that are maintained by Google. Fixes #152 --- .../src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 2d83a34d07a7..65b944dbbcb8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -87,6 +87,8 @@ * connection. Default is true. @see {@link * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} * for more information. + *
  • numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. + *
  • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to the server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. *
  • optimizerVersion (string): The query optimizer version to use for the connection. The value must be either a valid version number or LATEST. If no value is specified, the query optimizer version specified in the environment variable SPANNER_OPTIMIZER_VERSION will be used. If no query optimizer version is specified in the connection URL or in the environment variable, the default query optimizer version of Cloud Spanner will be used. * */ From a7ef4f16ce6e0e71820adcfe6c8cd7580a756784 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Jun 2020 11:42:21 +0200 Subject: [PATCH 0168/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v6 (#156) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:libraries-bom to v6 * deps: also update Spanner test version * deps: exclude opencensus-api from test jar dep Exclude the opencensus-api dependency from the test-jar for now, until the test jar version is included in the bom (from Spanner version 1.55.2). * deps: exclude all opencensus deps from test-jar * deps: list all exclusions * deps: exclude transitive dep and add specific * deps: add ignore unused dependencies Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 29 +++++++++++++++++++++- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7668d82844f9..a9c71bae3328 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -72,7 +72,7 @@ com.google.cloud libraries-bom - 5.3.0 + 6.0.0 pom import @@ -168,6 +168,30 @@ ${spanner.test.version} test-jar test + + + + io.opencensus + opencensus-api + + + io.opencensus + opencensus-contrib-grpc-util + + + + + + io.opencensus + opencensus-api + 0.24.0 + test + + + io.opencensus + opencensus-contrib-grpc-util + 0.24.0 + test com.google.api.grpc @@ -322,6 +346,9 @@ com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 + + io.opencensus:opencensus-api + io.opencensus:opencensus-contrib-grpc-util diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e37ccdde01bc..57f9da270215 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 5.4.0 + 6.0.0 pom import From 3194a78c07168d677cc3e29d66d3059ed384031a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Jun 2020 19:43:35 +0200 Subject: [PATCH 0169/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v7 (#161) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `6.0.0` -> `7.0.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a9c71bae3328..12a75f8e1285 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -72,7 +72,7 @@ com.google.cloud libraries-bom - 6.0.0 + 7.0.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 57f9da270215..50d4bc89ea49 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 6.0.0 + 7.0.0 pom import From 2037f75b9ea62da0bf7ed13eee638e932d94e1c6 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 17 Jun 2020 23:32:13 -0700 Subject: [PATCH 0170/1979] ci: switch to secret manager for sample/integration tests (#157) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/2c593734-539a-435d-8a04-27f04c90082f/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/c4f3059c27591eb24d6942a0e357ec94c80459f2 Source-Link: https://github.com/googleapis/synthtool/commit/6eb80fa9f96433af8dbeb1c8323aa80cda49b374 Source-Link: https://github.com/googleapis/synthtool/commit/6d3eed67a45fd58f9c7bfa173c32e4fd4fed058f Source-Link: https://github.com/googleapis/synthtool/commit/d1addcdf80aa9ddef8c932c89c919024bbad7af3 --- java-spanner-jdbc/.kokoro/build.sh | 2 +- .../.kokoro/nightly/integration.cfg | 12 ++---- java-spanner-jdbc/.kokoro/nightly/samples.cfg | 16 +++---- java-spanner-jdbc/.kokoro/populate-secrets.sh | 43 +++++++++++++++++++ .../.kokoro/presubmit/integration.cfg | 12 ++---- .../.kokoro/presubmit/samples.cfg | 14 +++--- java-spanner-jdbc/.kokoro/trampoline.sh | 2 + java-spanner-jdbc/synth.metadata | 4 +- 8 files changed, 67 insertions(+), 38 deletions(-) create mode 100755 java-spanner-jdbc/.kokoro/populate-secrets.sh diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index d09a94e19cbe..efe91569c97d 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -39,7 +39,7 @@ retry_with_backoff 3 10 \ # if GOOGLE_APPLICATION_CREDIENTIALS is specified as a relative path prepend Kokoro root directory onto it if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTIALS}" != /* ]]; then - export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_ROOT}/src/${GOOGLE_APPLICATION_CREDENTIALS}) + export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_GFILE_DIR}/${GOOGLE_APPLICATION_CREDENTIALS}) fi RETURN_CODE=0 diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index 40c4abb7bf08..0048c8ece7e5 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -28,14 +28,10 @@ env_vars: { env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + value: "secret_manager/java-it-service-account" } -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "java_it_service_account" - } - } +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" } diff --git a/java-spanner-jdbc/.kokoro/nightly/samples.cfg b/java-spanner-jdbc/.kokoro/nightly/samples.cfg index 20aabd55de11..f25429314f4d 100644 --- a/java-spanner-jdbc/.kokoro/nightly/samples.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/samples.cfg @@ -24,19 +24,15 @@ env_vars: { env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + value: "secret_manager/java-docs-samples-service-account" } env_vars: { - key: "ENABLE_BUILD_COP" - value: "true" + key: "SECRET_MANAGER_KEYS" + value: "java-docs-samples-service-account" } -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "java_it_service_account" - } - } +env_vars: { + key: "ENABLE_BUILD_COP" + value: "true" } diff --git a/java-spanner-jdbc/.kokoro/populate-secrets.sh b/java-spanner-jdbc/.kokoro/populate-secrets.sh new file mode 100755 index 000000000000..f52514257ef0 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/populate-secrets.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright 2020 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. + +set -eo pipefail + +function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} +function msg { println "$*" >&2 ;} +function println { printf '%s\n' "$(now) $*" ;} + + +# Populates requested secrets set in SECRET_MANAGER_KEYS from service account: +# kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com +SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" +msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" +mkdir -p ${SECRET_LOCATION} +for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") +do + msg "Retrieving secret ${key}" + docker run --entrypoint=gcloud \ + --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \ + gcr.io/google.com/cloudsdktool/cloud-sdk \ + secrets versions access latest \ + --project cloud-devrel-kokoro-resources \ + --secret ${key} > \ + "${SECRET_LOCATION}/${key}" + if [[ $? == 0 ]]; then + msg "Secret written to ${SECRET_LOCATION}/${key}" + else + msg "Error retrieving secret ${key}" + fi +done diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg index 522e5b10101c..dded67a9d54a 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -24,14 +24,10 @@ env_vars: { env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + value: "secret_manager/java-it-service-account" } -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "java_it_service_account" - } - } +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" } diff --git a/java-spanner-jdbc/.kokoro/presubmit/samples.cfg b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg index 1171aead01f0..01e0960047b8 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/samples.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/samples.cfg @@ -24,14 +24,10 @@ env_vars: { env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" + value: "secret_manager/java-docs-samples-service-account" } -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "java_it_service_account" - } - } -} +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-docs-samples-service-account" +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/trampoline.sh b/java-spanner-jdbc/.kokoro/trampoline.sh index ba17ce01466b..9da0f8398773 100644 --- a/java-spanner-jdbc/.kokoro/trampoline.sh +++ b/java-spanner-jdbc/.kokoro/trampoline.sh @@ -21,4 +21,6 @@ function cleanup() { echo "cleanup"; } trap cleanup EXIT + +$(dirname $0)/populate-secrets.sh # Secret Manager secrets. python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 367337e65d13..bd8a5c37f5a1 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "bc476ac3505b1793f62d64026c2537ecbf227e2e" + "sha": "36612ee15b3a2c72018aed16848c399f4bcfc2a3" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "987270824bd26f6a8c716d5e2022057b8ae7b26e" + "sha": "c4f3059c27591eb24d6942a0e357ec94c80459f2" } } ] From fbc38024872a1e3230625068c8cdc6b986c892a1 Mon Sep 17 00:00:00 2001 From: yangnuoyu <46553752+yangnuoyu@users.noreply.github.com> Date: Mon, 22 Jun 2020 11:09:38 -0700 Subject: [PATCH 0171/1979] feat(deps): adopt flatten plugin and google-cloud-shared-dependencies (#162) --- java-spanner-jdbc/.gitignore | 4 +++- java-spanner-jdbc/pom.xml | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.gitignore b/java-spanner-jdbc/.gitignore index 48876580084e..dbde6a740b09 100644 --- a/java-spanner-jdbc/.gitignore +++ b/java-spanner-jdbc/.gitignore @@ -39,4 +39,6 @@ api_key # Python utilities *.pyc -artman-genfiles \ No newline at end of file +artman-genfiles + +.flattened-pom.xml diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 12a75f8e1285..71347db0c7d6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -76,6 +76,13 @@ pom import + + com.google.cloud + google-cloud-shared-dependencies + 0.8.1 + pom + import + @@ -106,10 +113,6 @@ - - com.google.api.grpc - proto-google-cloud-spanner-v1 - com.google.protobuf protobuf-java @@ -121,7 +124,6 @@ org.threeten threetenbp - ${threeten.version} io.grpc @@ -134,7 +136,6 @@ com.google.code.findbugs jsr305 - ${findbugs.version} com.google.http-client @@ -333,6 +334,11 @@ + + + org.codehaus.mojo + flatten-maven-plugin + @@ -453,7 +459,7 @@ https://developers.google.com/protocol-buffers/docs/reference/java/ https://googleapis.dev/java/google-auth-library/latest/ https://googleapis.dev/java/gax/latest/ - https://googleapis.github.io/api-common-java/${google.api-common.version}/apidocs/ + https://googleapis.github.io/api-common-java/ From 0a842b31014fd91bc861a239d37d53fd43b446f4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 22 Jun 2020 22:53:49 +0200 Subject: [PATCH 0172/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.2.0 (#164) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [org.codehaus.mojo:build-helper-maven-plugin](http://www.mojohaus.org/build-helper-maven-plugin/) ([source](https://togithub.com/mojohaus/build-helper-maven-plugin)) | minor | `3.1.0` -> `3.2.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ecdfc9e084db..7442890fdc34 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 + 3.2.0 add-snippets-source diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 299de5d84939..3e4fe5deeb94 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.1.0 + 3.2.0 add-snippets-source From 0520ecd5902d06d1ff8ca725768e7d1c3e372d4b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 22 Jun 2020 23:48:47 +0200 Subject: [PATCH 0173/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v7.0.1 (#165) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | patch | `7.0.0` -> `7.0.1` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 71347db0c7d6..4657029c63b6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -72,7 +72,7 @@ com.google.cloud libraries-bom - 7.0.0 + 7.0.1 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 50d4bc89ea49..71a4e6c25c84 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 7.0.0 + 7.0.1 pom import From bb97e7cdb382e401d221b7e3aba61158eeabcb50 Mon Sep 17 00:00:00 2001 From: David Supplee Date: Thu, 25 Jun 2020 12:21:06 -0700 Subject: [PATCH 0174/1979] chore: update client_documentation link (#166) --- java-spanner-jdbc/.repo-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index 83c6f64d76e5..d5b76f2fcd39 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -2,7 +2,7 @@ "name": "spanner-jdbc", "name_pretty": "Google Cloud Spanner JDBC", "product_documentation": "https://cloud.google.com/pubsub/docs/", - "client_documentation": "https://googleapis.dev/java/google-cloud-clients/latest/index.html?com/google/cloud/spanner/jdbc/v1", + "client_documentation": "https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html", "release_level": "ga", "language": "java", "repo": "googleapis/java-spanner-jdbc", From 9fe70fe9d326851e1ccb55d5babac28e947309e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 26 Jun 2020 01:47:52 +0200 Subject: [PATCH 0175/1979] deps: upgrade to latest bom and remove dependency exclusions (#168) * deps: upgrade to latest bom + Spanner * deps: spanner dependency first * deps: remove ignored deps * deps: libraries-bom-8 --- java-spanner-jdbc/pom.xml | 42 +-------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4657029c63b6..de92a1845f01 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -59,7 +59,6 @@ google-cloud-spanner-jdbc 4.13 - 1.53.0 3.0.2 1.4.4 1.0.1 @@ -72,7 +71,7 @@ com.google.cloud libraries-bom - 7.0.1 + 8.0.0 pom import @@ -101,17 +100,6 @@ com.google.cloud google-cloud-spanner - - - - io.grpc - grpc-api - - - com.google.cloud - google-cloud-core-grpc - - com.google.protobuf @@ -166,33 +154,8 @@ com.google.cloud google-cloud-spanner - ${spanner.test.version} test-jar test - - - - io.opencensus - opencensus-api - - - io.opencensus - opencensus-contrib-grpc-util - - - - - - io.opencensus - opencensus-api - 0.24.0 - test - - - io.opencensus - opencensus-contrib-grpc-util - 0.24.0 - test com.google.api.grpc @@ -352,9 +315,6 @@ com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 - - io.opencensus:opencensus-api - io.opencensus:opencensus-contrib-grpc-util From b8691dd6cd51eddf41b6feaa6c81a2fe12d43bbe Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 26 Jun 2020 07:24:25 +0200 Subject: [PATCH 0176/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v8 (#169) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `7.0.1` -> `8.0.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 71a4e6c25c84..34060582cc82 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 7.0.1 + 8.0.0 pom import From e2bf4d2dedd393d483e072bbca563d7a3b778b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 30 Jun 2020 04:30:24 +0200 Subject: [PATCH 0177/1979] fix: return empty catalog name (#174) * fix: return empty catalog name The JDBC connection would return the current database name as the current catalog name, but that catalog name would not be returned in the ResultSet returned by getCatalogs(). This discrepancy causes some tools to ignore or misinterpret the catalog and schema structure of a Cloud Spanner database. Specifically, it breaks the autocomplete feature of DBeaver. * tests: fix failing test case --- .../java/com/google/cloud/spanner/jdbc/JdbcConnection.java | 2 +- .../com/google/cloud/spanner/jdbc/JdbcConnectionTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 5aefd35b5ddb..4e2318092866 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -291,7 +291,7 @@ public void setCatalog(String catalog) throws SQLException { @Override public String getCatalog() throws SQLException { checkClosed(); - return getConnectionOptions().getDatabaseName(); + return ""; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index a80e8009fe3b..82e26d03a10f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -634,7 +634,9 @@ public void testCatalog() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); when(options.getDatabaseName()).thenReturn("test"); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getCatalog()).isEqualTo("test"); + // The connection should always return the empty string as the current catalog, as no other + // catalogs exist in the INFORMATION_SCHEMA. + assertThat(connection.getCatalog()).isEqualTo(""); // This should be allowed. connection.setCatalog(""); try { From ff36cf729f7f5167339b7bdbd3a0e36cb84dc67e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 1 Jul 2020 21:06:17 +0200 Subject: [PATCH 0178/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.2 (#175) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | patch | `0.8.1` -> `0.8.2` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.8.2`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​082-httpswwwgithubcomgoogleapisjava-shared-dependenciescomparev081v082-2020-07-01) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.8.1...v0.8.2)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index de92a1845f01..fe33341e1728 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.8.1 + 0.8.2 pom import From e20f9a787b81980a3a7988d0bfa3dc484f7713e8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 8 Jul 2020 12:48:25 -0700 Subject: [PATCH 0179/1979] ci(java): run dependency test on Java 8 and 11 (#173) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/351f1c1a-f71f-4cfc-968c-ac334fd05a73/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/4f2c9f752a94042472fc03c5bd9e06e89817d2bd --- java-spanner-jdbc/.github/workflows/ci.yaml | 5 ++++- java-spanner-jdbc/.kokoro/dependencies.sh | 4 +++- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 445b4bf82ffd..683022075665 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -36,11 +36,14 @@ jobs: JOB_TYPE: test dependencies: runs-on: ubuntu-latest + strategy: + matrix: + java: [8, 11] steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: 8 + java-version: ${{matrix.java}} - run: java -version - run: .kokoro/dependencies.sh linkage-monitor: diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index cf3bb4347e01..cee4f11e7547 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -41,8 +41,10 @@ echo "****************** DEPENDENCY LIST COMPLETENESS CHECK *******************" ## Run dependency list completeness check function completenessCheck() { # Output dep list with compile scope generated using the original pom + # Running mvn dependency:list on Java versions that support modules will also include the module of the dependency. + # This is stripped from the output as it is not present in the flattened pom. msg "Generating dependency list using original pom..." - mvn dependency:list -f pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | grep -v ':test$' >.org-list.txt + mvn dependency:list -f pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e s/\\s--\\smodule.*// | grep -v ':test$' >.org-list.txt # Output dep list generated using the flattened pom (test scope deps are ommitted) msg "Generating dependency list using flattened pom..." diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index bd8a5c37f5a1..980c749efc50 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "36612ee15b3a2c72018aed16848c399f4bcfc2a3" + "sha": "7c336d0ae1328440d38713f66ea9459ffbdc3101" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c4f3059c27591eb24d6942a0e357ec94c80459f2" + "sha": "4f2c9f752a94042472fc03c5bd9e06e89817d2bd" } } ] From 783ebe15f6ee9c3c40090b1bbe7f912da24806e7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2020 15:33:53 +1000 Subject: [PATCH 0180/1979] chore: release 1.16.0 (#141) * updated CHANGELOG.md [ci skip] * updated README.md [ci skip] * updated versions.txt [ci skip] * updated samples/pom.xml [ci skip] * updated samples/install-without-bom/pom.xml [ci skip] * updated samples/snapshot/pom.xml [ci skip] * updated samples/snippets/pom.xml [ci skip] * updated pom.xml Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 31 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e01abdd37857..d8bafd09ce76 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [1.16.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.15.0...v1.16.0) (2020-07-08) + + +### Features + +* publish shaded jar on maven central ([#83](https://www.github.com/googleapis/java-spanner-jdbc/issues/83)) ([2a7c53e](https://www.github.com/googleapis/java-spanner-jdbc/commit/2a7c53e5d503eefc42e7927e58430f8d24fe5b48)) +* **deps:** adopt flatten plugin and google-cloud-shared-dependencies ([#162](https://www.github.com/googleapis/java-spanner-jdbc/issues/162)) ([6715a8b](https://www.github.com/googleapis/java-spanner-jdbc/commit/6715a8b24066595036c6228df18cca084a4bb1ad)) + + +### Bug Fixes + +* add missing documentation for connection properties ([#155](https://www.github.com/googleapis/java-spanner-jdbc/issues/155)) ([9b53df4](https://www.github.com/googleapis/java-spanner-jdbc/commit/9b53df4ea33926d9fa0955a4445c2ea6790ac3dc)), closes [#152](https://www.github.com/googleapis/java-spanner-jdbc/issues/152) +* ResultSet#get(...) methods should auto convert values ([#143](https://www.github.com/googleapis/java-spanner-jdbc/issues/143)) ([bc7d5bd](https://www.github.com/googleapis/java-spanner-jdbc/commit/bc7d5bd6205b23c99d01d2895ffb5c48ba423ea3)) +* return empty catalog name ([#174](https://www.github.com/googleapis/java-spanner-jdbc/issues/174)) ([cedd167](https://www.github.com/googleapis/java-spanner-jdbc/commit/cedd167c5973fe50e0205ae641f6580ebd627884)) +* test allowed a too old staleness ([#131](https://www.github.com/googleapis/java-spanner-jdbc/issues/131)) ([8a5e443](https://www.github.com/googleapis/java-spanner-jdbc/commit/8a5e44321b6587e1f719f4189dfe2af3482e47cc)) + + +### Dependencies + +* update core dependencies ([#105](https://www.github.com/googleapis/java-spanner-jdbc/issues/105)) ([d7c7095](https://www.github.com/googleapis/java-spanner-jdbc/commit/d7c7095e0f22cd477f56419e8300d67d48eb8484)) +* update core dependencies to v1.29.0 ([#121](https://www.github.com/googleapis/java-spanner-jdbc/issues/121)) ([1324769](https://www.github.com/googleapis/java-spanner-jdbc/commit/13247691db249a6bdd56ac1f5b03837ebfb0624f)) +* update core dependencies to v1.93.4 ([#111](https://www.github.com/googleapis/java-spanner-jdbc/issues/111)) ([a44b498](https://www.github.com/googleapis/java-spanner-jdbc/commit/a44b498be79189aa3ae2f9a32c4105a41d81922b)) +* update core dependencies to v29 (major) ([#114](https://www.github.com/googleapis/java-spanner-jdbc/issues/114)) ([143e6b6](https://www.github.com/googleapis/java-spanner-jdbc/commit/143e6b645fd09b91e9b3d8d1db2e522a04103c1e)) +* update dependency com.google.api:api-common to v1.9.0 ([#100](https://www.github.com/googleapis/java-spanner-jdbc/issues/100)) ([dc0793c](https://www.github.com/googleapis/java-spanner-jdbc/commit/dc0793ce0ea3ec1faaebcf59989e0b0977deffcf)) +* update dependency com.google.api.grpc:proto-google-common-protos to v1.18.0 ([#128](https://www.github.com/googleapis/java-spanner-jdbc/issues/128)) ([3f00adb](https://www.github.com/googleapis/java-spanner-jdbc/commit/3f00adbe0d1d317dfefe5ec3ee5a0be9fe0f5923)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.2 ([#175](https://www.github.com/googleapis/java-spanner-jdbc/issues/175)) ([a553f79](https://www.github.com/googleapis/java-spanner-jdbc/commit/a553f7919314152583b6aae9a98a450d3c50a8fc)) +* update dependency com.google.cloud.samples:shared-configuration to v1.0.13 ([#99](https://www.github.com/googleapis/java-spanner-jdbc/issues/99)) ([63717c2](https://www.github.com/googleapis/java-spanner-jdbc/commit/63717c2fc9cc2b3a43a6b0412fefca7bbfd7e12d)) +* update dependency org.threeten:threetenbp to v1.4.3 ([#94](https://www.github.com/googleapis/java-spanner-jdbc/issues/94)) ([cb7229f](https://www.github.com/googleapis/java-spanner-jdbc/commit/cb7229fbbf3e1d71b8a4331eb5ab889af5d4fd31)) +* update dependency org.threeten:threetenbp to v1.4.4 ([#124](https://www.github.com/googleapis/java-spanner-jdbc/issues/124)) ([4d3daa4](https://www.github.com/googleapis/java-spanner-jdbc/commit/4d3daa484394f790e07557175aa7311b248da6f7)) +* upgrade to latest bom and remove dependency exclusions ([#168](https://www.github.com/googleapis/java-spanner-jdbc/issues/168)) ([291189c](https://www.github.com/googleapis/java-spanner-jdbc/commit/291189cec8e9d166fb8df9d26a6381be9cbded9d)) + ## [1.15.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.14.0...v1.15.0) (2020-03-24) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 4940cce2e6b1..b3b29ce206b5 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.15.0 + 1.16.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.15.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.16.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.15.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.16.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fe33341e1728..9fabc5b50891 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.15.1-SNAPSHOT + 1.16.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3e4fe5deeb94..2664f5e69e59 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.15.1-SNAPSHOT + 1.16.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a36a2be463d9..a2a9f82c642e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.15.0:1.15.1-SNAPSHOT +google-cloud-spanner-jdbc:1.16.0:1.16.0 From 9f33f1fa23fcbb26fb5483c849fd31c1db8f791f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 9 Jul 2020 08:08:04 +0200 Subject: [PATCH 0181/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.9.2 (#170) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | minor | `0.8.1` -> `0.9.2` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.9.2`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​092-httpswwwgithubcomgoogleapisjava-shared-configcomparev091v092-2020-07-02) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.9.1...v0.9.2) ### [`v0.9.1`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​091-httpswwwgithubcomgoogleapisjava-shared-configcomparev090v091-2020-07-01) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.9.0...v0.9.1) ### [`v0.9.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​090-httpswwwgithubcomgoogleapisjava-shared-configcomparev081v090-2020-06-25) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.8.1...v0.9.0) ##### Features - add ignore rule for javax annotations to handle error in java11 ([#​171](https://www.github.com/googleapis/java-shared-config/issues/171)) ([cd635ad](https://www.github.com/googleapis/java-shared-config/commit/cd635ad6e8e5d71ac3a30e7656eb788027f1c370)) ##### [0.8.1](https://www.github.com/googleapis/java-shared-config/compare/v0.8.0...v0.8.1) (2020-06-15) ##### Bug Fixes - bump flatten plugin version to fix missing version in profile section issue ([#​159](https://www.github.com/googleapis/java-shared-config/issues/159)) ([5b34939](https://www.github.com/googleapis/java-shared-config/commit/5b349399a590b589718b7049f66c82ee38742372))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9fabc5b50891..5b33eb0139ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.8.1 + 0.9.2 From fa933d77df22ced59aa9e053bc1dd878274d25ef Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 10 Jul 2020 06:34:30 +0200 Subject: [PATCH 0182/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.3 (#180) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5b33eb0139ef..a8d38002c84b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.8.2 + 0.8.3 pom import From bab9dd705d266a051ebb6992fd54f499f6453440 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 10 Jul 2020 06:34:56 +0200 Subject: [PATCH 0183/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.16.0 (#177) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7442890fdc34..4d31f843dd6d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.15.0 + 1.16.0 From 201e84f8d5572f40122e8c1f82c366b4c13c8f06 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2020 04:54:07 +0000 Subject: [PATCH 0184/1979] chore: release 1.16.1-SNAPSHOT (#178) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a8d38002c84b..fd169f086cd5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.16.0 + 1.16.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2664f5e69e59..3571e453471f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.16.0 + 1.16.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a2a9f82c642e..1aedcc871151 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.16.0:1.16.0 +google-cloud-spanner-jdbc:1.16.0:1.16.1-SNAPSHOT From 2efbce8f9d435586fd2c8d5f293bfd6a1b4b7dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 16 Jul 2020 01:18:28 +0200 Subject: [PATCH 0185/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v8.1.0 (#184) --- java-spanner-jdbc/pom.xml | 2 +- .../java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd169f086cd5..5a2c9c07df34 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 8.0.0 + 8.1.0 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 1f886750c8c5..60911a86a771 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -214,7 +214,8 @@ public void autocommitExecuteSql() { @Test public void autocommitPDMLExecuteSql() { - mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setExecuteStreamingSqlExecutionTime( + SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); From 597d95dbd154514e61059dafd3d9fa9b0e836efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 16 Jul 2020 15:05:45 +0200 Subject: [PATCH 0186/1979] tests: run integration tests against emulator (#172) * tests: run integration tests against emulator * test: run integration tests against emulator * chore: update name of workflow * test: skip test when there are no credentials * test: change to docker based emulator tests --- .../integration-tests-against-emulator.yaml | 29 +++++++++++++ .../spanner/jdbc/ITAbstractJdbcTest.java | 18 +++++++- .../spanner/jdbc/it/ITJdbcConnectTest.java | 42 ++++++++++++------- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 7 ++++ .../jdbc/it/ITJdbcPreparedStatementTest.java | 7 ++++ .../jdbc/it/ITJdbcQueryOptionsTest.java | 7 ++++ .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 7 ++++ .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 13 ++++++ 8 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml new file mode 100644 index 000000000000..60647235c60c --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -0,0 +1,29 @@ +on: + push: + branches: + - master + pull_request: +name: Integration tests against emulator +jobs: + units: + runs-on: ubuntu-latest + + services: + emulator: + image: gcr.io/cloud-spanner-emulator/emulator:latest + ports: + - 9010:9010 + - 9020:9020 + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - run: java -version + - run: .kokoro/build.sh + - run: mvn -B -Dspanner.testenv.instance="" -Penable-integration-tests -DtrimStackTrace=false -Dclirr.skip=true -Denforcer.skip=true -fae verify + env: + JOB_TYPE: test + SPANNER_EMULATOR_HOST: localhost:9010 + GOOGLE_CLOUD_PROJECT: emulator-test-project diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index 2d173977787e..6361ce4af52b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -21,6 +21,7 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ITAbstractSpannerTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; import com.google.common.base.Preconditions; @@ -34,6 +35,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.ExecutionException; +import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; @@ -57,7 +59,16 @@ public JdbcGenericConnection getConnection() { } } - @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + @ClassRule + public static IntegrationTestEnv env = + new IntegrationTestEnv() { + @Override + protected void after() { + super.after(); + ConnectionOptions.closeSpanner(); + } + }; + private static final String DEFAULT_KEY_FILE = null; private static Database database; @@ -82,6 +93,11 @@ public static void setup() throws IOException, InterruptedException, ExecutionEx database = env.getTestHelper().createTestDatabase(); } + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); + } + /** * Creates a new default JDBC connection to a test database. Use the method {@link * ITAbstractJdbcTest#appendConnectionUri(StringBuilder)} to append additional connection options diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 580bfff989ac..88f577ec9ae4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcDataSource; import java.io.FileInputStream; +import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -53,8 +54,14 @@ public class ITJdbcConnectTest extends ITAbstractJdbcTest { private String createBaseUrl() { - StringBuilder url = - new StringBuilder("jdbc:cloudspanner:/").append(getDatabase().getId().getName()); + StringBuilder url = new StringBuilder("jdbc:cloudspanner:"); + if (env.getTestHelper().isEmulator()) { + url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST")); + } + url.append("/").append(getDatabase().getId().getName()); + if (env.getTestHelper().isEmulator()) { + url.append(";usePlainText=true"); + } return url.toString(); } @@ -99,7 +106,7 @@ public void testConnectWithURLWithDefaultValues() throws SQLException { @Test public void testConnectWithURLWithNonDefaultValues() throws SQLException { String url = createBaseUrl(); - url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false"; if (hasValidKeyFile()) { url = url + ";credentials=" + getKeyFile(); } @@ -138,7 +145,7 @@ public void testConnectWithPropertiesWithNonDefaultValues() throws SQLException @Test public void testConnectWithPropertiesWithConflictingValues() throws SQLException { String url = createBaseUrl(); - url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false"; if (hasValidKeyFile()) { url = url + ";credentials=" + getKeyFile(); } @@ -167,7 +174,7 @@ public void testConnectWithDataSourceWithDefaultValues() throws SQLException { public void testConnectWithDataSourceWithNonDefaultValues() throws SQLException { JdbcDataSource ds = new JdbcDataSource(); ds.setUrl(createBaseUrl()); - if (hasValidKeyFile()) { + if (hasValidKeyFile() && !env.getTestHelper().isEmulator()) { ds.setCredentials(getKeyFile()); } ds.setAutocommit(false); @@ -183,7 +190,7 @@ public void testConnectWithDataSourceWithConflictingValues() throws SQLException // Try with non-default values in URL and default values in data source. The values in the URL // should take precedent. String url = createBaseUrl(); - url = url + "?autocommit=false;readonly=true;retryAbortsInternally=false"; + url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false"; if (hasValidKeyFile()) { url = url + ";credentials=" + getKeyFile(); } @@ -203,14 +210,21 @@ public void testConnectWithOAuthToken() throws Exception { if (hasValidKeyFile()) { credentials = GoogleCredentials.fromStream(new FileInputStream(getKeyFile())); } else { - credentials = GoogleCredentials.getApplicationDefault(); - } - credentials = credentials.createScoped(SpannerOptions.getDefaultInstance().getScopes()); - AccessToken token = credentials.refreshAccessToken(); - String urlWithOAuth = createBaseUrl() + "?OAuthToken=" + token.getTokenValue(); - try (Connection connectionWithOAuth = DriverManager.getConnection(urlWithOAuth)) { - // Try to do a query using the connection created with an OAuth token. - testDefaultConnection(connectionWithOAuth); + try { + credentials = GoogleCredentials.getApplicationDefault(); + } catch (IOException e) { + credentials = null; + } + } + // Skip this test if there are no credentials set for the test case or environment. + if (credentials != null) { + credentials = credentials.createScoped(SpannerOptions.getDefaultInstance().getScopes()); + AccessToken token = credentials.refreshAccessToken(); + String urlWithOAuth = createBaseUrl() + ";OAuthToken=" + token.getTokenValue(); + try (Connection connectionWithOAuth = DriverManager.getConnection(urlWithOAuth)) { + // Try to do a query using the connection created with an OAuth token. + testDefaultConnection(connectionWithOAuth); + } } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 27d7a12f733d..9cf57b3f8e10 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -21,6 +21,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -31,6 +32,7 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -49,6 +51,11 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; private static final String TABLE_WITH_REF = "TableWithRef"; + @BeforeClass + public static void skipOnEmulator() { + assumeFalse("foreign keys are not supported on the emulator", env.getTestHelper().isEmulator()); + } + @Override protected boolean doCreateMusicTables() { return true; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 174e76c2b195..60ddb3c2c370 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -22,6 +22,7 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; import com.google.api.client.util.Base64; import com.google.cloud.spanner.IntegrationTest; @@ -45,6 +46,7 @@ import java.util.List; import java.util.Scanner; import java.util.TimeZone; +import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -254,6 +256,11 @@ private List createConcerts() { return res; } + @BeforeClass + public static void notOnEmulator() { + assumeFalse("foreign keys are not supported on the emulator", env.getTestHelper().isEmulator()); + } + @Override protected boolean doCreateMusicTables() { return true; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 0516a1448bf0..7ca650dfc173 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.SpannerOptions; @@ -95,6 +96,7 @@ public void connectionUrl() throws SQLException { @Test public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { + assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); this.connectionUriSuffix = ";optimizerVersion=9999999"; try (Connection connection = createConnection()) { try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { @@ -137,6 +139,7 @@ public void setLatestOptimizerVersion() throws SQLException { @Test public void setInvalidOptimizerVersion() throws SQLException { + assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); try (Connection connection = createConnection()) { connection.createStatement().execute("SET OPTIMIZER_VERSION='9999999'"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { @@ -151,6 +154,9 @@ public void setInvalidOptimizerVersion() throws SQLException { @Test public void optimizerVersionInQueryHint() throws SQLException { + assumeFalse( + "optimizer version in query hint is not supported on emulator", + env.getTestHelper().isEmulator()); try (Connection connection = createConnection()) { verifyOptimizerVersion(connection, ""); try (ResultSet rs = @@ -170,6 +176,7 @@ public void optimizerVersionInQueryHint() throws SQLException { @Test public void optimizerVersionInEnvironment() throws SQLException { + assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); try { SpannerOptions.useEnvironment( new SpannerOptions.SpannerEnvironment() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index db5c84246d68..98700d5ed26d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -18,6 +18,7 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -28,6 +29,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -82,6 +84,11 @@ public void createTestTables() throws Exception { } } + @After + public void closeSpanner() { + ConnectionOptions.closeSpanner(); + } + @Test public void testSqlScript() throws Exception { // Wait 100ms to ensure that staleness tests in the script succeed. diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index 07a1ab8f9559..8fc331bb5300 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -21,6 +21,7 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -28,6 +29,7 @@ import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; import java.sql.Connection; import java.sql.ResultSet; +import java.sql.SQLException; import java.sql.Statement; import org.junit.FixMethodOrder; import org.junit.Test; @@ -85,6 +87,12 @@ public void test02_InsertTestData() throws Exception { JdbcGenericConnection.of(connection), INSERT_AND_VERIFY_TEST_DATA, SqlScriptVerifier.class); + } catch (SQLException e) { + if (env.getTestHelper().isEmulator() + && e.getErrorCode() == ErrorCode.ALREADY_EXISTS.getGrpcStatusCode().value()) { + // Ignore, this is expected as errors during a read/write transaction are sticky on the + // emulator. + } } } @@ -101,6 +109,11 @@ public void test04_TestGetCommitTimestamp() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), TEST_GET_COMMIT_TIMESTAMP, SqlScriptVerifier.class); + } catch (SQLException e) { + if (env.getTestHelper().isEmulator() + && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()) { + // Ignore as errors during read/write transactions are sticky on the emulator. + } } } From 05ce4cb9eca6b11f3fcc9c7e93329638e48e15d2 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 5 Aug 2020 22:52:10 -0700 Subject: [PATCH 0187/1979] Add cloud-RAD for Java (#186) Co-authored-by: Jeff Ching Source-Author: Les Vogel Source-Date: Thu Jul 30 13:09:50 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: dd230c816f88d0141fcd0be83498986287220d1b Source-Link: https://github.com/googleapis/synthtool/commit/dd230c816f88d0141fcd0be83498986287220d1b --- .../.kokoro/release/publish_javadoc.cfg | 10 +++ .../.kokoro/release/publish_javadoc.sh | 25 +++++- java-spanner-jdbc/synth.metadata | 80 ++++++++++++++++++- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index fc95786fa749..b50b09ee9e35 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -1,14 +1,24 @@ # Format: //devtools/kokoro/config/proto/build.proto + +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/doc-templates/" + env_vars: { key: "STAGING_BUCKET" value: "docs-staging" } +env_vars: { + key: "STAGING_BUCKET_V2" + value: "docs-staging-v2-staging" + # Production will be at: docs-staging-v2 +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh" } + before_action { fetch_keystore { keystore_resource { diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 99de3944bc1c..d558f50925ff 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -24,6 +24,11 @@ if [[ -z "${STAGING_BUCKET}" ]]; then exit 1 fi +if [[ -z "${STAGING_BUCKET_V2}" ]]; then + echo "Need to set STAGING_BUCKET_V2 environment variable" + exit 1 +fi + # work from the git root directory pushd $(dirname "$0")/../../ @@ -31,13 +36,13 @@ pushd $(dirname "$0")/../../ python3 -m pip install gcp-docuploader # compile all packages -mvn clean install -B -DskipTests=true +mvn clean install -B -q -DskipTests=true NAME=google-cloud-spanner-jdbc VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) # build the docs -mvn site -B +mvn site -B -q pushd target/site/apidocs @@ -53,3 +58,19 @@ python3 -m docuploader upload . \ --staging-bucket ${STAGING_BUCKET} popd + +# V2 +mvn clean site -B -q -Ddevsite.template="${KOKORO_GFILE_DIR}/java/" + +pushd target/devsite + +# create metadata +python3 -m docuploader create-metadata \ + --name ${NAME} \ + --version ${VERSION} \ + --language java + +# upload docs +python3 -m docuploader upload . \ + --credentials ${CREDENTIALS} \ + --staging-bucket ${STAGING_BUCKET_V2} diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 980c749efc50..2254850e97e9 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,15 +4,91 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "7c336d0ae1328440d38713f66ea9459ffbdc3101" + "sha": "70f7c13b23571d167bcc6ff6671b9274b2131351" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4f2c9f752a94042472fc03c5bd9e06e89817d2bd" + "sha": "dd230c816f88d0141fcd0be83498986287220d1b" } } + ], + "generatedFiles": [ + ".github/CODEOWNERS", + ".github/ISSUE_TEMPLATE/bug_report.md", + ".github/ISSUE_TEMPLATE/feature_request.md", + ".github/ISSUE_TEMPLATE/support_request.md", + ".github/PULL_REQUEST_TEMPLATE.md", + ".github/release-please.yml", + ".github/trusted-contribution.yml", + ".github/workflows/ci.yaml", + ".kokoro/build.bat", + ".kokoro/build.sh", + ".kokoro/coerce_logs.sh", + ".kokoro/common.cfg", + ".kokoro/common.sh", + ".kokoro/continuous/common.cfg", + ".kokoro/continuous/dependencies.cfg", + ".kokoro/continuous/integration.cfg", + ".kokoro/continuous/java11.cfg", + ".kokoro/continuous/java7.cfg", + ".kokoro/continuous/java8-osx.cfg", + ".kokoro/continuous/java8-win.cfg", + ".kokoro/continuous/java8.cfg", + ".kokoro/continuous/lint.cfg", + ".kokoro/continuous/propose_release.cfg", + ".kokoro/continuous/samples.cfg", + ".kokoro/dependencies.sh", + ".kokoro/linkage-monitor.sh", + ".kokoro/nightly/common.cfg", + ".kokoro/nightly/dependencies.cfg", + ".kokoro/nightly/integration.cfg", + ".kokoro/nightly/java11.cfg", + ".kokoro/nightly/java7.cfg", + ".kokoro/nightly/java8-osx.cfg", + ".kokoro/nightly/java8-win.cfg", + ".kokoro/nightly/java8.cfg", + ".kokoro/nightly/lint.cfg", + ".kokoro/nightly/samples.cfg", + ".kokoro/populate-secrets.sh", + ".kokoro/presubmit/clirr.cfg", + ".kokoro/presubmit/common.cfg", + ".kokoro/presubmit/dependencies.cfg", + ".kokoro/presubmit/integration.cfg", + ".kokoro/presubmit/java11.cfg", + ".kokoro/presubmit/java7.cfg", + ".kokoro/presubmit/java8-osx.cfg", + ".kokoro/presubmit/java8-win.cfg", + ".kokoro/presubmit/java8.cfg", + ".kokoro/presubmit/linkage-monitor.cfg", + ".kokoro/presubmit/lint.cfg", + ".kokoro/presubmit/samples.cfg", + ".kokoro/release/bump_snapshot.cfg", + ".kokoro/release/common.cfg", + ".kokoro/release/common.sh", + ".kokoro/release/drop.cfg", + ".kokoro/release/drop.sh", + ".kokoro/release/promote.cfg", + ".kokoro/release/promote.sh", + ".kokoro/release/publish_javadoc.cfg", + ".kokoro/release/publish_javadoc.sh", + ".kokoro/release/snapshot.cfg", + ".kokoro/release/snapshot.sh", + ".kokoro/release/stage.cfg", + ".kokoro/release/stage.sh", + ".kokoro/trampoline.sh", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE", + "codecov.yaml", + "java.header", + "license-checks.xml", + "renovate.json", + "samples/install-without-bom/pom.xml", + "samples/pom.xml", + "samples/snapshot/pom.xml", + "samples/snippets/pom.xml" ] } \ No newline at end of file From 805dd1cddbc77950686538ffb9bd65bde9e0f9a4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 6 Aug 2020 07:52:31 +0200 Subject: [PATCH 0188/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.4 (#187) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a2c9c07df34..144a51982465 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.8.3 + 0.8.4 pom import From d9adf58736001440cf28791d9830115cadcc692d Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 7 Aug 2020 08:42:21 -0700 Subject: [PATCH 0189/1979] cleanup: removes unused kokoro config files (#188) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/5b7e2ed3-d953-49da-9f19-3f7f3762d72e/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/4530cc6ff080ef8aca258c1ec92c4db10a1bbfb4 --- .../.kokoro/continuous/dependencies.cfg | 12 ----- .../.kokoro/continuous/integration.cfg | 7 --- .../.kokoro/continuous/java11.cfg | 7 --- .../.kokoro/continuous/java7.cfg | 7 --- .../.kokoro/continuous/java8-osx.cfg | 3 -- .../.kokoro/continuous/java8-win.cfg | 3 -- java-spanner-jdbc/.kokoro/continuous/lint.cfg | 13 ----- .../.kokoro/continuous/propose_release.cfg | 53 ------------------- .../.kokoro/continuous/samples.cfg | 31 ----------- .../.kokoro/nightly/dependencies.cfg | 12 ----- java-spanner-jdbc/.kokoro/nightly/lint.cfg | 13 ----- java-spanner-jdbc/synth.metadata | 15 +----- 12 files changed, 2 insertions(+), 174 deletions(-) delete mode 100644 java-spanner-jdbc/.kokoro/continuous/dependencies.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/integration.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/java11.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/java7.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/java8-win.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/lint.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/propose_release.cfg delete mode 100644 java-spanner-jdbc/.kokoro/continuous/samples.cfg delete mode 100644 java-spanner-jdbc/.kokoro/nightly/dependencies.cfg delete mode 100644 java-spanner-jdbc/.kokoro/nightly/lint.cfg diff --git a/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg b/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg deleted file mode 100644 index 2d09bcc0ac01..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/dependencies.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/dependencies.sh" -} diff --git a/java-spanner-jdbc/.kokoro/continuous/integration.cfg b/java-spanner-jdbc/.kokoro/continuous/integration.cfg deleted file mode 100644 index 3b017fc80f04..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/integration.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} diff --git a/java-spanner-jdbc/.kokoro/continuous/java11.cfg b/java-spanner-jdbc/.kokoro/continuous/java11.cfg deleted file mode 100644 index 709f2b4c73db..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/java11.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java11" -} diff --git a/java-spanner-jdbc/.kokoro/continuous/java7.cfg b/java-spanner-jdbc/.kokoro/continuous/java7.cfg deleted file mode 100644 index cb24f44eea3b..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/java7.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java7" -} diff --git a/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg b/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg deleted file mode 100644 index c6980278d0ce..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/java8-osx.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -build_file: "java-spanner-jdbc/.kokoro/build.sh" diff --git a/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg b/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg deleted file mode 100644 index 90e4b928aa49..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/java8-win.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -build_file: "java-spanner-jdbc/.kokoro/build.bat" diff --git a/java-spanner-jdbc/.kokoro/continuous/lint.cfg b/java-spanner-jdbc/.kokoro/continuous/lint.cfg deleted file mode 100644 index 6d323c8ae768..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/lint.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. - -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -env_vars: { - key: "JOB_TYPE" - value: "lint" -} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg b/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg deleted file mode 100644 index 1b7a1affa1cb..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/propose_release.cfg +++ /dev/null @@ -1,53 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/continuous/propose_release.sh" -} - -# tokens used by release-please to keep an up-to-date release PR. -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-key-release-please" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-token-release-please" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-url-release-please" - } - } -} diff --git a/java-spanner-jdbc/.kokoro/continuous/samples.cfg b/java-spanner-jdbc/.kokoro/continuous/samples.cfg deleted file mode 100644 index fa7b493d0b5c..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/samples.cfg +++ /dev/null @@ -1,31 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -env_vars: { - key: "JOB_TYPE" - value: "samples" -} - -env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" -} - -env_vars: { - key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "keystore/73713_java_it_service_account" -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "java_it_service_account" - } - } -} diff --git a/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg b/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg deleted file mode 100644 index 2d09bcc0ac01..000000000000 --- a/java-spanner-jdbc/.kokoro/nightly/dependencies.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/dependencies.sh" -} diff --git a/java-spanner-jdbc/.kokoro/nightly/lint.cfg b/java-spanner-jdbc/.kokoro/nightly/lint.cfg deleted file mode 100644 index 6d323c8ae768..000000000000 --- a/java-spanner-jdbc/.kokoro/nightly/lint.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. - -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -env_vars: { - key: "JOB_TYPE" - value: "lint" -} \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 2254850e97e9..44af60626c42 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "70f7c13b23571d167bcc6ff6671b9274b2131351" + "sha": "ddb96f2424c11d0cde3a4b702a1e3599c0489e96" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "dd230c816f88d0141fcd0be83498986287220d1b" + "sha": "4530cc6ff080ef8aca258c1ec92c4db10a1bbfb4" } } ], @@ -30,27 +30,16 @@ ".kokoro/common.cfg", ".kokoro/common.sh", ".kokoro/continuous/common.cfg", - ".kokoro/continuous/dependencies.cfg", - ".kokoro/continuous/integration.cfg", - ".kokoro/continuous/java11.cfg", - ".kokoro/continuous/java7.cfg", - ".kokoro/continuous/java8-osx.cfg", - ".kokoro/continuous/java8-win.cfg", ".kokoro/continuous/java8.cfg", - ".kokoro/continuous/lint.cfg", - ".kokoro/continuous/propose_release.cfg", - ".kokoro/continuous/samples.cfg", ".kokoro/dependencies.sh", ".kokoro/linkage-monitor.sh", ".kokoro/nightly/common.cfg", - ".kokoro/nightly/dependencies.cfg", ".kokoro/nightly/integration.cfg", ".kokoro/nightly/java11.cfg", ".kokoro/nightly/java7.cfg", ".kokoro/nightly/java8-osx.cfg", ".kokoro/nightly/java8-win.cfg", ".kokoro/nightly/java8.cfg", - ".kokoro/nightly/lint.cfg", ".kokoro/nightly/samples.cfg", ".kokoro/populate-secrets.sh", ".kokoro/presubmit/clirr.cfg", From 71dc5c70214597800a52b777cf5377f8a46a4746 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 Aug 2020 23:34:03 +0200 Subject: [PATCH 0190/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.6 (#189) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | patch | `0.8.4` -> `0.8.6` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.8.6`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​086-httpswwwgithubcomgoogleapisjava-shared-dependenciescomparev085v086-2020-08-07) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.8.5...v0.8.6) ### [`v0.8.5`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​085-httpswwwgithubcomgoogleapisjava-shared-dependenciescomparev084v085-2020-08-07) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.8.4...v0.8.5)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 144a51982465..3171a6c282f5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.8.4 + 0.8.6 pom import From dfbdc80436da6becd35c074460fa9e3e362f05eb Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 10 Aug 2020 15:58:07 -0700 Subject: [PATCH 0191/1979] build: update dependencies check to only check for runtime and compile scopes (#190) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/4f159194-de9c-4c80-934e-eb32cd08c411/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/f8823dec98277a9516f2fb6fae9f58b3a59a23e1 --- java-spanner-jdbc/.kokoro/dependencies.sh | 9 +++++---- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index cee4f11e7547..c91e5a56937a 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -43,12 +43,13 @@ function completenessCheck() { # Output dep list with compile scope generated using the original pom # Running mvn dependency:list on Java versions that support modules will also include the module of the dependency. # This is stripped from the output as it is not present in the flattened pom. + # Only dependencies with 'compile' or 'runtime' scope are included from original dependency list. msg "Generating dependency list using original pom..." - mvn dependency:list -f pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e s/\\s--\\smodule.*// | grep -v ':test$' >.org-list.txt + mvn dependency:list -f pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e s/\\s--\\smodule.*// >.org-list.txt - # Output dep list generated using the flattened pom (test scope deps are ommitted) + # Output dep list generated using the flattened pom (only 'compile' and 'runtime' scopes) msg "Generating dependency list using flattened pom..." - mvn dependency:list -f .flattened-pom.xml -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' >.new-list.txt + mvn dependency:list -f .flattened-pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' >.new-list.txt # Compare two dependency lists msg "Comparing dependency lists..." @@ -85,4 +86,4 @@ then else msg "Errors found. See log statements above." exit 1 -fi +fi \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 44af60626c42..9d84bd12d278 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ddb96f2424c11d0cde3a4b702a1e3599c0489e96" + "sha": "2259332c7657cd160aef889f88649713dd2fe61e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4530cc6ff080ef8aca258c1ec92c4db10a1bbfb4" + "sha": "f8823dec98277a9516f2fb6fae9f58b3a59a23e1" } } ], From bcb78ec47e60be14c8d75d1064f18a1658d9f90f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 14 Aug 2020 04:26:40 +0200 Subject: [PATCH 0192/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v9 (#191) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `8.1.0` -> `9.0.0` | | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `8.0.0` -> `9.0.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3171a6c282f5..9efc30082e1b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 8.1.0 + 9.0.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 34060582cc82..b49cc4719b57 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 8.0.0 + 9.0.0 pom import From 1290f42c37bcc88c0f1341645896bb0c10f5bdc7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 Aug 2020 00:04:13 +0200 Subject: [PATCH 0193/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v9.1.0 --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9efc30082e1b..27f615ff07ea 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 9.0.0 + 9.1.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index b49cc4719b57..cf90669f5dd7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 9.0.0 + 9.1.0 pom import From 91b14818ff2ab38abe17f2bb6a491fd917e14d17 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 20 Aug 2020 15:38:04 -0700 Subject: [PATCH 0194/1979] samples: add presubmit lint check (#194) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/04a3c534-5129-4a05-922f-148232720a95/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/9602086c6c5b05db77950c7f7495a2a3868f3537 Source-Link: https://github.com/googleapis/synthtool/commit/c3caf0704f25a0c365f1c315e804a30b87c62a75 --- java-spanner-jdbc/.github/workflows/samples.yaml | 14 ++++++++++++++ java-spanner-jdbc/synth.metadata | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/samples.yaml diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml new file mode 100644 index 000000000000..a1d50073069d --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -0,0 +1,14 @@ +on: + pull_request: +name: samples +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 8 + - name: Run checkstyle + run: mvn -P lint --quiet --batch-mode checkstyle:check + working-directory: samples/snippets diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 9d84bd12d278..59f6dd9ed326 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "2259332c7657cd160aef889f88649713dd2fe61e" + "sha": "e6f9be1221abf580e1203339a46fe4ca5b0a65b7" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "f8823dec98277a9516f2fb6fae9f58b3a59a23e1" + "sha": "9602086c6c5b05db77950c7f7495a2a3868f3537" } } ], @@ -24,6 +24,7 @@ ".github/release-please.yml", ".github/trusted-contribution.yml", ".github/workflows/ci.yaml", + ".github/workflows/samples.yaml", ".kokoro/build.bat", ".kokoro/build.sh", ".kokoro/coerce_logs.sh", From 751ff439a5f0c0399d0915613d08001dfbc8c42f Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 26 Aug 2020 09:31:41 -0700 Subject: [PATCH 0195/1979] build: temporarily disable reporting to unblock releases Source-Author: Stephanie Wang Source-Date: Tue Aug 25 13:05:26 2020 -0400 Source-Repo: googleapis/synthtool Source-Sha: 968465a1cad496e1292ef4584a054a35f756ff94 Source-Link: https://github.com/googleapis/synthtool/commit/968465a1cad496e1292ef4584a054a35f756ff94 --- java-spanner-jdbc/.kokoro/release/stage.sh | 5 +++-- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 3c482cbc55f1..d19191fc896c 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -16,8 +16,9 @@ set -eo pipefail # Start the releasetool reporter -python3 -m pip install gcp-releasetool -python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script +# Disable reporting due to issue observed with Kokoro blocking releases +# python3 -m pip install gcp-releasetool +# python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script source $(dirname "$0")/common.sh MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 59f6dd9ed326..8ad3605ced83 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "e6f9be1221abf580e1203339a46fe4ca5b0a65b7" + "sha": "41a179972deb84035ccd17cccc31f746dbc620db" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "9602086c6c5b05db77950c7f7495a2a3868f3537" + "sha": "968465a1cad496e1292ef4584a054a35f756ff94" } } ], From c3f54c6c92ca7f7ff01d420c9915c5584e7546b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 4 Sep 2020 15:10:29 +0200 Subject: [PATCH 0196/1979] feat: add support for NUMERIC type (#185) * feat: add support for NUMERIC type * deps: no snapshot * fix: add accidentally removed test script * fix: remove spanner version --- .../jdbc/AbstractJdbcPreparedStatement.java | 2 +- .../spanner/jdbc/AbstractJdbcWrapper.java | 58 ++++++++++++ .../cloud/spanner/jdbc/JdbcDataType.java | 27 ++++++ .../spanner/jdbc/JdbcDatabaseMetaData.java | 38 ++++++++ .../spanner/jdbc/JdbcParameterMetaData.java | 2 +- .../spanner/jdbc/JdbcParameterStore.java | 34 +++---- .../cloud/spanner/jdbc/JdbcResultSet.java | 26 ++++++ .../spanner/jdbc/JdbcResultSetMetaData.java | 8 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 19 ++++ .../jdbc/DatabaseMetaData_GetColumns.sql | 3 + .../cloud/spanner/jdbc/JdbcArrayTest.java | 8 ++ .../jdbc/JdbcDatabaseMetaDataTest.java | 2 + .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 18 ++-- .../spanner/jdbc/JdbcParameterStoreTest.java | 41 ++++++--- .../jdbc/JdbcPreparedStatementTest.java | 10 --- .../spanner/jdbc/JdbcTypeConverterTest.java | 40 ++++++++- .../jdbc/SpannerJdbcExceptionMatcher.java | 2 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 4 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 89 +++++++++++++++++++ .../spanner/jdbc/it/CreateMusicTables.sql | 4 +- 20 files changed, 381 insertions(+), 54 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 52ac32c9cfcd..bbd5975bd7b8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -128,7 +128,7 @@ public void setDouble(int parameterIndex, double value) throws SQLException { @Override public void setBigDecimal(int parameterIndex, BigDecimal value) throws SQLException { checkClosed(); - parameters.setParameter(parameterIndex, value, Types.DECIMAL); + parameters.setParameter(parameterIndex, value, Types.NUMERIC); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index aef5638e1f28..655566870d1a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -19,6 +19,8 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.math.BigInteger; import java.sql.Date; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; @@ -44,6 +46,7 @@ static int extractColumnType(Type type) { if (type.equals(Type.date())) return Types.DATE; if (type.equals(Type.float64())) return Types.DOUBLE; if (type.equals(Type.int64())) return Types.BIGINT; + if (type.equals(Type.numeric())) return Types.NUMERIC; if (type.equals(Type.string())) return Types.NVARCHAR; if (type.equals(Type.timestamp())) return Types.TIMESTAMP; if (type.getCode() == Code.ARRAY) return Types.ARRAY; @@ -60,6 +63,8 @@ static String getSpannerTypeName(int sqlType) { || sqlType == Types.INTEGER || sqlType == Types.SMALLINT || sqlType == Types.TINYINT) return Type.int64().getCode().name(); + if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL) + return Type.numeric().getCode().name(); if (sqlType == Types.NVARCHAR) return Type.string().getCode().name(); if (sqlType == Types.TIMESTAMP) return Type.timestamp().getCode().name(); if (sqlType == Types.ARRAY) return Code.ARRAY.name(); @@ -77,6 +82,7 @@ static String getClassName(int sqlType) { || sqlType == Types.INTEGER || sqlType == Types.SMALLINT || sqlType == Types.TINYINT) return Long.class.getName(); + if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL) return BigDecimal.class.getName(); if (sqlType == Types.NVARCHAR) return String.class.getName(); if (sqlType == Types.TIMESTAMP) return Timestamp.class.getName(); if (sqlType == Types.ARRAY) return Object.class.getName(); @@ -96,6 +102,7 @@ static String getClassName(Type type) { if (type == Type.date()) return Date.class.getName(); if (type == Type.float64()) return Double.class.getName(); if (type == Type.int64()) return Long.class.getName(); + if (type == Type.numeric()) return BigDecimal.class.getName(); if (type == Type.string()) return String.class.getName(); if (type == Type.timestamp()) return Timestamp.class.getName(); if (type.getCode() == Code.ARRAY) { @@ -104,6 +111,7 @@ static String getClassName(Type type) { if (type.getArrayElementType() == Type.date()) return Date[].class.getName(); if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); + if (type.getArrayElementType() == Type.numeric()) return BigDecimal[].class.getName(); if (type.getArrayElementType() == Type.string()) return String[].class.getName(); if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); } @@ -122,6 +130,16 @@ static byte checkedCastToByte(long val) throws SQLException { return (byte) val; } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static byte checkedCastToByte(BigDecimal val) throws SQLException { + try { + return val.byteValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "byte", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static short checkedCastToShort(long val) throws SQLException { if (val > Short.MAX_VALUE || val < Short.MIN_VALUE) { @@ -131,6 +149,16 @@ static short checkedCastToShort(long val) throws SQLException { return (short) val; } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static short checkedCastToShort(BigDecimal val) throws SQLException { + try { + return val.shortValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "short", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static int checkedCastToInt(long val) throws SQLException { if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) { @@ -140,6 +168,16 @@ static int checkedCastToInt(long val) throws SQLException { return (int) val; } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static int checkedCastToInt(BigDecimal val) throws SQLException { + try { + return val.intValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "int", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static float checkedCastToFloat(double val) throws SQLException { if (val > Float.MAX_VALUE || val < -Float.MAX_VALUE) { @@ -163,6 +201,26 @@ static long parseLong(String val) throws SQLException { } } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static BigInteger checkedCastToBigInteger(BigDecimal val) throws SQLException { + try { + return val.toBigIntegerExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "BigInteger", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + + /** Cast value and throw {@link SQLException} if out-of-range. */ + static long checkedCastToLong(BigDecimal val) throws SQLException { + try { + return val.longValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "long", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** * Parses the given string value as a double. Throws {@link SQLException} if the string is not a * valid double value. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 1c984c74d493..1dc5f0e49e6b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -19,6 +19,7 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; +import java.math.BigDecimal; import java.sql.Date; import java.sql.Timestamp; import java.sql.Types; @@ -175,6 +176,32 @@ public Type getSpannerType() { return Type.int64(); } }, + NUMERIC { + @Override + public int getSqlType() { + return Types.NUMERIC; + } + + @Override + public Class getJavaClass() { + return BigDecimal.class; + } + + @Override + public Code getCode() { + return Code.NUMERIC; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getBigDecimalList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.numeric(); + } + }, STRING { @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 22176595ec9f..508a2c3715e1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -1203,6 +1203,44 @@ public ResultSet getTypeInfo() throws SQLException { .to((Long) null) .set("NUM_PREC_RADIX") .to((Long) null) + .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("NUMERIC") + .set("DATA_TYPE") + .to(Types.NUMERIC) // 2 + .set("PRECISION") + .to(2621440L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(false) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("NUMERIC") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to(10) .build()))); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java index f78f1f03dc65..59b10b68fd0b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -98,7 +98,7 @@ public int getParameterType(int param) throws SQLException { } else if (Double.class.isAssignableFrom(value.getClass())) { return Types.DOUBLE; } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { - return Types.DECIMAL; + return Types.NUMERIC; } else if (Date.class.isAssignableFrom(value.getClass())) { return Types.DATE; } else if (Timestamp.class.isAssignableFrom(value.getClass())) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 5a139a9df0dc..807666ce4f97 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -211,11 +211,9 @@ private boolean isTypeSupported(int sqlType) { case Types.BLOB: case Types.CLOB: case Types.NCLOB: - return true; case Types.NUMERIC: case Types.DECIMAL: - // currently not supported as Cloud Spanner does not have any decimal data type. - return false; + return true; } return false; } @@ -235,11 +233,9 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { case Types.FLOAT: case Types.REAL: case Types.DOUBLE: - return value instanceof Number; case Types.NUMERIC: case Types.DECIMAL: - // currently not supported as Cloud Spanner does not have any decimal data type. - return false; + return value instanceof Number; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -473,9 +469,18 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, throw JdbcSqlExceptionFactory.of(value + " is not a valid double", Code.INVALID_ARGUMENT); case Types.NUMERIC: case Types.DECIMAL: - // currently not supported as Cloud Spanner does not have any decimal data type. + if (value instanceof Number) { + if (value instanceof BigDecimal) { + return binder.to((BigDecimal) value); + } + try { + return binder.to(new BigDecimal(value.toString())); + } catch (NumberFormatException e) { + // ignore and fall through to the exception. + } + } throw JdbcSqlExceptionFactory.of( - "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + value + " is not a valid BigDecimal", Code.INVALID_ARGUMENT); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -604,8 +609,7 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } else if (Double.class.isAssignableFrom(value.getClass())) { return binder.to(((Double) value).doubleValue()); } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { - // currently not supported - return null; + return binder.to((BigDecimal) value); } else if (Date.class.isAssignableFrom(value.getClass())) { Date dateValue = (Date) value; return binder.to(JdbcTypeConverter.toGoogleDate(dateValue)); @@ -693,8 +697,7 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu return binder.toFloat64Array((double[]) null); case Types.NUMERIC: case Types.DECIMAL: - throw JdbcSqlExceptionFactory.of( - "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + return binder.toNumericArray(null); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -755,8 +758,7 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (Double[].class.isAssignableFrom(value.getClass())) { return binder.toFloat64Array(toDoubleList((Double[]) value)); } else if (BigDecimal[].class.isAssignableFrom(value.getClass())) { - // currently not supported - return null; + return binder.toNumericArray(Arrays.asList((BigDecimal[]) value)); } else if (Date[].class.isAssignableFrom(value.getClass())) { return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value)); } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { @@ -810,9 +812,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) throw return binder.to((com.google.cloud.Date) null); case Types.NUMERIC: case Types.DECIMAL: - // currently not supported - throw JdbcSqlExceptionFactory.of( - "DECIMAL/NUMERIC values are not supported", Code.INVALID_ARGUMENT); + return binder.to((BigDecimal) null); case Types.DOUBLE: return binder.to((Double) null); case Types.FLOAT: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 2e4014ba2c68..3f10b0c18853 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -138,6 +138,8 @@ public String getString(int columnIndex) throws SQLException { return isNull ? null : Double.toString(spanner.getDouble(spannerIndex)); case INT64: return isNull ? null : Long.toString(spanner.getLong(spannerIndex)); + case NUMERIC: + return isNull ? null : spanner.getBigDecimal(spannerIndex).toString(); case STRING: return isNull ? null : spanner.getString(spannerIndex); case TIMESTAMP: @@ -162,6 +164,8 @@ public boolean getBoolean(int columnIndex) throws SQLException { return isNull ? false : spanner.getDouble(spannerIndex) != 0D; case INT64: return isNull ? false : spanner.getLong(spannerIndex) != 0L; + case NUMERIC: + return isNull ? false : !spanner.getBigDecimal(spannerIndex).equals(BigDecimal.ZERO); case STRING: return isNull ? false : Boolean.valueOf(spanner.getString(spannerIndex)); case BYTES: @@ -189,6 +193,8 @@ public byte getByte(int columnIndex) throws SQLException { : checkedCastToByte(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: return isNull ? (byte) 0 : checkedCastToByte(spanner.getLong(spannerIndex)); + case NUMERIC: + return isNull ? (byte) 0 : checkedCastToByte(spanner.getBigDecimal(spannerIndex)); case STRING: return isNull ? (byte) 0 : checkedCastToByte(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -216,6 +222,8 @@ public short getShort(int columnIndex) throws SQLException { : checkedCastToShort(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); + case NUMERIC: + return isNull ? 0 : checkedCastToShort(spanner.getBigDecimal(spannerIndex)); case STRING: return isNull ? 0 : checkedCastToShort(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -243,6 +251,8 @@ public int getInt(int columnIndex) throws SQLException { : checkedCastToInt(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: return isNull ? 0 : checkedCastToInt(spanner.getLong(spannerIndex)); + case NUMERIC: + return isNull ? 0 : checkedCastToInt(spanner.getBigDecimal(spannerIndex)); case STRING: return isNull ? 0 : checkedCastToInt(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -268,6 +278,8 @@ public long getLong(int columnIndex) throws SQLException { return isNull ? 0L : Double.valueOf(spanner.getDouble(spannerIndex)).longValue(); case INT64: return isNull ? 0L : spanner.getLong(spannerIndex); + case NUMERIC: + return isNull ? 0L : checkedCastToLong(spanner.getBigDecimal(spannerIndex)); case STRING: return isNull ? 0L : parseLong(spanner.getString(spannerIndex)); case BYTES: @@ -293,6 +305,8 @@ public float getFloat(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToFloat(spanner.getDouble(spannerIndex)); case INT64: return isNull ? 0 : checkedCastToFloat(spanner.getLong(spannerIndex)); + case NUMERIC: + return isNull ? 0 : spanner.getBigDecimal(spannerIndex).floatValue(); case STRING: return isNull ? 0 : checkedCastToFloat(parseDouble(spanner.getString(spannerIndex))); case BYTES: @@ -318,6 +332,8 @@ public double getDouble(int columnIndex) throws SQLException { return isNull ? 0 : spanner.getDouble(spannerIndex); case INT64: return isNull ? 0 : spanner.getLong(spannerIndex); + case NUMERIC: + return isNull ? 0 : spanner.getBigDecimal(spannerIndex).doubleValue(); case STRING: return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); case BYTES: @@ -354,6 +370,7 @@ public Date getDate(int columnIndex) throws SQLException { case BOOL: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: @@ -377,6 +394,7 @@ public Time getTime(int columnIndex) throws SQLException { case DATE: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: @@ -401,6 +419,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case BOOL: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: @@ -555,6 +574,7 @@ private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.date()) return getDate(columnIndex); if (type == Type.float64()) return getDouble(columnIndex); if (type == Type.int64()) return getLong(columnIndex); + if (type == Type.numeric()) return getBigDecimal(columnIndex); if (type == Type.string()) return getString(columnIndex); if (type == Type.timestamp()) return getTimestamp(columnIndex); if (type.getCode() == Code.ARRAY) return getArray(columnIndex); @@ -630,6 +650,9 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) case INT64: res = isNull ? null : BigDecimal.valueOf(spanner.getLong(spannerIndex)); break; + case NUMERIC: + res = isNull ? null : spanner.getBigDecimal(spannerIndex); + break; case STRING: try { res = isNull ? null : new BigDecimal(spanner.getString(spannerIndex)); @@ -724,6 +747,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { case BOOL: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: @@ -752,6 +776,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { case DATE: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: @@ -783,6 +808,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException case BOOL: case FLOAT64: case INT64: + case NUMERIC: case BYTES: case STRUCT: case ARRAY: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index 4292c9225515..a598b109e46d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -79,7 +79,7 @@ public int isNullable(int column) throws SQLException { @Override public boolean isSigned(int column) throws SQLException { int type = getColumnType(column); - return type == Types.DOUBLE || type == Types.BIGINT; + return type == Types.DOUBLE || type == Types.BIGINT || type == Types.NUMERIC; } @Override @@ -99,6 +99,8 @@ public int getColumnDisplaySize(int column) throws SQLException { return 14; case Types.BIGINT: return 10; + case Types.NUMERIC: + return 14; case Types.NVARCHAR: int length = getPrecision(column); return length == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : length; @@ -136,6 +138,8 @@ public int getPrecision(int column) throws SQLException { return 14; case Types.BIGINT: return 10; + case Types.NUMERIC: + return 14; case Types.TIMESTAMP: return 24; default: @@ -150,7 +154,7 @@ public int getPrecision(int column) throws SQLException { @Override public int getScale(int column) throws SQLException { int colType = getColumnType(column); - if (colType == Types.DOUBLE) return 15; + if (colType == Types.DOUBLE || colType == Types.NUMERIC) return 15; return 0; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index e922e58598c9..c1f4b929d1bf 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -80,43 +80,58 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (type.getCode() == Code.BOOL) return value; if (type.getCode() == Code.INT64) return Boolean.valueOf((Long) value != 0); if (type.getCode() == Code.FLOAT64) return Boolean.valueOf((Double) value != 0d); + if (type.getCode() == Code.NUMERIC) + return Boolean.valueOf(!((BigDecimal) value).equals(BigDecimal.ZERO)); } if (targetType.equals(BigDecimal.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; if (type.getCode() == Code.INT64) return BigDecimal.valueOf((Long) value); + if (type.getCode() == Code.NUMERIC) return value; } if (targetType.equals(Long.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1L : 0L; if (type.getCode() == Code.INT64) return value; + if (type.getCode() == Code.NUMERIC) + return AbstractJdbcWrapper.checkedCastToLong((BigDecimal) value); } if (targetType.equals(Integer.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64) return AbstractJdbcWrapper.checkedCastToInt((Long) value); + if (type.getCode() == Code.NUMERIC) + return AbstractJdbcWrapper.checkedCastToInt((BigDecimal) value); } if (targetType.equals(Short.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64) return AbstractJdbcWrapper.checkedCastToShort((Long) value); + if (type.getCode() == Code.NUMERIC) + return AbstractJdbcWrapper.checkedCastToShort((BigDecimal) value); } if (targetType.equals(Byte.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64) return AbstractJdbcWrapper.checkedCastToByte((Long) value); + if (type.getCode() == Code.NUMERIC) + return AbstractJdbcWrapper.checkedCastToByte((BigDecimal) value); } if (targetType.equals(BigInteger.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; if (type.getCode() == Code.INT64) return BigInteger.valueOf((Long) value); + if (type.getCode() == Code.NUMERIC) + return AbstractJdbcWrapper.checkedCastToBigInteger((BigDecimal) value); } if (targetType.equals(Float.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Float.valueOf(1f) : Float.valueOf(0f); if (type.getCode() == Code.FLOAT64) return AbstractJdbcWrapper.checkedCastToFloat((Double) value); + if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).floatValue(); } if (targetType.equals(Double.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Double.valueOf(1d) : Double.valueOf(0d); if (type.getCode() == Code.FLOAT64) return value; + if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).doubleValue(); } if (targetType.equals(java.sql.Date.class)) { if (type.getCode() == Code.DATE) return value; @@ -175,6 +190,10 @@ private static void checkValidTypeAndValueForConvert(Type type, Object value) (type.getCode() == Code.TIMESTAMP && value.getClass().equals(java.sql.Timestamp.class)) || type.getCode() != Code.TIMESTAMP, "input type is timestamp, but input value is not an instance of java.sql.Timestamp"); + JdbcPreconditions.checkArgument( + (type.getCode() == Code.NUMERIC && value.getClass().equals(BigDecimal.class)) + || type.getCode() != Code.NUMERIC, + "input type is numeric, but input value is not an instance of BigDecimal"); } @SuppressWarnings("deprecation") diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 40601611e848..8b29c15b1493 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -22,6 +22,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE = 'DATE' THEN 91 WHEN SPANNER_TYPE = 'FLOAT64' THEN 8 WHEN SPANNER_TYPE = 'INT64' THEN -5 + WHEN SPANNER_TYPE = 'NUMERIC' THEN 2 WHEN SPANNER_TYPE LIKE 'STRING%' THEN -9 WHEN SPANNER_TYPE = 'TIMESTAMP' THEN 93 END AS DATA_TYPE, @@ -30,6 +31,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN STRPOS(SPANNER_TYPE, '(')=0 THEN CASE WHEN SPANNER_TYPE = 'INT64' OR SPANNER_TYPE = 'ARRAY' THEN 19 + WHEN SPANNER_TYPE = 'NUMERIC' OR SPANNER_TYPE = 'ARRAY' THEN 15 WHEN SPANNER_TYPE = 'FLOAT64' OR SPANNER_TYPE = 'ARRAY' THEN 15 WHEN SPANNER_TYPE = 'BOOL' OR SPANNER_TYPE = 'ARRAY' THEN NULL WHEN SPANNER_TYPE = 'DATE' OR SPANNER_TYPE = 'ARRAY' THEN 10 @@ -45,6 +47,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU END AS DECIMAL_DIGITS, CASE WHEN SPANNER_TYPE LIKE '%INT64%' THEN 10 + WHEN SPANNER_TYPE LIKE '%NUMERIC%' THEN 10 WHEN SPANNER_TYPE LIKE '%FLOAT64%' THEN 2 ELSE NULL END AS NUM_PREC_RADIX, diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 50a696fa5122..01184c2d2226 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; +import java.math.BigDecimal; import java.sql.Date; import java.sql.SQLException; import java.sql.Timestamp; @@ -54,6 +55,13 @@ public void testCreateArrayTypeName() throws SQLException { assertEquals(array.getBaseType(), Types.BIGINT); assertEquals(((Long[]) array.getArray(1, 1))[0], Long.valueOf(1L)); + array = + JdbcArray.createArray("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}); + assertEquals(array.getBaseType(), Types.NUMERIC); + assertEquals(((BigDecimal[]) array.getArray(1, 1))[0], BigDecimal.ONE); + assertEquals(((BigDecimal[]) array.getArray(2, 1))[0], null); + assertEquals(((BigDecimal[]) array.getArray(3, 1))[0], BigDecimal.TEN); + array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); assertEquals(array.getBaseType(), Types.NVARCHAR); assertEquals(((String[]) array.getArray(1, 1))[0], "foo"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 48d55214de31..b3697a071aec 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -461,6 +461,8 @@ public void testGetTypeInfo() throws SQLException { assertThat(rs.getString("TYPE_NAME"), is(equalTo("DATE"))); assertThat(rs.next(), is(true)); assertThat(rs.getString("TYPE_NAME"), is(equalTo("TIMESTAMP"))); + assertThat(rs.next(), is(true)); + assertThat(rs.getString("TYPE_NAME"), is(equalTo("NUMERIC"))); assertThat(rs.next(), is(false)); ResultSetMetaData rsmd = rs.getMetaData(); assertThat(rsmd.getColumnCount(), is(equalTo(18))); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 60911a86a771..bdeda19cfbd3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -328,8 +328,10 @@ public void autocommitExecuteStreamingSql() { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - connection.createStatement().executeQuery(SELECT1.getSql()); - fail("missing expected exception"); + try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + rs.next(); + fail("missing expected exception"); + } } catch (SQLException e) { assertThat(testExceptionMatcher.matches(e)).isTrue(); } @@ -341,8 +343,10 @@ public void transactionalExecuteStreamingSql() { SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - connection.createStatement().executeQuery(SELECT1.getSql()); - fail("missing expected exception"); + try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + rs.next(); + fail("missing expected exception"); + } } catch (SQLException e) { assertThat(testExceptionMatcher.matches(e)).isTrue(); } @@ -355,8 +359,10 @@ public void readOnlyExecuteStreamingSql() { try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); - connection.createStatement().executeQuery(SELECT1.getSql()); - fail("missing expected exception"); + try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { + rs.next(); + fail("missing expected exception"); + } } catch (SQLException e) { assertThat(testExceptionMatcher.matches(e)).isTrue(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 1b201f9a916e..624a031ef90b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -120,16 +120,8 @@ public void testSetParameterWithType() throws SQLException, IOException { is(true)); verifyParameter(params, Value.string("test")); - // test unsupported types - boolean expectedException = false; - try { - params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); - } catch (SQLException e) { - if (e instanceof JdbcSqlException) { - expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; - } - } - assertThat(expectedException, is(true)); + params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); // types that should lead to int64 for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { @@ -281,6 +273,32 @@ public void testSetParameterWithType() throws SQLException, IOException { assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ZERO))); verifyParameter(params, Value.bool(false)); } + + // types that should lead to numeric + for (int type : new int[] {Types.DECIMAL, Types.NUMERIC}) { + params.setParameter(1, BigDecimal.ONE, type); + assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + + params.setParameter(1, (byte) 1, type); + assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + params.setParameter(1, (short) 1, type); + assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + params.setParameter(1, 1, type); + assertThat((Integer) params.getParameter(1), is(equalTo(1))); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + params.setParameter(1, 1L, type); + assertThat((Long) params.getParameter(1), is(equalTo(1L))); + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + params.setParameter(1, (float) 1, type); + assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); + params.setParameter(1, (double) 1, type); + assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); + } } @Test @@ -353,9 +371,6 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { assertInvalidParameter(params, new Object(), type); } - assertInvalidParameter(params, BigDecimal.ONE, Types.DECIMAL); - assertInvalidParameter(params, BigDecimal.ZERO, Types.NUMERIC); - // test setting closed readers and streams. for (int type : new int[] { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index bcf0454f75a5..c5d939601b0b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -34,7 +34,6 @@ import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.StringReader; -import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Date; @@ -211,15 +210,6 @@ public void testParameters() throws SQLException, MalformedURLException { private void testSetUnsupportedTypes(PreparedStatement ps) { // TODO: Rewrite these tests using functional interfaces when Java8 is available. boolean expectedException = false; - try { - ps.setBigDecimal(5, BigDecimal.valueOf(1l)); - } catch (SQLException e) { - if (e instanceof JdbcSqlException) { - expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; - } - } - assertThat(expectedException, is(true)); - expectedException = false; try { ps.setRef(38, (Ref) null); } catch (SQLException e) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 58ef03a1c9ed..d7c844a787ff 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -71,7 +71,8 @@ public void testConvertArray() throws SQLException { Type.float64(), Type.int64(), Type.string(), - Type.timestamp() + Type.timestamp(), + Type.numeric() }) { assertConvertThrows(testValue, Type.array(t), Boolean.class, Code.INVALID_ARGUMENT); assertConvertThrows(testValue, Type.array(t), Byte.class, Code.INVALID_ARGUMENT); @@ -292,6 +293,43 @@ public void testConvertFloat64() throws SQLException { } } + @Test + public void testConvertNumeric() throws SQLException { + BigDecimal[] testValues = + new BigDecimal[] { + BigDecimal.ZERO, + BigDecimal.ONE.negate(), + BigDecimal.ONE, + BigDecimal.valueOf(Double.MIN_VALUE), + BigDecimal.valueOf(Double.MAX_VALUE), + BigDecimal.valueOf(Float.MIN_VALUE), + BigDecimal.valueOf(Float.MAX_VALUE), + BigDecimal.valueOf(Float.MAX_VALUE + 1D) + }; + for (BigDecimal d : testValues) { + assertThat(convert(d, Type.numeric(), BigDecimal.class)).isEqualTo(d); + assertThat(convert(d, Type.numeric(), Double.class)).isEqualTo(d.doubleValue()); + assertThat(convert(d, Type.numeric(), Float.class)).isEqualTo(d.floatValue()); + assertThat(convert(d, Type.numeric(), String.class)).isEqualTo(String.valueOf(d)); + assertThat(convert(d, Type.numeric(), Boolean.class)) + .isEqualTo(Boolean.valueOf(!d.equals(BigDecimal.ZERO))); + if (d.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0 + || d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0 + || d.scale() > 0) { + assertConvertThrows(d, Type.numeric(), Long.class, Code.OUT_OF_RANGE); + } else { + assertThat(convert(d, Type.numeric(), Long.class)).isEqualTo(d.longValue()); + } + if (d.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) > 0 + || d.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) < 0 + || d.scale() > 0) { + assertConvertThrows(d, Type.numeric(), Integer.class, Code.OUT_OF_RANGE); + } else { + assertThat(convert(d, Type.numeric(), Integer.class)).isEqualTo(d.intValue()); + } + } + } + private void assertConvertThrows(Object t, Type type, Class destinationType, Code code) throws SQLException { try { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java index 4cd5e9b9be1b..be5fed233dea 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java @@ -55,7 +55,7 @@ public boolean matches(Object item) { return exception.getErrorCode() == errorCode.getNumber(); } return exception.getErrorCode() == errorCode.getNumber() - && exception.getMessage().endsWith(": " + message); + && exception.getMessage().contains(": " + message); } return false; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 9cf57b3f8e10..711363c29159 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -104,6 +104,7 @@ private Column( new Column("ColDate", Types.DATE, "DATE", 10, null, null, false, null), new Column("ColTimestamp", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColCommitTS", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), + new Column("ColNumeric", Types.NUMERIC, "NUMERIC", 15, null, 10, false, null), new Column("ColInt64Array", Types.ARRAY, "ARRAY", 19, null, 10, true, null), new Column("ColFloat64Array", Types.ARRAY, "ARRAY", 15, 16, 2, true, null), new Column("ColBoolArray", Types.ARRAY, "ARRAY", null, null, null, true, null), @@ -131,7 +132,8 @@ private Column( null), new Column("ColDateArray", Types.ARRAY, "ARRAY", 10, null, null, true, null), new Column( - "ColTimestampArray", Types.ARRAY, "ARRAY", 35, null, null, true, null)); + "ColTimestampArray", Types.ARRAY, "ARRAY", 35, null, null, true, null), + new Column("ColNumericArray", Types.ARRAY, "ARRAY", 15, null, 10, true, null)); @Test public void testGetColumns() throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 60ddb3c2c370..799b494d0e62 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -31,6 +31,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.StringReader; +import java.math.BigDecimal; import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.Date; @@ -749,6 +750,94 @@ public void test07_StatementBatchUpdateWithException() throws SQLException { } } + @Test + public void test08_InsertAllColumnTypes() throws SQLException { + try (Connection con = createConnection()) { + try (PreparedStatement ps = + con.prepareStatement( + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + ps.setLong(1, 1L); + ps.setDouble(2, 2D); + ps.setBoolean(3, true); + ps.setString(4, "test"); + ps.setString(5, "testtest"); + ps.setBytes(6, "test".getBytes()); + ps.setBytes(7, "testtest".getBytes()); + ps.setDate(8, new Date(System.currentTimeMillis())); + ps.setTimestamp(9, new Timestamp(System.currentTimeMillis())); + ps.setBigDecimal(10, BigDecimal.TEN); + ps.setArray(11, con.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); + ps.setArray(12, con.createArrayOf("FLOAT64", new Double[] {1.1D, 2.2D, 3.3D})); + ps.setArray( + 13, con.createArrayOf("BOOL", new Boolean[] {Boolean.TRUE, null, Boolean.FALSE})); + ps.setArray(14, con.createArrayOf("STRING", new String[] {"1", "2", "3"})); + ps.setArray(15, con.createArrayOf("STRING", new String[] {"3", "2", "1"})); + ps.setArray( + 16, + con.createArrayOf( + "BYTES", new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()})); + ps.setArray( + 17, + con.createArrayOf( + "BYTES", new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()})); + ps.setArray( + 18, + con.createArrayOf( + "DATE", new Date[] {new Date(System.currentTimeMillis()), null, new Date(0)})); + ps.setArray( + 19, + con.createArrayOf( + "TIMESTAMP", + new Timestamp[] { + new Timestamp(System.currentTimeMillis()), null, new Timestamp(0) + })); + ps.setArray( + 20, + con.createArrayOf("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN})); + assertThat(ps.executeUpdate(), is(equalTo(1))); + } + try (ResultSet rs = + con.createStatement().executeQuery("SELECT * FROM TableWithAllColumnTypes")) { + assertThat(rs.next(), is(true)); + assertThat(rs.getLong(1), is(equalTo(1L))); + assertThat(rs.getDouble(2), is(equalTo(2D))); + assertThat(rs.getBoolean(3), is(true)); + assertThat(rs.getString(4), is(equalTo("test"))); + assertThat(rs.getString(5), is(equalTo("testtest"))); + assertThat(rs.getBytes(6), is(equalTo("test".getBytes()))); + assertThat(rs.getBytes(7), is(equalTo("testtest".getBytes()))); + assertThat(rs.getDate(8), is(notNullValue())); + assertThat(rs.getTimestamp(9), is(notNullValue())); + assertThat(rs.getTime(10), is(notNullValue())); // Commit timestamp + assertThat(rs.getBigDecimal(11), is(equalTo(BigDecimal.TEN))); + assertThat((Long[]) rs.getArray(12).getArray(), is(equalTo(new Long[] {1L, 2L, 3L}))); + assertThat( + (Double[]) rs.getArray(13).getArray(), is(equalTo(new Double[] {1.1D, 2.2D, 3.3D}))); + assertThat( + (Boolean[]) rs.getArray(14).getArray(), is(equalTo(new Boolean[] {true, null, false}))); + assertThat( + (String[]) rs.getArray(15).getArray(), is(equalTo(new String[] {"1", "2", "3"}))); + assertThat( + (String[]) rs.getArray(16).getArray(), is(equalTo(new String[] {"3", "2", "1"}))); + assertThat( + (byte[][]) rs.getArray(17).getArray(), + is(equalTo(new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()}))); + assertThat( + (byte[][]) rs.getArray(18).getArray(), + is(equalTo(new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()}))); + assertThat(((Date[]) rs.getArray(19).getArray()).length, is(equalTo(3))); + assertThat(((Timestamp[]) rs.getArray(20).getArray()).length, is(equalTo(3))); + assertThat( + (BigDecimal[]) rs.getArray(21).getArray(), + is(equalTo(new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}))); + assertThat(rs.next(), is(false)); + } + } + } + private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) throws SQLException { assertThat(pmd.getParameterCount(), is(equalTo(expectedParamCount))); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 5bbb90f6bdf1..4d05cdfb55d7 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -73,6 +73,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColDate DATE NOT NULL, ColTimestamp TIMESTAMP NOT NULL, ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), + ColNumeric NUMERIC NOT NULL, ColInt64Array ARRAY, ColFloat64Array ARRAY, @@ -82,7 +83,8 @@ CREATE TABLE TableWithAllColumnTypes ( ColBytesArray ARRAY, ColBytesMaxArray ARRAY, ColDateArray ARRAY, - ColTimestampArray ARRAY + ColTimestampArray ARRAY, + ColNumericArray ARRAY ) PRIMARY KEY (ColInt64) ; From aa209b227e2c124412954f8f6d71ec72f41a2457 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 5 Sep 2020 10:15:37 +1000 Subject: [PATCH 0197/1979] chore: release 1.17.0 (#201) * chore: updated CHANGELOG.md [ci skip] * chore: updated README.md [ci skip] * chore: updated versions.txt [ci skip] * chore: updated samples/pom.xml [ci skip] * chore: updated samples/install-without-bom/pom.xml [ci skip] * chore: updated samples/snapshot/pom.xml [ci skip] * chore: updated pom.xml [ci skip] * chore: updated samples/snippets/pom.xml Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d8bafd09ce76..287047b61165 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [1.17.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.16.0...v1.17.0) (2020-09-04) + + +### Features + +* add support for NUMERIC type ([#185](https://www.github.com/googleapis/java-spanner-jdbc/issues/185)) ([4579249](https://www.github.com/googleapis/java-spanner-jdbc/commit/457924980ab0f10fcbb61a0cf1442069f4d0b8b4)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.3 ([#180](https://www.github.com/googleapis/java-spanner-jdbc/issues/180)) ([b446d48](https://www.github.com/googleapis/java-spanner-jdbc/commit/b446d48e40973ef03ec1d3c470a338c371b967a1)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.4 ([#187](https://www.github.com/googleapis/java-spanner-jdbc/issues/187)) ([ddb96f2](https://www.github.com/googleapis/java-spanner-jdbc/commit/ddb96f2424c11d0cde3a4b702a1e3599c0489e96)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.8.6 ([#189](https://www.github.com/googleapis/java-spanner-jdbc/issues/189)) ([2259332](https://www.github.com/googleapis/java-spanner-jdbc/commit/2259332c7657cd160aef889f88649713dd2fe61e)) + ## [1.16.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.15.0...v1.16.0) (2020-07-08) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index b3b29ce206b5..12825ec87eb4 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.16.0 + 1.17.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.16.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.16.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.0" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 27f615ff07ea..27cb88a8cf56 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.16.1-SNAPSHOT + 1.17.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3571e453471f..dbe465c72ea1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.16.1-SNAPSHOT + 1.17.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1aedcc871151..a93df05d767d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.16.0:1.16.1-SNAPSHOT +google-cloud-spanner-jdbc:1.17.0:1.17.0 From 57e6504c0dce3a149dff2ed1a99da87682c4ee08 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 8 Sep 2020 00:29:25 -0700 Subject: [PATCH 0198/1979] build(java): switch to release-publish app for notifying GitHub of release status (#197) Source-Author: Jeff Ching Source-Date: Wed Aug 26 21:48:06 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: 019c7168faa0e56619f792693a8acdb30d6de19b Source-Link: https://github.com/googleapis/synthtool/commit/019c7168faa0e56619f792693a8acdb30d6de19b --- java-spanner-jdbc/.kokoro/release/stage.cfg | 31 ++------------------- java-spanner-jdbc/.kokoro/release/stage.sh | 5 ++-- java-spanner-jdbc/synth.metadata | 4 +-- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/stage.cfg b/java-spanner-jdbc/.kokoro/release/stage.cfg index 8ea66bc79322..edca2bef01e1 100644 --- a/java-spanner-jdbc/.kokoro/release/stage.cfg +++ b/java-spanner-jdbc/.kokoro/release/stage.cfg @@ -13,32 +13,7 @@ action { } } -# Fetch the token needed for reporting release status to GitHub -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "yoshi-automation-github-key" - } - } -} - -# Fetch magictoken to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "releasetool-magictoken" - } - } -} - -# Fetch api key to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "magic-github-proxy-api-key" - } - } +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" } diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index d19191fc896c..3c482cbc55f1 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -16,9 +16,8 @@ set -eo pipefail # Start the releasetool reporter -# Disable reporting due to issue observed with Kokoro blocking releases -# python3 -m pip install gcp-releasetool -# python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script +python3 -m pip install gcp-releasetool +python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script source $(dirname "$0")/common.sh MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 8ad3605ced83..6982bb6e84cb 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "41a179972deb84035ccd17cccc31f746dbc620db" + "sha": "b5a7cb875718f88d66f6e717058706dd499e4fac" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "968465a1cad496e1292ef4584a054a35f756ff94" + "sha": "019c7168faa0e56619f792693a8acdb30d6de19b" } } ], From 9df5286b1315a95c037d3d206a2ab3b895b6ed18 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Sep 2020 09:30:04 +0200 Subject: [PATCH 0199/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v10 (#198) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 27cb88a8cf56..a5f038228012 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 9.1.0 + 10.0.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index cf90669f5dd7..43116f8336ad 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 9.1.0 + 10.0.0 pom import From 5393942528870a5af5f855a561fe555b3b79e835 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Sep 2020 21:26:10 +0200 Subject: [PATCH 0200/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.9.0 (#199) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.8.6` -> `0.9.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.9.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​090-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare086v090-2020-08-31) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.8.6...v0.9.0) ##### Bug Fixes - temporarily disable reporting to unblock releases ([#​129](https://www.github.com/googleapis/java-shared-dependencies/issues/129)) ([7fff6f2](https://www.github.com/googleapis/java-shared-dependencies/commit/7fff6f2c94a19ba998d8cd47e8be5a6333808df8)) ##### Dependencies - update dependency com.google.protobuf:protobuf-bom to v3.13.0 ([#​126](https://www.github.com/googleapis/java-shared-dependencies/issues/126)) ([908063f](https://www.github.com/googleapis/java-shared-dependencies/commit/908063f9b820dd3195b15537189e45be0d4acbbb)) - update dependency io.grpc:grpc-bom to v1.31.1 ([#​124](https://www.github.com/googleapis/java-shared-dependencies/issues/124)) ([553a339](https://www.github.com/googleapis/java-shared-dependencies/commit/553a3393f5bede0e90e16e2d0d87daa2b936ab32)) - update google.common-protos.version to v1.18.1 ([#​119](https://www.github.com/googleapis/java-shared-dependencies/issues/119)) ([05ad27e](https://www.github.com/googleapis/java-shared-dependencies/commit/05ad27e35fe082e148d377315b10943b187b5670)) - update google.core.version to v1.93.8 ([f72cef3](https://www.github.com/googleapis/java-shared-dependencies/commit/f72cef3d78a036e2b2434bf08b0a75d57b2fa139)) - update iam.version to v0.15.0 ([#​118](https://www.github.com/googleapis/java-shared-dependencies/issues/118)) ([1409a16](https://www.github.com/googleapis/java-shared-dependencies/commit/1409a16826d3fd4a5d9cbcbe46ea4b4af8687a5c)) - update iam.version to v1 (major) ([#​120](https://www.github.com/googleapis/java-shared-dependencies/issues/120)) ([a6243a0](https://www.github.com/googleapis/java-shared-dependencies/commit/a6243a02129e42fec804b5769fb8e3f334ba84ce)) ##### [0.8.6](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.5...v0.8.6) (2020-08-07) ##### Dependencies - update gax to v1.58.2 ([#​115](https://www.github.com/googleapis/java-shared-dependencies/issues/115)) ([84b48b4](https://www.github.com/googleapis/java-shared-dependencies/commit/84b48b4e77a4b5b4a2db6030609abe241d5ee2e1)) ##### [0.8.5](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.4...v0.8.5) (2020-08-07) ##### Dependencies - update gax to v1.58.1 ([#​111](https://www.github.com/googleapis/java-shared-dependencies/issues/111)) ([93a1691](https://www.github.com/googleapis/java-shared-dependencies/commit/93a16915b863a610ffdabe0e23aec58c4ae5f4f1)) ##### [0.8.4](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.3...v0.8.4) (2020-08-04) ##### Dependencies - update core dependencies ([#​104](https://www.github.com/googleapis/java-shared-dependencies/issues/104)) ([5046818](https://www.github.com/googleapis/java-shared-dependencies/commit/504681803d2bba888404acffe9a8853746501358)) - update dependency com.google.api:api-common to v1.10.0 ([#​101](https://www.github.com/googleapis/java-shared-dependencies/issues/101)) ([6472fac](https://www.github.com/googleapis/java-shared-dependencies/commit/6472face89700e3f2f982c04a5e88801876580be)) - update dependency com.google.protobuf:protobuf-bom to v3.12.4 ([#​103](https://www.github.com/googleapis/java-shared-dependencies/issues/103)) ([885bd0e](https://www.github.com/googleapis/java-shared-dependencies/commit/885bd0ef3c9e344bd1fc60e0f3264995064001d9)) ##### [0.8.3](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.2...v0.8.3) (2020-07-09) ##### Dependencies - update core dependencies ([#​96](https://www.github.com/googleapis/java-shared-dependencies/issues/96)) ([978e69e](https://www.github.com/googleapis/java-shared-dependencies/commit/978e69e9b5999630354ea204c034be2d6b8a2d80)) - update dependency com.google.api-client:google-api-client-bom to v1.30.10 ([#​99](https://www.github.com/googleapis/java-shared-dependencies/issues/99)) ([65c9cce](https://www.github.com/googleapis/java-shared-dependencies/commit/65c9ccea34275fa6f9599043d6e06df169bc433a)) - update dependency com.google.api:api-common to v1.9.3 ([#​91](https://www.github.com/googleapis/java-shared-dependencies/issues/91)) ([2a23a50](https://www.github.com/googleapis/java-shared-dependencies/commit/2a23a50ee5c73b581a02171048e20b14f999949f)) ##### [0.8.2](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.1...v0.8.2) (2020-07-01) ##### Dependencies - update dependency com.google.auth:google-auth-library-bom to v0.21.0 ([#​86](https://www.github.com/googleapis/java-shared-dependencies/issues/86)) ([dc9d717](https://www.github.com/googleapis/java-shared-dependencies/commit/dc9d717fdec4f0962141ba34e98f5737ec3bc57a)) - update dependency com.google.http-client:google-http-client-bom to v1.36.0 ([#​89](https://www.github.com/googleapis/java-shared-dependencies/issues/89)) ([12437d7](https://www.github.com/googleapis/java-shared-dependencies/commit/12437d7392a430299c3372d18d2650b62be60eaf)) - update dependency io.grpc:grpc-bom to v1.30.1 ([#​82](https://www.github.com/googleapis/java-shared-dependencies/issues/82)) ([a5199a0](https://www.github.com/googleapis/java-shared-dependencies/commit/a5199a02d5bde75e86349b37c1efae64a6379a40)) - update dependency io.grpc:grpc-bom to v1.30.2 ([#​85](https://www.github.com/googleapis/java-shared-dependencies/issues/85)) ([084d18d](https://www.github.com/googleapis/java-shared-dependencies/commit/084d18daab010c6b0be04e67b42ca8ab8ba5f3d5)) ##### [0.8.1](https://www.github.com/googleapis/java-shared-dependencies/compare/v0.8.0...v0.8.1) (2020-06-13) ##### Reverts - Revert "feat: mark javax annotations scope as provided ([#​70](https://togithub.com/googleapis/java-shared-dependencies/issues/70))" ([#​75](https://togithub.com/googleapis/java-shared-dependencies/issues/75)) ([d2f23ec](https://www.github.com/googleapis/java-shared-dependencies/commit/d2f23ecae56a1ec07b1217f0fca5347dd0f0406b)), closes [#​70](https://www.github.com/googleapis/java-shared-dependencies/issues/70) [#​75](https://www.github.com/googleapis/java-shared-dependencies/issues/75)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a5f038228012..907b4a911ec8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.8.6 + 0.9.0 pom import From 6b86b61e626d5df68879976ec34bf90d9ce6be49 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Sep 2020 00:19:55 +0200 Subject: [PATCH 0201/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.1.1 (#200) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 907b4a911ec8..6fde42860c18 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -361,7 +361,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.1.0 + 3.1.1 From 0523b255888093d7b855d04f2238ee7176b37de9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Sep 2020 00:20:34 +0200 Subject: [PATCH 0202/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.17.0 (#202) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 4d31f843dd6d..978869ab23e1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.16.0 + 1.17.0 From a44a2d70abd06abe9c907000402c8764487dafa8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 08:46:20 +1000 Subject: [PATCH 0203/1979] chore: release 1.17.1-SNAPSHOT (#203) * chore: updated versions.txt [ci skip] * chore: updated samples/pom.xml [ci skip] * chore: updated samples/install-without-bom/pom.xml [ci skip] * chore: updated samples/snippets/pom.xml [ci skip] * chore: updated pom.xml [ci skip] * chore: updated samples/snapshot/pom.xml Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6fde42860c18..23999d9a70b1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.0 + 1.17.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index dbe465c72ea1..284ecefade18 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.0 + 1.17.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a93df05d767d..f2b71aa2d888 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.0:1.17.0 +google-cloud-spanner-jdbc:1.17.0:1.17.1-SNAPSHOT From 0cc18be570a2946f6b82e612a211709b5ae03f5a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 10 Sep 2020 07:45:15 +0200 Subject: [PATCH 0204/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v10.1.0 (#205) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 23999d9a70b1..18b278398f1c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 10.0.0 + 10.1.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 43116f8336ad..8f9cd29bb02e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 10.0.0 + 10.1.0 pom import From 5cc76fcdfd22d613fa30489540c4cf6f33c72600 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 21 Sep 2020 15:04:02 -0700 Subject: [PATCH 0205/1979] build(ci): enable auto-release for dependency-update-only releases (#207) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/c4f2bea9-da3f-4895-ad62-afd4fd0c9206/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/538a68019eb4a36a0cdfa4021f324dd01b784395 --- .../.github/workflows/auto-release.yaml | 69 +++++++++++++++++++ java-spanner-jdbc/synth.metadata | 5 +- 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/auto-release.yaml diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml new file mode 100644 index 000000000000..d26427e468a4 --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -0,0 +1,69 @@ +on: + pull_request: +name: auto-release +jobs: + approve: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v3.0.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + debug: true + script: | + // only approve PRs from release-please[bot] + if (context.payload.pull_request.user.login !== "release-please[bot]") { + return; + } + + // only approve PRs like "chore: release " + if ( !context.payload.pull_request.title.startsWith("chore: release") ) { + return; + } + + // trigger auto-release when + // 1) it is a SNAPSHOT release (auto-generated post regular release) + // 2) there are dependency updates only + // 3) there are no open dependency update PRs in this repo (to avoid multiple releases) + if ( + context.payload.pull_request.body.includes("Fix") || + context.payload.pull_request.body.includes("Build") || + context.payload.pull_request.body.includes("Documentation") || + context.payload.pull_request.body.includes("BREAKING CHANGES") || + context.payload.pull_request.body.includes("Features") + ) { + console.log( "Not auto-releasing since it is not a dependency-update-only release." ); + return; + } + + const promise = github.pulls.list.endpoint({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open' + }); + const open_pulls = await github.paginate(promise) + + if ( open_pulls.length > 1 && !context.payload.pull_request.title.includes("SNAPSHOT") ) { + for ( const pull of open_pulls ) { + if ( pull.title.startsWith("deps: update dependency") ) { + console.log( "Not auto-releasing yet since there are dependency update PRs open in this repo." ); + return; + } + } + } + + // approve release PR + await github.pulls.createReview({ + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Rubber stamped release!', + pull_number: context.payload.pull_request.number, + event: 'APPROVE' + }); + + // attach kokoro:force-run and automerge labels + await github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ['kokoro:force-run', 'automerge'] + }); \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 6982bb6e84cb..181da27ccb70 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "b5a7cb875718f88d66f6e717058706dd499e4fac" + "sha": "386d65d05dafa6092a34c834467df180ad386e2e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "019c7168faa0e56619f792693a8acdb30d6de19b" + "sha": "538a68019eb4a36a0cdfa4021f324dd01b784395" } } ], @@ -23,6 +23,7 @@ ".github/PULL_REQUEST_TEMPLATE.md", ".github/release-please.yml", ".github/trusted-contribution.yml", + ".github/workflows/auto-release.yaml", ".github/workflows/ci.yaml", ".github/workflows/samples.yaml", ".kokoro/build.bat", From baa570cad77059b77646bdf148f0231d0a329e62 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 21 Sep 2020 22:26:04 +0000 Subject: [PATCH 0206/1979] chore: release 1.17.1 (#204) :robot: I have created a release \*beep\* \*boop\* --- ### [1.17.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.0...v1.17.1) (2020-09-21) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v0.9.0 ([#199](https://www.github.com/googleapis/java-spanner-jdbc/issues/199)) ([5393942](https://www.github.com/googleapis/java-spanner-jdbc/commit/5393942528870a5af5f855a561fe555b3b79e835)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 287047b61165..83d63b6603ca 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.17.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.0...v1.17.1) (2020-09-21) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.9.0 ([#199](https://www.github.com/googleapis/java-spanner-jdbc/issues/199)) ([59a7d07](https://www.github.com/googleapis/java-spanner-jdbc/commit/59a7d07c284210033bd1d587b09c44d9c271a52e)) + ## [1.17.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.16.0...v1.17.0) (2020-09-04) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 12825ec87eb4..0c6d51ea2af7 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -11,16 +11,16 @@ If you are using Maven, add this to your pom.xml file com.google.cloud google-cloud-spanner-jdbc - 1.17.0 + 1.17.1 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.1" ``` [//]: # ({x-version-update-end}) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 18b278398f1c..a02a413d93c6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.1-SNAPSHOT + 1.17.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 284ecefade18..478be55741cc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.1-SNAPSHOT + 1.17.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f2b71aa2d888..ce335643e50b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.0:1.17.1-SNAPSHOT +google-cloud-spanner-jdbc:1.17.1:1.17.1 From d1a0db6a271fdee73b4b291f372045933ef91ed9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2020 08:22:04 +0000 Subject: [PATCH 0207/1979] chore: release 1.17.2-SNAPSHOT (#209) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a02a413d93c6..532f044c957b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.1 + 1.17.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 478be55741cc..055b296af321 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.1 + 1.17.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ce335643e50b..4892c9a21bca 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.1:1.17.1 +google-cloud-spanner-jdbc:1.17.1:1.17.2-SNAPSHOT From ed21e9121aa291214ff419de3a7de40ab0981896 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 22 Sep 2020 13:00:13 -0700 Subject: [PATCH 0208/1979] chore(java): set yoshi-java as default CODEOWNER (#210) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/1659e5a3-ce7a-4440-8e7f-0dc13b0c12fa/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/80003a3de2d8a75f5b47cb2e77e018f7f0f776cc --- java-spanner-jdbc/.github/CODEOWNERS | 2 ++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index 6137bef2a259..30fdb7b9c8f7 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -4,5 +4,7 @@ # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax +* @googleapis/yoshi-java + # The java-samples-reviewers team is the default owner for samples changes samples/**/*.java @googleapis/java-samples-reviewers diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 181da27ccb70..04f0d3201edf 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "386d65d05dafa6092a34c834467df180ad386e2e" + "sha": "3092bc79cebb816dbf0fd1489f56153a8c51e6a0" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "538a68019eb4a36a0cdfa4021f324dd01b784395" + "sha": "80003a3de2d8a75f5b47cb2e77e018f7f0f776cc" } } ], From 4751be088efc3c15ac293d953e446434757c2386 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 23 Sep 2020 22:52:10 +0200 Subject: [PATCH 0209/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.10.0 (#219) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.9.0` -> `0.10.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.10.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0100-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare091v0100-2020-09-23) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.9.1...v0.10.0) ##### Features - manage error-prone version ([#​147](https://www.github.com/googleapis/java-shared-dependencies/issues/147)) ([0fb3108](https://www.github.com/googleapis/java-shared-dependencies/commit/0fb3108c96abcdef83b5051e842530e6c9934c37)) ##### Dependencies - update google.core.version to v1.93.9 ([#​148](https://www.github.com/googleapis/java-shared-dependencies/issues/148)) ([b2a680e](https://www.github.com/googleapis/java-shared-dependencies/commit/b2a680ec9297136dceb622463672cc554359ba5b)) ##### [0.9.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.9.0...v0.9.1) (2020-09-23) ##### Dependencies - update dependency io.grpc:grpc-bom to v1.32.1 ([#​133](https://www.github.com/googleapis/java-shared-dependencies/issues/133)) ([cde0463](https://www.github.com/googleapis/java-shared-dependencies/commit/cde0463dd15c2a510085a3d5e3ac7b418c2fc3d4)) - update iam.version to v1.0.1 ([#​136](https://www.github.com/googleapis/java-shared-dependencies/issues/136)) ([162e2bd](https://www.github.com/googleapis/java-shared-dependencies/commit/162e2bda35fc3427ce571c6747aae4c9eb5866f6)) ### [`v0.9.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​091-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare090v091-2020-09-23) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.9.0...v0.9.1)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 532f044c957b..c36fd5b1c061 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.9.0 + 0.10.0 pom import From 25bed34b611c7743fcd485e580ce4de9d450d5a8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 23 Sep 2020 15:46:19 -0700 Subject: [PATCH 0210/1979] build(java): use yoshi-approver token for auto-approve (#221) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/24b2f5f7-a563-4efc-b279-c0403f4fd854/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/916c10e8581804df2b48a0f0457d848f3faa582e --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 4 ++-- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index d26427e468a4..c8494910553a 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/github-script@v3.0.0 with: - github-token: ${{secrets.GITHUB_TOKEN}} + github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true script: | // only approve PRs from release-please[bot] @@ -66,4 +66,4 @@ jobs: repo: context.repo.repo, issue_number: context.payload.pull_request.number, labels: ['kokoro:force-run', 'automerge'] - }); \ No newline at end of file + }); diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 04f0d3201edf..b0b2d434d87a 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3092bc79cebb816dbf0fd1489f56153a8c51e6a0" + "sha": "0ab5c5b5bee3324cb641f0505068ff99bf3d204d" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "80003a3de2d8a75f5b47cb2e77e018f7f0f776cc" + "sha": "916c10e8581804df2b48a0f0457d848f3faa582e" } } ], From aaac5a32a18511b4e746122f57db885985dae6fe Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 24 Sep 2020 19:46:13 +0200 Subject: [PATCH 0211/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v11 (#223) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `10.1.0` -> `11.0.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c36fd5b1c061..50bd5bf20520 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 10.1.0 + 11.0.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 8f9cd29bb02e..63ae755bac40 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 10.1.0 + 11.0.0 pom import From b1c271db531cf9862303d6b48516cc7d84b30b8a Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 24 Sep 2020 14:00:39 -0700 Subject: [PATCH 0212/1979] chore: add repo settings configuration (#222) --- .../.github/sync-repo-settings.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 java-spanner-jdbc/.github/sync-repo-settings.yaml diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml new file mode 100644 index 000000000000..6bddd18eac90 --- /dev/null +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -0,0 +1,49 @@ + +# Whether or not rebase-merging is enabled on this repository. +# Defaults to `true` +rebaseMergeAllowed: false + +# Whether or not squash-merging is enabled on this repository. +# Defaults to `true` +squashMergeAllowed: true + +# Whether or not PRs are merged with a merge commit on this repository. +# Defaults to `false` +mergeCommitAllowed: false + +# Rules for master branch protection +branchProtectionRules: +# Identifies the protection rule pattern. Name of the branch to be protected. +# Defaults to `master` +- pattern: master + # Can admins overwrite branch protection. + # Defaults to `true` + isAdminEnforced: true + # Number of approving reviews required to update matching branches. + # Defaults to `1` + requiredApprovingReviewCount: 1 + # Are reviews from code owners required to update matching branches. + # Defaults to `false` + requiresCodeOwnerReviews: true + # Require up to date branches + requiresStrictStatusChecks: false + # List of required status check contexts that must pass for commits to be accepted to matching branches. + requiredStatusCheckContexts: + - "dependencies (8)" + - "dependencies (11)" + - "linkage-monitor" + - "lint" + - "clirr" + - "units (7)" + - "units (8)" + - "units (11)" + - "Kokoro - Test: Integration" + - "cla/google" +# List of explicit permissions to add (additive only) +permissionRules: +- team: yoshi-admins + permission: admin +- team: yoshi-java-admins + permission: admin +- team: yoshi-java + permission: push \ No newline at end of file From f1421f50c362b766390be9dd33d97ff93ec58182 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 25 Sep 2020 08:52:08 -0700 Subject: [PATCH 0213/1979] chore(ci): skip autorelease workflow on non-release PRs (#225) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/cb8e9e40-1c94-4237-af69-70f70fdb6d3a/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/95dbe1bee3c7f7e52ddb24a54c37080620e0d1a2 --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 1 + java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index c8494910553a..3ce51eeea78d 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -4,6 +4,7 @@ name: auto-release jobs: approve: runs-on: ubuntu-latest + if: contains(github.head_ref, 'release-v') steps: - uses: actions/github-script@v3.0.0 with: diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index b0b2d434d87a..c7f454878231 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "0ab5c5b5bee3324cb641f0505068ff99bf3d204d" + "sha": "ecd35a542cfbcf6587adc2b9bea82724b74df576" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "916c10e8581804df2b48a0f0457d848f3faa582e" + "sha": "95dbe1bee3c7f7e52ddb24a54c37080620e0d1a2" } } ], From 1a3e4d5e97c183ab5da0976c7d29b7eedf2dd71a Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 25 Sep 2020 17:36:15 -0700 Subject: [PATCH 0214/1979] chore(ci): verify autorelease release PR content has changes (#226) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/4d7892ee-6265-4e89-b8a8-1c509f6b7076/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/da29da32b3a988457b49ae290112b74f14b713cc --- .../.github/workflows/auto-release.yaml | 18 ++++++++++++++++++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 3ce51eeea78d..bc1554aecba2 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -21,6 +21,24 @@ jobs: return; } + // only approve PRs with pom.xml and versions.txt changes + const filesPromise = github.pulls.listFiles.endpoint({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + }); + const changed_files = await github.paginate(filesPromise) + + if ( changed_files.length < 1 ) { + console.log( "Not proceeding since PR is empty!" ) + return; + } + + if ( !changed_files.some(v => v.filename.includes("pom")) || !changed_files.some(v => v.filename.includes("versions.txt")) ) { + console.log( "PR file changes do not have pom.xml or versions.txt -- something is wrong. PTAL!" ) + return; + } + // trigger auto-release when // 1) it is a SNAPSHOT release (auto-generated post regular release) // 2) there are dependency updates only diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index c7f454878231..d12790ea0710 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ecd35a542cfbcf6587adc2b9bea82724b74df576" + "sha": "3583c5f7d3b5d739fd6bfe78baad5ea5236b38a0" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "95dbe1bee3c7f7e52ddb24a54c37080620e0d1a2" + "sha": "da29da32b3a988457b49ae290112b74f14b713cc" } } ], From b8ef1203d21b7c6b49a8c08290d47c7c658e739a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 2 Oct 2020 18:52:06 +0200 Subject: [PATCH 0215/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.21 (#224) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud.samples:shared-configuration](com/google/cloud/samples/shared-configuration) | patch | `1.0.18` -> `1.0.21` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 978869ab23e1..222446e5fb21 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.18 + 1.0.21 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index a2399748cf50..13432e5e892c 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.18 + 1.0.21 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 055b296af321..2969fb4171c7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.18 + 1.0.21 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 63ae755bac40..2b9ebb56bfaa 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.18 + 1.0.21 From 8eec35118bd6d06acb6438e9731b62e0b1010838 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 6 Oct 2020 22:08:11 +0200 Subject: [PATCH 0216/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v12 (#229) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `11.0.0` -> `12.0.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 50bd5bf20520..b194b1353485 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud libraries-bom - 11.0.0 + 12.0.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2b9ebb56bfaa..ed37291ca5d1 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 11.0.0 + 12.0.0 pom import From ba2556345048fb726f54c89bbfc5c0eab8201403 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 12 Oct 2020 18:59:04 +0200 Subject: [PATCH 0217/1979] test(deps): update dependency junit:junit to v4.13.1 --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 222446e5fb21..4df7db512752 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -36,7 +36,7 @@ junit junit - 4.13 + 4.13.1 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2969fb4171c7..d0409a9c41a3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -35,7 +35,7 @@ junit junit - 4.13 + 4.13.1 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ed37291ca5d1..dc2f39a9a7f4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -47,7 +47,7 @@ junit junit - 4.13 + 4.13.1 test From 1b354a5803a7468a81a11329796efcb690f43f37 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 15 Oct 2020 11:43:54 +0200 Subject: [PATCH 0218/1979] deps: update dependency junit:junit to v4.13.1 (#232) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b194b1353485..183f759a06ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 4.13 + 4.13.1 3.0.2 1.4.4 1.0.1 From 21272297a9707593748c72271b35fe63ba8598a1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 16 Oct 2020 18:14:47 +0200 Subject: [PATCH 0219/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.9.3 (#236) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | patch | `0.9.2` -> `0.9.3` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.9.3`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​093-httpswwwgithubcomgoogleapisjava-shared-configcomparev092v093-2020-10-15) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.9.2...v0.9.3)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 183f759a06ef..7509f42cf816 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.9.2 + 0.9.3 From e1401969ac58d1e8c27acc4f79adc1e996962c1b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 20 Oct 2020 15:46:23 -0700 Subject: [PATCH 0220/1979] chore: regenerate common templates (#231) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/319da543-d501-47a9-96ec-0267776604c9/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/0762e8ee2ec21cdfc4d82020b985a104feb0453b Source-Link: https://github.com/googleapis/synthtool/commit/8a7a3021fe97aa0a3641db642fe2b767f1c8110f Source-Link: https://github.com/googleapis/synthtool/commit/e6168630be3e31eede633ba2c6f1cd64248dec1c --- java-spanner-jdbc/.github/readme/synth.py | 19 +++++++ .../.github/workflows/samples.yaml | 2 +- .../.kokoro/continuous/readme.cfg | 55 +++++++++++++++++++ java-spanner-jdbc/.kokoro/readme.sh | 36 ++++++++++++ java-spanner-jdbc/synth.metadata | 7 ++- 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 java-spanner-jdbc/.github/readme/synth.py create mode 100644 java-spanner-jdbc/.kokoro/continuous/readme.cfg create mode 100755 java-spanner-jdbc/.kokoro/readme.sh diff --git a/java-spanner-jdbc/.github/readme/synth.py b/java-spanner-jdbc/.github/readme/synth.py new file mode 100644 index 000000000000..7b48cc28d361 --- /dev/null +++ b/java-spanner-jdbc/.github/readme/synth.py @@ -0,0 +1,19 @@ +# Copyright 2020 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. + +"""This script is used to synthesize generated the README for this library.""" + +from synthtool.languages import java + +java.custom_templates(["java_library/README.md"]) diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index a1d50073069d..c46230a78c38 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -2,7 +2,7 @@ on: pull_request: name: samples jobs: - lint: + checkstyle: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/java-spanner-jdbc/.kokoro/continuous/readme.cfg b/java-spanner-jdbc/.kokoro/continuous/readme.cfg new file mode 100644 index 000000000000..8c130dec7700 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/readme.cfg @@ -0,0 +1,55 @@ +# Copyright 2020 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. + +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/readme.sh" +} + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.log" + } +} + +# The github token is stored here. +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "yoshi-automation-github-key" + # TODO(theacodes): remove this after secrets have globally propagated + backend_type: FASTCONFIGPUSH + } + } +} + +# Common env vars for all repositories and builds. +env_vars: { + key: "GITHUB_USER" + value: "yoshi-automation" +} +env_vars: { + key: "GITHUB_EMAIL" + value: "yoshi-automation@google.com" +} diff --git a/java-spanner-jdbc/.kokoro/readme.sh b/java-spanner-jdbc/.kokoro/readme.sh new file mode 100755 index 000000000000..0bd5ca59731c --- /dev/null +++ b/java-spanner-jdbc/.kokoro/readme.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Copyright 2020 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. + +set -eo pipefail + +cd ${KOKORO_ARTIFACTS_DIR}/github/java-spanner-jdbc + +# Disable buffering, so that the logs stream through. +export PYTHONUNBUFFERED=1 + +# Kokoro exposes this as a file, but the scripts expect just a plain variable. +export GITHUB_TOKEN=$(cat ${KOKORO_KEYSTORE_DIR}/73713_yoshi-automation-github-key) + +# Setup git credentials +echo "https://${GITHUB_TOKEN}:@github.com" >> ~/.git-credentials +git config --global credential.helper 'store --file ~/.git-credentials' + +python3.6 -m pip install git+https://github.com/googleapis/synthtool.git#egg=gcp-synthtool +python3.6 -m autosynth.synth \ + --repository=googleapis/java-spanner-jdbc \ + --synth-file-name=.github/readme/synth.py \ + --metadata-path=.github/readme/synth.metadata \ + --pr-title="chore: regenerate README" \ + --branch-suffix="readme" \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index d12790ea0710..352e0cc92da2 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3583c5f7d3b5d739fd6bfe78baad5ea5236b38a0" + "sha": "5c63dfe391360fb00e92e6ebeedb3ce2cfc2ff62" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "da29da32b3a988457b49ae290112b74f14b713cc" + "sha": "0762e8ee2ec21cdfc4d82020b985a104feb0453b" } } ], @@ -21,6 +21,7 @@ ".github/ISSUE_TEMPLATE/feature_request.md", ".github/ISSUE_TEMPLATE/support_request.md", ".github/PULL_REQUEST_TEMPLATE.md", + ".github/readme/synth.py", ".github/release-please.yml", ".github/trusted-contribution.yml", ".github/workflows/auto-release.yaml", @@ -33,6 +34,7 @@ ".kokoro/common.sh", ".kokoro/continuous/common.cfg", ".kokoro/continuous/java8.cfg", + ".kokoro/continuous/readme.cfg", ".kokoro/dependencies.sh", ".kokoro/linkage-monitor.sh", ".kokoro/nightly/common.cfg", @@ -56,6 +58,7 @@ ".kokoro/presubmit/linkage-monitor.cfg", ".kokoro/presubmit/lint.cfg", ".kokoro/presubmit/samples.cfg", + ".kokoro/readme.sh", ".kokoro/release/bump_snapshot.cfg", ".kokoro/release/common.cfg", ".kokoro/release/common.sh", From 84353c2c63431ac228705cb98803a64211f5cf38 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 22 Oct 2020 10:26:27 -0700 Subject: [PATCH 0221/1979] chore: regenerate common templates (#242) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/fc1413bf-7539-42ca-a3cb-6a8d29e26892/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/6abb59097be84599a1d6091fe534a49e5c5cf948 Source-Link: https://github.com/googleapis/synthtool/commit/5a506ec8765cc04f7e29f888b8e9b257d9a7ae11 Source-Link: https://github.com/googleapis/synthtool/commit/7c5370937dd9ba9dcf9cd7d2af880a58b389b4f1 Source-Link: https://github.com/googleapis/synthtool/commit/27e0e916cbfdb3d5ff6639b686cc04f78a0b0386 Source-Link: https://github.com/googleapis/synthtool/commit/b65ef07d99946d23e900ef2cc490274a16edd336 --- java-spanner-jdbc/.github/snippet-bot.yml | 0 .../.github/workflows/approve-readme.yaml | 54 +++++++++++++++++++ .../.github/workflows/formatting.yaml | 25 +++++++++ java-spanner-jdbc/.kokoro/build.sh | 11 +++- java-spanner-jdbc/renovate.json | 30 ++++------- java-spanner-jdbc/synth.metadata | 7 ++- 6 files changed, 104 insertions(+), 23 deletions(-) create mode 100644 java-spanner-jdbc/.github/snippet-bot.yml create mode 100644 java-spanner-jdbc/.github/workflows/approve-readme.yaml create mode 100644 java-spanner-jdbc/.github/workflows/formatting.yaml diff --git a/java-spanner-jdbc/.github/snippet-bot.yml b/java-spanner-jdbc/.github/snippet-bot.yml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml new file mode 100644 index 000000000000..e2d841d6c5a0 --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -0,0 +1,54 @@ +on: + pull_request: +name: auto-merge-readme +jobs: + approve: + runs-on: ubuntu-latest + if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' + steps: + - uses: actions/github-script@v3.0.0 + with: + github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} + script: | + // only approve PRs from yoshi-automation + if (context.payload.pull_request.user.login !== "yoshi-automation") { + return; + } + + // only approve PRs like "chore: release " + if (!context.payload.pull_request.title === "chore: regenerate README") { + return; + } + + // only approve PRs with README.md and synth.metadata changes + const files = new Set( + ( + await github.paginate( + github.pulls.listFiles.endpoint({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + }) + ) + ).map(file => file.filename) + ); + if (files.size != 2 || !files.has("README.md") || !files.has(".github/readme/synth.metadata/synth.metadata")) { + return; + } + + // approve README regeneration PR + await github.pulls.createReview({ + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Rubber stamped PR!', + pull_number: context.payload.pull_request.number, + event: 'APPROVE' + }); + + // attach automerge label + await github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ['automerge'] + }); diff --git a/java-spanner-jdbc/.github/workflows/formatting.yaml b/java-spanner-jdbc/.github/workflows/formatting.yaml new file mode 100644 index 000000000000..d4d367cfce03 --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/formatting.yaml @@ -0,0 +1,25 @@ +on: + pull_request_target: + types: [opened, synchronize] + branches: + - master +name: format +jobs: + format-code: + runs-on: ubuntu-latest + env: + ACCESS_TOKEN: ${{ secrets.YOSHI_CODE_BOT_TOKEN }} + steps: + - uses: actions/checkout@v2 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + - uses: actions/setup-java@v1 + with: + java-version: 11 + - run: "mvn com.coveo:fmt-maven-plugin:format" + - uses: googleapis/code-suggester@v1.8.0 + with: + command: review + pull_number: ${{ github.event.pull_request.number }} + git_dir: '.' diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index efe91569c97d..89171e36691e 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -69,9 +69,16 @@ integration) RETURN_CODE=$? ;; samples) - if [[ -f samples/pom.xml ]] + SAMPLES_DIR=samples + # only run ITs in snapshot/ on presubmit PRs. run ITs in all 3 samples/ subdirectories otherwise. + if [[ ! -z ${KOKORO_GITHUB_PULL_REQUEST_NUMBER} ]] then - pushd samples + SAMPLES_DIR=samples/snapshot + fi + + if [[ -f ${SAMPLES_DIR}/pom.xml ]] + then + pushd {SAMPLES_DIR} mvn -B \ -Penable-samples \ -DtrimStackTrace=false \ diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 0fd3e3fc8395..4ac4d97c635c 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -17,24 +17,6 @@ ], "versionScheme": "docker" }, - { - "packagePatterns": [ - "^com.google.api:gax", - "^com.google.auth:", - "^com.google.cloud:google-cloud-core", - "^io.grpc:", - "^com.google.guava:" - ], - "groupName": "core dependencies" - }, - { - "packagePatterns": [ - "^com.google.http-client:", - "^com.google.oauth-client:", - "^com.google.api-client:" - ], - "groupName": "core transport dependencies" - }, { "packagePatterns": [ "*" @@ -63,6 +45,16 @@ "semanticCommitType": "chore", "semanticCommitScope": "deps" }, + { + "packagePatterns": [ + "^junit:junit", + "^com.google.truth:truth", + "^org.mockito:mockito-core", + "^org.objenesis:objenesis" + ], + "semanticCommitType": "test", + "semanticCommitScope": "deps" + }, { "packagePatterns": [ "^com.google.cloud:google-cloud-" @@ -78,4 +70,4 @@ ], "semanticCommits": true, "masterIssue": true -} \ No newline at end of file +} diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 352e0cc92da2..37966bd76ad4 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "5c63dfe391360fb00e92e6ebeedb3ce2cfc2ff62" + "sha": "03f85578270816cdbcafa480bbf69e2fa9775dc5" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "0762e8ee2ec21cdfc4d82020b985a104feb0453b" + "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" } } ], @@ -23,9 +23,12 @@ ".github/PULL_REQUEST_TEMPLATE.md", ".github/readme/synth.py", ".github/release-please.yml", + ".github/snippet-bot.yml", ".github/trusted-contribution.yml", + ".github/workflows/approve-readme.yaml", ".github/workflows/auto-release.yaml", ".github/workflows/ci.yaml", + ".github/workflows/formatting.yaml", ".github/workflows/samples.yaml", ".kokoro/build.bat", ".kokoro/build.sh", From 322e4bfa6b40316ec73f97a292abf2e9bdc60a94 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 22 Oct 2020 11:06:13 -0700 Subject: [PATCH 0222/1979] chore: regenerate README (#241) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-10-20 22:51:24,900 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working directory clean 2020-10-20 22:51:25,803 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/39f46d83-6672-485b-8a06-7b8c7725b896/targets - [ ] To automatically regenerate this PR, check this box. --- .../readme/synth.metadata/synth.metadata | 18 ++ java-spanner-jdbc/README.md | 154 ++++++++++-------- 2 files changed, 104 insertions(+), 68 deletions(-) create mode 100644 java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata new file mode 100644 index 000000000000..bd17a694b7d1 --- /dev/null +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -0,0 +1,18 @@ +{ + "sources": [ + { + "git": { + "name": ".", + "remote": "https://github.com/googleapis/java-spanner-jdbc.git", + "sha": "03f85578270816cdbcafa480bbf69e2fa9775dc5" + } + }, + { + "git": { + "name": "synthtool", + "remote": "https://github.com/googleapis/synthtool.git", + "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + } + } + ] +} \ No newline at end of file diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0c6d51ea2af7..3bbc9076243d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -1,112 +1,130 @@ -# JDBC Driver for Google Cloud Spanner +# Google Google Cloud Spanner JDBC Client for Java -JDBC Driver for -[Google Cloud Spanner](https://cloud.google.com/spanner/). +Java idiomatic client for [Google Cloud Spanner JDBC][product-docs]. + +[![Maven][maven-version-image]][maven-version-link] +![Stability][stability-image] + +- [Product Documentation][product-docs] +- [Client Library Documentation][javadocs] ## Quickstart -[//]: # ({x-version-update-start:google-cloud-spanner-jdbc:released}) -If you are using Maven, add this to your pom.xml file + +If you are using Maven, add this to your pom.xml file: + ```xml com.google.cloud google-cloud-spanner-jdbc - 1.17.1 + 1.17.0 ``` + If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.1' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.0" ``` -[//]: # ({x-version-update-end}) + +## Authentication + +See the [Authentication][authentication] section in the base directory's README. ## Getting Started -You can access Google Cloud Spanner through JDBC like this: - -```java -String url = "jdbc:cloudspanner:/projects/my_project_id/" - + "instances/my_instance_id/" - + "databases/my_database_name" - + "?credentials=/home/cloudspanner-keys/my-key.json" - + ";autocommit=false"; -try (Connection connection = DriverManager.getConnection(url)) { - try(ResultSet rs = connection.createStatement() - .executeQuery("SELECT SingerId, AlbumId, MarketingBudget FROM Albums")) { - while(rs.next()) { - Long singerId = rs.getLong(1); - } - } -} -``` -### Connection URL -The JDBC connection URL must be specified in the following format: +### Prerequisites -``` -jdbc:cloudspanner:[//host[:port]]/projects/project-id[/instances/instance-id[/databases/database-name]][\?property-name=property-value[;property-name=property-value]*]? -``` +You will need a [Google Cloud Platform Console][developer-console] project with the Google Cloud Spanner JDBC [API enabled][enable-api]. -The property-value strings should be url-encoded. +[Follow these instructions][create-project] to get your project set up. You will also need to set up the local development environment by +[installing the Google Cloud SDK][cloud-sdk] and running the following commands in command line: +`gcloud auth login` and `gcloud config set project [YOUR PROJECT ID]`. -The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This -placeholder will be replaced by the default project id of the environment that is requesting a -connection. -The supported connection properties are: +### Installation and setup -* credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials, the default credentials of the environment as returned by {@link GoogleCredentials#getApplicationDefault()} will be used. -* autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. -* readonly (boolean): Sets the initial readonly mode for the connection. Default is false. -* retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the connection. Default is true. See -CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean) for more information. +You'll need to obtain the `google-cloud-spanner-jdbc` library. See the [Quickstart](#quickstart) section +to add `google-cloud-spanner-jdbc` as a dependency in your code. -### Authentication -The JDBC Driver will either use the credentials that are specified in the connection URL, or if none specified, the default credentials of the environment. +## About Google Cloud Spanner JDBC -See the -[Authentication](https://github.com/googleapis/google-cloud-java#authentication) -section in the base directory's README for more information. -## Shaded JAR +[Google Cloud Spanner JDBC][product-docs] -You can build a shaded JAR of the JDBC Driver to use with third-party tools using the following command: +See the [Google Cloud Spanner JDBC client library docs][javadocs] to learn how to +use this Google Cloud Spanner JDBC Client Library. -``` -mvn package -Pbuild-jdbc-driver -``` + + + + + +## Troubleshooting + +To get help, follow the instructions in the [shared Troubleshooting document][troubleshooting]. ## Java Versions -Java 7 or above is required for using this JDBC Driver. +Java 7 or above is required for using this client. ## Versioning + This library follows [Semantic Versioning](http://semver.org/). + ## Contributing + Contributions to this library are always welcome and highly encouraged. -See `google-cloud`'s [CONTRIBUTING] documentation and the -[shared documentation](https://github.com/googleapis/google-cloud-common/blob/master/contributing/readme.md#how-to-contribute-to-gcloud) -for more information on how to get started. +See [CONTRIBUTING][contributing] for more information how to get started. -Please note that this project is released with a Contributor Code of Conduct. -By participating in this project you agree to abide by its terms. See -[Code of Conduct][code-of-conduct] for more information. +Please note that this project is released with a Contributor Code of Conduct. By participating in +this project you agree to abide by its terms. See [Code of Conduct][code-of-conduct] for more +information. ## License -Apache 2.0 - See [LICENSE] for more information. - - -[CONTRIBUTING]:https://github.com/googleapis/google-cloud-java/blob/master/CONTRIBUTING.md -[code-of-conduct]:https://github.com/googleapis/google-cloud-java/blob/master/CODE_OF_CONDUCT.md#contributor-code-of-conduct -[LICENSE]: https://github.com/googleapis/google-cloud-java/blob/master/LICENSE -[cloud-platform]: https://cloud.google.com/ - -[cloud-spanner]: https://cloud.google.com/spanner/ -[cloud-spanner-docs]: https://cloud.google.com/spanner/docs/overview +Apache 2.0 - See [LICENSE][license] for more information. + +## CI Status + +Java Version | Status +------------ | ------ +Java 7 | [![Kokoro CI][kokoro-badge-image-1]][kokoro-badge-link-1] +Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2] +Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] +Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] +Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] + +[product-docs]: https://cloud.google.com/pubsub/docs/ +[javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html +[kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg +[kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.html +[kokoro-badge-image-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8.svg +[kokoro-badge-link-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8.html +[kokoro-badge-image-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-osx.svg +[kokoro-badge-link-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-osx.html +[kokoro-badge-image-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-win.svg +[kokoro-badge-link-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-win.html +[kokoro-badge-image-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java11.svg +[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java11.html +[stability-image]: https://img.shields.io/badge/stability-ga-green +[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner-jdbc.svg +[maven-version-link]: https://search.maven.org/search?q=g:com.google.cloud%20AND%20a:google-cloud-spanner-jdbc&core=gav +[authentication]: https://github.com/googleapis/google-cloud-java#authentication +[developer-console]: https://console.developers.google.com/ +[create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects +[cloud-sdk]: https://cloud.google.com/sdk/ +[troubleshooting]: https://github.com/googleapis/google-cloud-common/blob/master/troubleshooting/readme.md#troubleshooting +[contributing]: https://github.com/googleapis/java-spanner-jdbc/blob/master/CONTRIBUTING.md +[code-of-conduct]: https://github.com/googleapis/java-spanner-jdbc/blob/master/CODE_OF_CONDUCT.md#contributor-code-of-conduct +[license]: https://github.com/googleapis/java-spanner-jdbc/blob/master/LICENSE + + +[libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM +[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png From acb5d32c2c5ec10b0272e35a4da8b926dd0417d5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 22 Oct 2020 21:36:33 +0200 Subject: [PATCH 0223/1979] test(deps): update dependency com.google.truth:truth to v1.1 (#240) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.truth:truth](com/google/truth/truth) | minor | `1.0.1` -> `1.1` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 4df7db512752..72e625fbd93f 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.0.1 + 1.1 test
    diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d0409a9c41a3..346dfe62138f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.0.1 + 1.1 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index dc2f39a9a7f4..a43f36d0d57a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.0.1 + 1.1 test From b621f767eb43b8ec4c0fbed5fb2ac07ad1176e63 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 26 Oct 2020 16:52:17 -0700 Subject: [PATCH 0224/1979] chore: regenerate common templates (#243) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/40fd65e9-4f88-4269-b3f6-e2cfea7f2b3e/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/5f6ef0ec5501d33c4667885b37a7685a30d41a76 Source-Link: https://github.com/googleapis/synthtool/commit/9593c3b5b714cc9b17c445aee8834ac2b4b9348b --- java-spanner-jdbc/.kokoro/release/publish_javadoc.sh | 2 +- java-spanner-jdbc/CODE_OF_CONDUCT.md | 7 ++++--- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index d558f50925ff..3c87c1b7f8f4 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -62,7 +62,7 @@ popd # V2 mvn clean site -B -q -Ddevsite.template="${KOKORO_GFILE_DIR}/java/" -pushd target/devsite +pushd target/devsite/reference # create metadata python3 -m docuploader create-metadata \ diff --git a/java-spanner-jdbc/CODE_OF_CONDUCT.md b/java-spanner-jdbc/CODE_OF_CONDUCT.md index 6b2238bb75e0..2add2547a812 100644 --- a/java-spanner-jdbc/CODE_OF_CONDUCT.md +++ b/java-spanner-jdbc/CODE_OF_CONDUCT.md @@ -1,3 +1,4 @@ + # Code of Conduct ## Our Pledge @@ -69,12 +70,12 @@ dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. -Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the -Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to +Reports should be directed to *googleapis-stewards@google.com*, the +Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the Open Source Programs Office and the Google Open Source Strategy team. If for any reason you -are uncomfortable reaching out the Project Steward, please email +are uncomfortable reaching out to the Project Steward, please email opensource@google.com. We will investigate every complaint, but you may not receive a direct response. diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 37966bd76ad4..9963f829b911 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "03f85578270816cdbcafa480bbf69e2fa9775dc5" + "sha": "56fd1290b2430a81dd5c4a44c942c5cc2659e1ca" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + "sha": "5f6ef0ec5501d33c4667885b37a7685a30d41a76" } } ], From 2ef8f897ebbfa49567f47a3f0c7285e7b899f72f Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 27 Oct 2020 11:06:14 -0700 Subject: [PATCH 0225/1979] chore(ci): fix typo in restrict presubmit samples ITs to only snapshot (#244) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/5893004d-fa83-442b-abe3-609b1bb3357f/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/f68649c5f26bcff6817c6d21e90dac0fc71fef8e --- java-spanner-jdbc/.kokoro/build.sh | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 89171e36691e..b4005cc6879f 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -78,7 +78,7 @@ samples) if [[ -f ${SAMPLES_DIR}/pom.xml ]] then - pushd {SAMPLES_DIR} + pushd ${SAMPLES_DIR} mvn -B \ -Penable-samples \ -DtrimStackTrace=false \ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 9963f829b911..d1f78842421c 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "56fd1290b2430a81dd5c4a44c942c5cc2659e1ca" + "sha": "66fc72c1ae967bf7608000c1f008f83c55cd8ab5" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5f6ef0ec5501d33c4667885b37a7685a30d41a76" + "sha": "f68649c5f26bcff6817c6d21e90dac0fc71fef8e" } } ], From 6eef3d6c3108e315cde07dbb67fe9e674c937613 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 27 Oct 2020 20:24:11 +0100 Subject: [PATCH 0226/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.9.4 (#245) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | patch | `0.9.3` -> `0.9.4` | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.9.4`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​094-httpswwwgithubcomgoogleapisjava-shared-configcomparev093v094-2020-10-21) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.9.3...v0.9.4)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7509f42cf816..0340dd9c2fc3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.9.3 + 0.9.4 From 934729edbccb61d57b53804343555e77b8df7504 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Thu, 29 Oct 2020 12:22:07 +1100 Subject: [PATCH 0227/1979] build: adds api-spanner-java team as owners (#246) Adds @googleapis/api-spanner-java as github codeowners. --- java-spanner-jdbc/.github/CODEOWNERS | 2 +- java-spanner-jdbc/.repo-metadata.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index 30fdb7b9c8f7..2e8e575cf78e 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -4,7 +4,7 @@ # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax -* @googleapis/yoshi-java +* @googleapis/yoshi-java @googleapis/api-spanner-java # The java-samples-reviewers team is the default owner for samples changes samples/**/*.java @googleapis/java-samples-reviewers diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index d5b76f2fcd39..fe90fd731d04 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -7,5 +7,6 @@ "language": "java", "repo": "googleapis/java-spanner-jdbc", "repo_short": "java-spanner-jdbc", - "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc" + "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc", + "codeowner_team": "@googleapis/api-spanner-java" } From e4755fe6b25e2e438df1f0728c9839010690a23a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 13:11:49 +1100 Subject: [PATCH 0228/1979] build(deps-dev): bump junit from 4.13 to 4.13.1 (#234) Bumps [junit](https://github.com/junit-team/junit4) from 4.13 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.13...r4.13.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 3d6170a3e3c313c2d04caa9ffc423e38e8c31b3f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2020 11:50:14 +1100 Subject: [PATCH 0229/1979] chore: release 1.17.2 (#220) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 83d63b6603ca..f10983723438 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### [1.17.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.1...v1.17.2) (2020-10-29) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.10.0 ([#219](https://www.github.com/googleapis/java-spanner-jdbc/issues/219)) ([0ab5c5b](https://www.github.com/googleapis/java-spanner-jdbc/commit/0ab5c5b5bee3324cb641f0505068ff99bf3d204d)) +* update dependency junit:junit to v4.13.1 ([#232](https://www.github.com/googleapis/java-spanner-jdbc/issues/232)) ([a6c09d7](https://www.github.com/googleapis/java-spanner-jdbc/commit/a6c09d73d707bece320f59dcab98dfde6802a5b3)) + ### [1.17.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.0...v1.17.1) (2020-09-21) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0340dd9c2fc3..b2b1092d93e4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.2-SNAPSHOT + 1.17.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 346dfe62138f..959886067239 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.2-SNAPSHOT + 1.17.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4892c9a21bca..f61970fd6843 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.1:1.17.2-SNAPSHOT +google-cloud-spanner-jdbc:1.17.2:1.17.2 From 636a6959c60be8dd086724f032edd14be38c6126 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2020 09:22:03 +0000 Subject: [PATCH 0230/1979] chore: release 1.17.3-SNAPSHOT (#249) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b2b1092d93e4..bccc721251c7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.2 + 1.17.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 959886067239..949d10fdd460 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.2 + 1.17.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f61970fd6843..195dd2e84aeb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.2:1.17.2 +google-cloud-spanner-jdbc:1.17.2:1.17.3-SNAPSHOT From 954823fb6c56c6ae9bd16006d406ee8aa454727b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 2 Nov 2020 09:25:43 -0800 Subject: [PATCH 0231/1979] chore: regenerate common templates (#248) * changes without context autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. * chore(java): enable generated-files-bot This bot will comment on pull requests that modify templated files. For java, we configure to read from our 2 synth.metadata files: (primary templates and README) Source-Author: Jeff Ching Source-Date: Fri Oct 30 14:22:02 2020 -0700 Source-Repo: googleapis/synthtool Source-Sha: b19b401571e77192f8dd38eab5fb2300a0de9324 Source-Link: https://github.com/googleapis/synthtool/commit/b19b401571e77192f8dd38eab5fb2300a0de9324 --- java-spanner-jdbc/.github/CODEOWNERS | 2 ++ java-spanner-jdbc/.github/generated-files-bot.yml | 7 +++++++ java-spanner-jdbc/synth.metadata | 5 +++-- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/generated-files-bot.yml diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index 2e8e575cf78e..da6403b346e0 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -4,7 +4,9 @@ # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax +# The @googleapis/api-spanner-java is the default owner for changes in this repo * @googleapis/yoshi-java @googleapis/api-spanner-java +**/*.java @googleapis/api-spanner-java # The java-samples-reviewers team is the default owner for samples changes samples/**/*.java @googleapis/java-samples-reviewers diff --git a/java-spanner-jdbc/.github/generated-files-bot.yml b/java-spanner-jdbc/.github/generated-files-bot.yml new file mode 100644 index 000000000000..20f3acc28172 --- /dev/null +++ b/java-spanner-jdbc/.github/generated-files-bot.yml @@ -0,0 +1,7 @@ +externalManifests: +- type: json + file: 'synth.metadata' + jsonpath: '$.generatedFiles[*]' +- type: json + file: '.github/readme/synth.metadata/synth.metadata' + jsonpath: '$.generatedFiles[*]' diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index d1f78842421c..894c0c308dea 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "66fc72c1ae967bf7608000c1f008f83c55cd8ab5" + "sha": "bdb6d483070018d5b6dac31bbf68ab66bfad5225" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "f68649c5f26bcff6817c6d21e90dac0fc71fef8e" + "sha": "b19b401571e77192f8dd38eab5fb2300a0de9324" } } ], @@ -21,6 +21,7 @@ ".github/ISSUE_TEMPLATE/feature_request.md", ".github/ISSUE_TEMPLATE/support_request.md", ".github/PULL_REQUEST_TEMPLATE.md", + ".github/generated-files-bot.yml", ".github/readme/synth.py", ".github/release-please.yml", ".github/snippet-bot.yml", From 6a105da074bbc2da71636c8d1f7545e34600d232 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 4 Nov 2020 19:56:40 -0800 Subject: [PATCH 0232/1979] chore(java): use production staging bucket (#256) Source-Author: Les Vogel Source-Date: Wed Nov 4 10:18:01 2020 -0800 Source-Repo: googleapis/synthtool Source-Sha: c7824ea48ff6d4d42dfae0849aec8a85acd90bd9 Source-Link: https://github.com/googleapis/synthtool/commit/c7824ea48ff6d4d42dfae0849aec8a85acd90bd9 --- java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index b50b09ee9e35..33cb6e725134 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -9,7 +9,7 @@ env_vars: { env_vars: { key: "STAGING_BUCKET_V2" - value: "docs-staging-v2-staging" + value: "docs-staging-v2" # Production will be at: docs-staging-v2 } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 894c0c308dea..369d94fd8481 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "bdb6d483070018d5b6dac31bbf68ab66bfad5225" + "sha": "c3616a7960d0f544366301464ec6f357b9fdb275" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "b19b401571e77192f8dd38eab5fb2300a0de9324" + "sha": "c7824ea48ff6d4d42dfae0849aec8a85acd90bd9" } } ], From 3f37dafa179689d1a4f980eb98477c1f85912daa Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Fri, 6 Nov 2020 16:28:10 -0500 Subject: [PATCH 0233/1979] deps: use google-cloud-spanner-bom (#258) --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bccc721251c7..4b304c9b3444 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -70,8 +70,8 @@ com.google.cloud - libraries-bom - 12.0.0 + google-cloud-spanner-bom + 2.0.2 pom import From f7bce23507bf1fafee63b5dc10821f135634ef35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 9 Nov 2020 00:08:38 +0100 Subject: [PATCH 0234/1979] chore: remove unused maven profile (#262) This build profile is no longer needed, as it has been moved to the client library together with the general Connection API. --- java-spanner-jdbc/pom.xml | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4b304c9b3444..26a86015613d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -321,41 +321,6 @@ - - - - generate-test-sql-scripts - - - - org.codehaus.mojo - exec-maven-plugin - - - generateTestScripts - compile - - java - - - com.google.cloud.spanner.jdbc.SqlTestScriptsGenerator - - - do_log_statements - true - - - test - false - - - - - - - - From 4a1d16d540b8c4e6facc1caa2386ef1496f6192a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 9 Nov 2020 00:09:22 +0100 Subject: [PATCH 0235/1979] docs: add simple connection sample to readme (#263) Adds a simple code example for connecting to Cloud Spanner using JDBC. Also fixes a wrong link to the online documentation. --- java-spanner-jdbc/README.md | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 3bbc9076243d..00c974a90066 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -58,8 +58,30 @@ See the [Google Cloud Spanner JDBC client library docs][javadocs] to learn how t use this Google Cloud Spanner JDBC Client Library. - - +### Creating a JDBC Connection + +The following example shows how to create a JDBC connection to Cloud Spanner and execute a simple query. + +```java +String projectId = "my-project"; +String instanceId = "my-instance"; +String databaseId = "my-database"; + +try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } +} +``` ## Troubleshooting @@ -101,7 +123,7 @@ Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] -[product-docs]: https://cloud.google.com/pubsub/docs/ +[product-docs]: https://cloud.google.com/spanner/docs/use-oss-jdbc [javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html [kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg [kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.html From f60ad9bf33d3608feaa9753e74a1e14412943633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 9 Nov 2020 00:11:24 +0100 Subject: [PATCH 0236/1979] docs: add package-info to jdbc (#264) * docs: add package-info to jdbc Adds a package-info.java file to the com.google.cloud.spanner.jdbc package, with a simple example for how to create a JDBC connection. * fix: run linter --- .../cloud/spanner/jdbc/package-info.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/package-info.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/package-info.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/package-info.java new file mode 100644 index 000000000000..27e15386b49d --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/package-info.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020 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. + */ + +/** + * A JDBC driver for Cloud Spanner - A no-compromise relational database service. + * + *

    Example for creating a JDBC connection to Cloud Spanner. + * + *

    {@code
    + * String projectId = "my-project";
    + * String instanceId = "my-instance";
    + * String databaseId = "my-database";
    + *
    + * try (Connection connection =
    + *     DriverManager.getConnection(
    + *         String.format(
    + *             "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s",
    + *             projectId, instanceId, databaseId))) {
    + *   try (Statement statement = connection.createStatement()) {
    + *     try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) {
    + *       while (rs.next()) {
    + *         System.out.printf(
    + *             "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString());
    + *       }
    + *     }
    + *   }
    + * }
    + * }
    + * + * @see JdbcDriver + * java doc for all supported connection URL properties. + * @see Cloud Spanner JDBC Driver + */ +package com.google.cloud.spanner.jdbc; From 6fb58bf078a4f4076ffb65131a0fcc7330f15798 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Sun, 8 Nov 2020 18:12:30 -0500 Subject: [PATCH 0237/1979] chore(deps): the libraries BOM 15.0.0 (#251) * chore(deps): libraires-bom 13.4.0 https://github.com/googleapis/java-spanner-jdbc/pull/235 is stale * chore(deps): libraries-bom 13.4.0 * linkage checker and shared deps BOM * the libraries BOM 13.3.0 (1 release behind) * Libraries BOM 15.0.0 --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a43f36d0d57a..c4ec1a86ce7f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 12.0.0 + 15.0.0 pom import From 2d8c1e5b236e28359c33594861063977302d0734 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 8 Nov 2020 15:26:03 -0800 Subject: [PATCH 0238/1979] chore: regenerate README (#265) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-11-08 23:10:41,211 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working directory clean 2020-11-08 23:10:42,077 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/c618af2e-7ed8-4b37-892b-2ac9dc809ab4/targets - [ ] To automatically regenerate this PR, check this box. --- .../readme/synth.metadata/synth.metadata | 4 +-- java-spanner-jdbc/README.md | 28 ++----------------- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index bd17a694b7d1..19ca2958ff12 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "03f85578270816cdbcafa480bbf69e2fa9775dc5" + "sha": "3a305ba00b9739ceb17c879f82319b0a6b2a3f9f" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6abb59097be84599a1d6091fe534a49e5c5cf948" + "sha": "1f1148d3c7a7a52f0c98077f976bd9b3c948ee2b" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 00c974a90066..3bbc9076243d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -58,30 +58,8 @@ See the [Google Cloud Spanner JDBC client library docs][javadocs] to learn how t use this Google Cloud Spanner JDBC Client Library. -### Creating a JDBC Connection - -The following example shows how to create a JDBC connection to Cloud Spanner and execute a simple query. - -```java -String projectId = "my-project"; -String instanceId = "my-instance"; -String databaseId = "my-database"; - -try (Connection connection = - DriverManager.getConnection( - String.format( - "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", - projectId, instanceId, databaseId))) { - try (Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { - while (rs.next()) { - System.out.printf( - "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); - } - } - } -} -``` + + ## Troubleshooting @@ -123,7 +101,7 @@ Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] -[product-docs]: https://cloud.google.com/spanner/docs/use-oss-jdbc +[product-docs]: https://cloud.google.com/pubsub/docs/ [javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html [kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg [kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.html From 50fc1cd6f17d1aa76e83139672aef29b058205c9 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 10 Nov 2020 09:36:22 -0800 Subject: [PATCH 0239/1979] chore(java): ignore return code 28 in README autosynth job (#266) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/268ed0db-90ce-4f9f-ba46-1924fe46218f/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/7db8a6c5ffb12a6e4c2f799c18f00f7f3d60e279 --- java-spanner-jdbc/.kokoro/readme.sh | 11 ++++++++++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/readme.sh b/java-spanner-jdbc/.kokoro/readme.sh index 0bd5ca59731c..05ab5cf8e746 100755 --- a/java-spanner-jdbc/.kokoro/readme.sh +++ b/java-spanner-jdbc/.kokoro/readme.sh @@ -28,9 +28,18 @@ echo "https://${GITHUB_TOKEN}:@github.com" >> ~/.git-credentials git config --global credential.helper 'store --file ~/.git-credentials' python3.6 -m pip install git+https://github.com/googleapis/synthtool.git#egg=gcp-synthtool + +set +e python3.6 -m autosynth.synth \ --repository=googleapis/java-spanner-jdbc \ --synth-file-name=.github/readme/synth.py \ --metadata-path=.github/readme/synth.metadata \ --pr-title="chore: regenerate README" \ - --branch-suffix="readme" \ No newline at end of file + --branch-suffix="readme" + +# autosynth returns 28 to signal there are no changes +RETURN_CODE=$? +if [[ ${RETURN_CODE} -ne 0 && ${RETURN_CODE} -ne 28 ]] +then + exit ${RETURN_CODE} +fi diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 369d94fd8481..8406623f9d78 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "c3616a7960d0f544366301464ec6f357b9fdb275" + "sha": "5805c364b0f5f3085830ed741682a1ceda2189ef" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c7824ea48ff6d4d42dfae0849aec8a85acd90bd9" + "sha": "7db8a6c5ffb12a6e4c2f799c18f00f7f3d60e279" } } ], From 853f3f255ded21d3e6077a5cc056bb28d71b7871 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 12 Nov 2020 19:18:09 +0100 Subject: [PATCH 0240/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v15.1.0 (#268) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `15.0.0` -> `15.1.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c4ec1a86ce7f..a21d7304d293 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 15.0.0 + 15.1.0 pom import From 49ebe57b63700cfb7a7fb3b314015e7d673e1842 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 13 Nov 2020 13:14:18 -0800 Subject: [PATCH 0241/1979] build(java): use code-suggester v1 tag rather than full semver (#269) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/62d29775-e679-4d20-bb82-8ed0902c03b5/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/7d652819519dfa24da9e14548232e4aaba71a11c --- java-spanner-jdbc/.github/workflows/formatting.yaml | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/formatting.yaml b/java-spanner-jdbc/.github/workflows/formatting.yaml index d4d367cfce03..6844407b4d97 100644 --- a/java-spanner-jdbc/.github/workflows/formatting.yaml +++ b/java-spanner-jdbc/.github/workflows/formatting.yaml @@ -18,7 +18,7 @@ jobs: with: java-version: 11 - run: "mvn com.coveo:fmt-maven-plugin:format" - - uses: googleapis/code-suggester@v1.8.0 + - uses: googleapis/code-suggester@v1 with: command: review pull_number: ${{ github.event.pull_request.number }} diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 8406623f9d78..73444be09051 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "5805c364b0f5f3085830ed741682a1ceda2189ef" + "sha": "96bb531c9ef8499b815bdb13cb07363da0e4f293" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7db8a6c5ffb12a6e4c2f799c18f00f7f3d60e279" + "sha": "7d652819519dfa24da9e14548232e4aaba71a11c" } } ], From acc8b1c50735fd21d85464e3251651bed626bc4a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 17 Nov 2020 22:02:05 +0100 Subject: [PATCH 0242/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.15.0 (#237) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.10.0` -> `0.15.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.15.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0150-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0141v0150-2020-11-10) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.14.1...v0.15.0) ##### Dependencies - update dependency com.google.http-client:google-http-client-bom to v1.38.0 ([#​207](https://www.github.com/googleapis/java-shared-dependencies/issues/207)) ([5e3198d](https://www.github.com/googleapis/java-shared-dependencies/commit/5e3198de5e1d0fe55c4d947b12984db7726059da)) - update google.common-protos.version to v2.0.1 ([#​205](https://www.github.com/googleapis/java-shared-dependencies/issues/205)) ([6b12417](https://www.github.com/googleapis/java-shared-dependencies/commit/6b1241737d34e99a55acdcd439aa71ad28d1e26c)) - update iam.version to v1.0.3 ([#​206](https://www.github.com/googleapis/java-shared-dependencies/issues/206)) ([94a4e31](https://www.github.com/googleapis/java-shared-dependencies/commit/94a4e31634718a206ef0f5ff1a8801dc7be4c5c5)) ##### [0.14.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.14.0...v0.14.1) (2020-10-31) ##### Dependencies - update google.core.version to v1.93.10 ([#​200](https://www.github.com/googleapis/java-shared-dependencies/issues/200)) ([2d73dc1](https://www.github.com/googleapis/java-shared-dependencies/commit/2d73dc152469d175c74f85c5c76dcc67993c9783)) ### [`v0.14.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0141-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0140v0141-2020-10-31) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.14.0...v0.14.1) ### [`v0.14.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0140-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0130v0140-2020-10-31) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.13.0...v0.14.0) ##### Dependencies - update dependency io.grpc:grpc-bom to v1.33.1 ([#​192](https://www.github.com/googleapis/java-shared-dependencies/issues/192)) ([b29384d](https://www.github.com/googleapis/java-shared-dependencies/commit/b29384dc40c812f1848f00695228d5437556f029)) - update dependency org.threeten:threetenbp to v1.5.0 ([#​196](https://www.github.com/googleapis/java-shared-dependencies/issues/196)) ([825a6fa](https://www.github.com/googleapis/java-shared-dependencies/commit/825a6fa375d12f1caa0a515b784ffde182bac98d)) - update iam.version to v1.0.2 ([#​194](https://www.github.com/googleapis/java-shared-dependencies/issues/194)) ([5c57239](https://www.github.com/googleapis/java-shared-dependencies/commit/5c572399a1b453f4dc5f6ef8d8850a35be2aef75)) ### [`v0.13.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0130-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0121v0130-2020-10-20) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.12.1...v0.13.0) ##### Features - add jackson-core to the list of managed dependencies ([#​190](https://www.github.com/googleapis/java-shared-dependencies/issues/190)) ([b37035e](https://www.github.com/googleapis/java-shared-dependencies/commit/b37035ed9b0beeb5e07d6e1c121154eece1a2c87)) ##### Dependencies - update dependency com.google.guava:guava-bom to v30 ([#​181](https://www.github.com/googleapis/java-shared-dependencies/issues/181)) ([bdb1e58](https://www.github.com/googleapis/java-shared-dependencies/commit/bdb1e582288d06a872e36ac8b778563f2d088468)) - update gax.version to v1.60.0 ([#​187](https://www.github.com/googleapis/java-shared-dependencies/issues/187)) ([8a8adf7](https://www.github.com/googleapis/java-shared-dependencies/commit/8a8adf7745d563c449bf095aad63b5e4a94e1a7d)) - update google.common-protos.version to v2 ([#​174](https://www.github.com/googleapis/java-shared-dependencies/issues/174)) ([3f7e3ff](https://www.github.com/googleapis/java-shared-dependencies/commit/3f7e3ffd5e07d2f11f0aa981dae2bdf5381e429f)) ##### [0.12.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.12.0...v0.12.1) (2020-10-16) ##### Dependencies - update dependency com.google.api:api-common to v1.10.1 ([#​180](https://www.github.com/googleapis/java-shared-dependencies/issues/180)) ([b1f2d5d](https://www.github.com/googleapis/java-shared-dependencies/commit/b1f2d5dfde24fcf683eeb5600fce7f51190ecce8)) ### [`v0.12.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0121-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0120v0121-2020-10-16) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.12.0...v0.12.1) ### [`v0.12.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0120-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0110v0120-2020-10-15) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.11.0...v0.12.0) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.30.11 ([#​169](https://www.github.com/googleapis/java-shared-dependencies/issues/169)) ([a1b18d1](https://www.github.com/googleapis/java-shared-dependencies/commit/a1b18d1838c2ceca882615d574ab5d0245794820)) - update dependency com.google.auth:google-auth-library-bom to v0.22.0 ([#​171](https://www.github.com/googleapis/java-shared-dependencies/issues/171)) ([0c7635a](https://www.github.com/googleapis/java-shared-dependencies/commit/0c7635a82d922971ae6aac18dc2ee1879e017516)) ### [`v0.11.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0110-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0102v0110-2020-10-13) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.10.2...v0.11.0) ##### Dependencies - update dependency com.google.http-client:google-http-client-bom to v1.37.0 ([#​166](https://www.github.com/googleapis/java-shared-dependencies/issues/166)) ([5721225](https://www.github.com/googleapis/java-shared-dependencies/commit/572122574ce8452b6a0fc6df919e9ce2d8ffd2ce)) - update dependency io.grpc:grpc-bom to v1.32.2 ([#​165](https://www.github.com/googleapis/java-shared-dependencies/issues/165)) ([b70ddb0](https://www.github.com/googleapis/java-shared-dependencies/commit/b70ddb00a3be97536cdd80bd57fe6bca1b0973e2)) ##### [0.10.2](https://www.github.com/googleapis/java-shared-dependencies/compare/0.10.1...v0.10.2) (2020-10-08) ##### Dependencies - update dependency org.threeten:threetenbp to v1.4.5 ([#​162](https://www.github.com/googleapis/java-shared-dependencies/issues/162)) ([54eccb5](https://www.github.com/googleapis/java-shared-dependencies/commit/54eccb533353ddfe537a7e069a696a3f0f70f211)) ##### [0.10.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.10.0...v0.10.1) (2020-10-06) ##### Dependencies - update gax.version to v1.59.1 ([#​159](https://www.github.com/googleapis/java-shared-dependencies/issues/159)) ([7c84443](https://www.github.com/googleapis/java-shared-dependencies/commit/7c84443db92e1d910590fa89c2e35b14613e7eba)) ### [`v0.10.2`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0102-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0101v0102-2020-10-08) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.10.1...v0.10.2) ### [`v0.10.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0101-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0100v0101-2020-10-06) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.10.0...v0.10.1)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 26a86015613d..873e9b0a0e56 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,13 +78,17 @@ com.google.cloud google-cloud-shared-dependencies - 0.10.0 + 0.15.0 pom import
    + + com.google.http-client + google-http-client + io.grpc grpc-api @@ -125,10 +129,6 @@ com.google.code.findbugs jsr305 - - com.google.http-client - google-http-client - com.google.auth google-auth-library-oauth2-http From bdd52688bd1c8ea3f0257436bbc47e7ff35cc8e7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 17 Nov 2020 16:25:31 -0500 Subject: [PATCH 0243/1979] chore: release 1.17.3 (#259) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index f10983723438..8aae6b617915 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +### [1.17.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.2...v1.17.3) (2020-11-17) + + +### Documentation + +* add package-info to jdbc ([#264](https://www.github.com/googleapis/java-spanner-jdbc/issues/264)) ([a2d26a1](https://www.github.com/googleapis/java-spanner-jdbc/commit/a2d26a1a9d1595c5a4d766419d3f46619d8d6c71)) +* add simple connection sample to readme ([#263](https://www.github.com/googleapis/java-spanner-jdbc/issues/263)) ([3a305ba](https://www.github.com/googleapis/java-spanner-jdbc/commit/3a305ba00b9739ceb17c879f82319b0a6b2a3f9f)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.15.0 ([#237](https://www.github.com/googleapis/java-spanner-jdbc/issues/237)) ([6487a24](https://www.github.com/googleapis/java-spanner-jdbc/commit/6487a24def74e630ee43ec058a267f8d0889c336)) +* use google-cloud-spanner-bom ([#258](https://www.github.com/googleapis/java-spanner-jdbc/issues/258)) ([c9906c9](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9906c9440d1574ae74d735aad8b3c255704d59d)) + ### [1.17.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.1...v1.17.2) (2020-10-29) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 873e9b0a0e56..65918336441d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.3-SNAPSHOT + 1.17.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 949d10fdd460..d062d58e5add 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.3-SNAPSHOT + 1.17.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 195dd2e84aeb..e2424ad9507d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.2:1.17.3-SNAPSHOT +google-cloud-spanner-jdbc:1.17.3:1.17.3 From 0ac32b4d32fa9ba8069a875211f3255a48e608dd Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 18 Nov 2020 14:43:15 -0800 Subject: [PATCH 0244/1979] build(java): use actions/github-script v3 tag rather than full semver (#274) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/068e3861-8461-4859-af8c-cbe12aa64c29/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58 --- java-spanner-jdbc/.github/workflows/approve-readme.yaml | 2 +- java-spanner-jdbc/.github/workflows/auto-release.yaml | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml index e2d841d6c5a0..7513acaebcc2 100644 --- a/java-spanner-jdbc/.github/workflows/approve-readme.yaml +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' steps: - - uses: actions/github-script@v3.0.0 + - uses: actions/github-script@v3 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} script: | diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index bc1554aecba2..2b6cdbc976c4 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.head_ref, 'release-v') steps: - - uses: actions/github-script@v3.0.0 + - uses: actions/github-script@v3 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 73444be09051..4184d389207a 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "96bb531c9ef8499b815bdb13cb07363da0e4f293" + "sha": "b58db75ff89d92e8a5548699500b10fbe3251c02" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7d652819519dfa24da9e14548232e4aaba71a11c" + "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" } } ], From 5c98b2eec8165761715ac8fe25efcd20469670fe Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 18 Nov 2020 15:06:03 -0800 Subject: [PATCH 0245/1979] chore: regenerate README (#277) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-11-18 22:47:42,543 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working directory clean 2020-11-18 22:47:43,488 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/9682518c-ef5e-4ccf-a98f-fdd5addc52e6/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 19ca2958ff12..231304669ff0 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3a305ba00b9739ceb17c879f82319b0a6b2a3f9f" + "sha": "35d0936d769fea9c46216dce009a3cc78a4d9eba" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "1f1148d3c7a7a52f0c98077f976bd9b3c948ee2b" + "sha": "39b7149da4026765385403632db3c6f63db96b2c" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 3bbc9076243d..ba6915f6bb1c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,17 +17,17 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.17.0 + 1.17.3 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.3' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.3" ``` ## Authentication From 5be4abcd42a5b131f57d16a94fb8b7657c76ce38 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 19 Nov 2020 17:58:38 +0100 Subject: [PATCH 0246/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v16 (#275) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | major | `15.1.0` -> `16.1.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a21d7304d293..974bf1c3a060 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 15.1.0 + 16.1.0 pom import From 43de095199a93a7617690f76404b5d04ce83d0ba Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 19 Nov 2020 18:38:22 +0100 Subject: [PATCH 0247/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.17.3 (#273) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://togithub.com/googleapis/java-spanner-jdbc) | patch | `1.17.0` -> `1.17.3` | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v1.17.3`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​1173-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev1172v1173-2020-11-17) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v1.17.0...v1.17.3)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 72e625fbd93f..f6888f0e5a73 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.0 + 1.17.3 From 934fb04d9ecf5e0468ee432912fe46db218649dd Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 20 Nov 2020 08:10:28 -0800 Subject: [PATCH 0248/1979] chore(java): retry staging portion of the release with backoff (#279) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/407a758f-25d9-475d-8ed1-b8b2eb5d7c99/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/68742c6016bf0d16948a572633d17955a8737414 --- java-spanner-jdbc/.kokoro/common.sh | 1 - java-spanner-jdbc/.kokoro/release/stage.sh | 17 ++++++++++------- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/common.sh b/java-spanner-jdbc/.kokoro/common.sh index a8d0ea04d37d..ace89f45a9de 100644 --- a/java-spanner-jdbc/.kokoro/common.sh +++ b/java-spanner-jdbc/.kokoro/common.sh @@ -25,7 +25,6 @@ function retry_with_backoff { # allow a failures to continue set +e - echo "${command}" ${command} exit_code=$? diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 3c482cbc55f1..16126d2eb53f 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -20,19 +20,22 @@ python3 -m pip install gcp-releasetool python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script source $(dirname "$0")/common.sh +source $(dirname "$0")/../common.sh MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml pushd $(dirname "$0")/../../ setup_environment_secrets create_settings_xml_file "settings.xml" -mvn clean install deploy -B \ - --settings ${MAVEN_SETTINGS_FILE} \ - -DskipTests=true \ - -DperformRelease=true \ - -Dgpg.executable=gpg \ - -Dgpg.passphrase=${GPG_PASSPHRASE} \ - -Dgpg.homedir=${GPG_HOMEDIR} +# attempt to stage 3 times with exponential backoff (starting with 10 seconds) +retry_with_backoff 3 10 \ + mvn clean install deploy -B \ + --settings ${MAVEN_SETTINGS_FILE} \ + -DskipTests=true \ + -DperformRelease=true \ + -Dgpg.executable=gpg \ + -Dgpg.passphrase=${GPG_PASSPHRASE} \ + -Dgpg.homedir=${GPG_HOMEDIR} if [[ -n "${AUTORELEASE_PR}" ]] then diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 4184d389207a..c1e35a32eeb1 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "b58db75ff89d92e8a5548699500b10fbe3251c02" + "sha": "825f186f485dc2326c53bbc05151284cfc5f9c26" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" + "sha": "68742c6016bf0d16948a572633d17955a8737414" } } ], From 6f8c0bc00052b1ce9ffb9e58d13cce16fbe9f6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 24 Nov 2020 20:18:45 +0100 Subject: [PATCH 0249/1979] deps: do not re-declare grpc dependencies as test dependencies (#278) * deps: include grpc dependencies * deps: remove all unnecessary deps * fix: re-add undeclared dependencies --- java-spanner-jdbc/pom.xml | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 65918336441d..8a1031437132 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -147,9 +147,9 @@
    com.google.api.grpc - grpc-google-cloud-spanner-v1 + proto-google-cloud-spanner-v1 - + com.google.cloud @@ -157,21 +157,6 @@ test-jar test - - com.google.api.grpc - grpc-google-cloud-spanner-v1 - test - - - com.google.api.grpc - grpc-google-cloud-spanner-admin-instance-v1 - test - - - com.google.api.grpc - grpc-google-cloud-spanner-admin-database-v1 - test - com.google.truth truth From a23ec10db033af0cffe25f9e0bb337d4f3c5cf7d Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 24 Nov 2020 13:12:19 -0800 Subject: [PATCH 0250/1979] build(java): enable blunderbuss for samples (#280) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/5b6c114a-8bee-4a8e-8985-0e8ec5df74d0/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/943bb78606d035001123030067dffcc34f4645f2 --- java-spanner-jdbc/.github/blunderbuss.yml | 7 +++++++ java-spanner-jdbc/synth.metadata | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/blunderbuss.yml diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml new file mode 100644 index 000000000000..1a23ea42b141 --- /dev/null +++ b/java-spanner-jdbc/.github/blunderbuss.yml @@ -0,0 +1,7 @@ +# Configuration for the Blunderbuss GitHub app. For more info see +# https://github.com/googleapis/repo-automation-bots/tree/master/packages/blunderbuss +assign_prs_by: +- labels: + - samples + to: + - googleapis/java-samples-reviewers \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index c1e35a32eeb1..9752b2767798 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "825f186f485dc2326c53bbc05151284cfc5f9c26" + "sha": "9b1b9067241736c7e2f6d75d3f34824bc4ea1aca" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "68742c6016bf0d16948a572633d17955a8737414" + "sha": "943bb78606d035001123030067dffcc34f4645f2" } } ], @@ -21,6 +21,7 @@ ".github/ISSUE_TEMPLATE/feature_request.md", ".github/ISSUE_TEMPLATE/support_request.md", ".github/PULL_REQUEST_TEMPLATE.md", + ".github/blunderbuss.yml", ".github/generated-files-bot.yml", ".github/readme/synth.py", ".github/release-please.yml", From 00d7b8a8232ad120e371b9ec5f9bc6ff7c43f577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 27 Nov 2020 01:34:23 +0100 Subject: [PATCH 0251/1979] docs: add connection example to readme (#281) --- java-spanner-jdbc/.readme-partials.yaml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 java-spanner-jdbc/.readme-partials.yaml diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml new file mode 100644 index 000000000000..47e65e1488b5 --- /dev/null +++ b/java-spanner-jdbc/.readme-partials.yaml @@ -0,0 +1,25 @@ +custom_content: | + ### Creating a JDBC Connection + + The following example shows how to create a JDBC connection to Cloud Spanner and execute a simple query. + + ```java + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } + } + ``` From 9cefae4e850f1233e0d66d539412f18912a552dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 27 Nov 2020 01:34:47 +0100 Subject: [PATCH 0252/1979] docs: fix product docs link (#282) --- java-spanner-jdbc/.repo-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index fe90fd731d04..524b2f3f22c9 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -1,7 +1,7 @@ { "name": "spanner-jdbc", "name_pretty": "Google Cloud Spanner JDBC", - "product_documentation": "https://cloud.google.com/pubsub/docs/", + "product_documentation": "https://cloud.google.com/spanner/docs/use-oss-jdbc", "client_documentation": "https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html", "release_level": "ga", "language": "java", From bffa806931babfd53864359cc43aa18124aa1895 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 1 Dec 2020 03:53:19 +0100 Subject: [PATCH 0253/1979] test(deps): update dependency com.google.truth:truth to v1.1 (#239) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8a1031437132..5c3690907a55 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ 4.13.1 3.0.2 1.4.4 - 1.0.1 + 1.1 1.10.19 2.2 From 547c6785c699e17cbbdfd0d29a4ae0aa1a672b90 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 1 Dec 2020 07:06:59 +0100 Subject: [PATCH 0254/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v3 (#260) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5c3690907a55..24eb814804e1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 2.0.2 + 3.0.4 pom import From 81878640de9307c870e314da41f4130787afe448 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 2 Dec 2020 22:24:46 +0100 Subject: [PATCH 0255/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.16.0 (#286) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.15.0` -> `0.16.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.16.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0160-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0150v0160-2020-12-02) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.15.0...v0.16.0) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.12.0 ([#​225](https://www.github.com/googleapis/java-shared-dependencies/issues/225)) ([b78a1ef](https://www.github.com/googleapis/java-shared-dependencies/commit/b78a1ef83ad946b0d29cd0dff46e48fbde44d120)) - update dependency com.google.api-client:google-api-client-bom to v1.31.1 ([#​215](https://www.github.com/googleapis/java-shared-dependencies/issues/215)) ([08d643a](https://www.github.com/googleapis/java-shared-dependencies/commit/08d643aaf289984b87d734274830712af82585b6)) - update dependency com.google.protobuf:protobuf-bom to v3.14.0 ([#​217](https://www.github.com/googleapis/java-shared-dependencies/issues/217)) ([01a9c64](https://www.github.com/googleapis/java-shared-dependencies/commit/01a9c6442906e8482a53712eba95ccc6f7040928)) - update dependency io.grpc:grpc-bom to v1.34.0 ([#​228](https://www.github.com/googleapis/java-shared-dependencies/issues/228)) ([425d1ea](https://www.github.com/googleapis/java-shared-dependencies/commit/425d1eab2a046c365f816f946576e4030e7c3696)) - update gax.version to v1.60.1 ([#​223](https://www.github.com/googleapis/java-shared-dependencies/issues/223)) ([84c75bd](https://www.github.com/googleapis/java-shared-dependencies/commit/84c75bdbd3f86ef7187373289ee08ad3a0c24719)) - update google.core.version to v1.94.0 ([#​212](https://www.github.com/googleapis/java-shared-dependencies/issues/212)) ([764ef5e](https://www.github.com/googleapis/java-shared-dependencies/commit/764ef5e9a2272cd9244a8fc5cc107ffacf9e9d5b))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 24eb814804e1..28207c7a06b9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.15.0 + 0.16.0 pom import From 6dd0eee348829499a3f6811d05620aa3513dbe04 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 4 Dec 2020 08:25:48 +0100 Subject: [PATCH 0256/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v3.0.5 (#287) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 28207c7a06b9..956c1888d00d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 3.0.4 + 3.0.5 pom import From f6bfdcdaa8be287ec856a8c11f2c09d2479ba2c5 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sat, 5 Dec 2020 01:24:30 -0800 Subject: [PATCH 0257/1979] chore: regenerate README (#285) --- .../readme/synth.metadata/synth.metadata | 4 +-- java-spanner-jdbc/README.md | 27 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 231304669ff0..0d720cda1de3 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "35d0936d769fea9c46216dce009a3cc78a4d9eba" + "sha": "0065a9b319b09e71bf285f85c33514442a163dea" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "39b7149da4026765385403632db3c6f63db96b2c" + "sha": "c2de32114ec484aa708d32012d1fa8d75232daf5" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ba6915f6bb1c..f1207a9b90b5 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -58,6 +58,31 @@ See the [Google Cloud Spanner JDBC client library docs][javadocs] to learn how t use this Google Cloud Spanner JDBC Client Library. +### Creating a JDBC Connection + +The following example shows how to create a JDBC connection to Cloud Spanner and execute a simple query. + +```java +String projectId = "my-project"; +String instanceId = "my-instance"; +String databaseId = "my-database"; + +try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } +} +``` + @@ -101,7 +126,7 @@ Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] -[product-docs]: https://cloud.google.com/pubsub/docs/ +[product-docs]: https://cloud.google.com/spanner/docs/use-oss-jdbc [javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html [kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg [kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.html From 60d357e90c27f4546347d74dc39ced4fd467bb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 5 Dec 2020 10:35:22 +0100 Subject: [PATCH 0258/1979] feat: expose more methods from Connection in JDBC (#255) * feat: expose more methods from Connection in JDBC More methods from the Connection API should be exposed in the Cloud Spanner JDBC Connection interface to make it easier to execute read-only transactions with specific timestamp bounds. Towards #253 * clirr: add ignored differences --- .../clirr-ignored-differences.xml | 52 +++++++++ .../jdbc/CloudSpannerJdbcConnection.java | 110 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcConnection.java | 63 ++++++++++ 3 files changed, 225 insertions(+) diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index cfa113659dca..7e243773992e 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -42,4 +42,56 @@ 8001 com/google/cloud/spanner/jdbc/UnitOfWork$UnitOfWorkState + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.connection.AutocommitDmlMode getAutocommitDmlMode() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + java.lang.String getOptimizerVersion() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.TimestampBound getReadOnlyStaleness() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.connection.TransactionMode getTransactionMode() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isInTransaction() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isTransactionStarted() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setAutocommitDmlMode(com.google.cloud.spanner.connection.AutocommitDmlMode) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setOptimizerVersion(java.lang.String) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setReadOnlyStaleness(com.google.cloud.spanner.TimestampBound) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setTransactionMode(com.google.cloud.spanner.connection.TransactionMode) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index dc52ca355d95..f13a64f5b64f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -19,6 +19,9 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.TimestampBound; +import com.google.cloud.spanner.connection.AutocommitDmlMode; +import com.google.cloud.spanner.connection.TransactionMode; import java.sql.Connection; import java.sql.SQLException; import java.sql.Timestamp; @@ -34,6 +37,113 @@ */ public interface CloudSpannerJdbcConnection extends Connection { + /** + * Sets the transaction mode to use for current transaction. This method may only be called when + * in a transaction, and before the transaction is actually started, i.e. before any statements + * have been executed in the transaction. + * + * @param transactionMode The transaction mode to use for the current transaction. + *
      + *
    • {@link TransactionMode#READ_ONLY_TRANSACTION} will create a read-only transaction and + * prevent any changes to written to the database through this transaction. The read + * timestamp to be used will be determined based on the current readOnlyStaleness + * setting of this connection. It is recommended to use {@link + * TransactionMode#READ_ONLY_TRANSACTION} instead of {@link + * TransactionMode#READ_WRITE_TRANSACTION} when possible, as read-only transactions do + * not acquire locks on Cloud Spanner, and read-only transactions never abort. + *
    • {@link TransactionMode#READ_WRITE_TRANSACTION} this value is only allowed when the + * connection is not in read-only mode and will create a read-write transaction. If + * {@link Connection#isRetryAbortsInternally()} is true, each read/write + * transaction will keep track of a running SHA256 checksum for each {@link ResultSet} + * that is returned in order to be able to retry the transaction in case the transaction + * is aborted by Spanner. + *
    + */ + void setTransactionMode(TransactionMode transactionMode) throws SQLException; + + /** + * @return the transaction mode of the current transaction. This method may only be called when + * the connection is in a transaction. + */ + TransactionMode getTransactionMode() throws SQLException; + + /** + * Sets the mode for executing DML statements in autocommit mode for this connection. This setting + * is only used when the connection is in autocommit mode, and may only be set while the + * transaction is in autocommit mode and not in a temporary transaction. The autocommit + * transaction mode is reset to its default value of {@link AutocommitDmlMode#TRANSACTIONAL} when + * autocommit mode is changed on the connection. + * + * @param mode The DML autocommit mode to use + *
      + *
    • {@link AutocommitDmlMode#TRANSACTIONAL} DML statements are executed as single + * read-write transaction. After successful execution, the DML statement is guaranteed + * to have been applied exactly once to the database + *
    • {@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} DML statements are executed as + * partitioned DML transactions. If an error occurs during the execution of the DML + * statement, it is possible that the statement has been applied to some but not all of + * the rows specified in the statement. + *
    + */ + void setAutocommitDmlMode(AutocommitDmlMode mode) throws SQLException; + + /** + * @return the current {@link AutocommitDmlMode} setting for this connection. This method may only + * be called on a connection that is in autocommit mode and not while in a temporary + * transaction. + */ + AutocommitDmlMode getAutocommitDmlMode() throws SQLException; + + /** + * Sets the staleness to use for the current read-only transaction. This method may only be called + * when the transaction mode of the current transaction is {@link + * TransactionMode#READ_ONLY_TRANSACTION} and there is no transaction that has started, or when + * the connection is in read-only and autocommit mode. + * + * @param staleness The staleness to use for the current but not yet started read-only transaction + */ + void setReadOnlyStaleness(TimestampBound staleness) throws SQLException; + + /** + * @return the read-only staleness setting for the current read-only transaction. This method may + * only be called when the current transaction is a read-only transaction, or when the + * connection is in read-only and autocommit mode. + */ + TimestampBound getReadOnlyStaleness() throws SQLException; + + /** + * Sets the query optimizer version to use for this connection. + * + * @param optimizerVersion The query optimizer version to use. Must be a valid optimizer version + * number, the string LATEST or an empty string. The empty string will instruct + * the connection to use the optimizer version that is defined in the environment variable + * SPANNER_OPTIMIZER_VERSION. If no value is specified in the environment + * variable, the default query optimizer of Cloud Spanner is used. + */ + void setOptimizerVersion(String optimizerVersion) throws SQLException; + + /** + * Gets the current query optimizer version of this connection. + * + * @return The query optimizer version that is currently used by this connection. + */ + String getOptimizerVersion() throws SQLException; + + /** + * @return true if this connection has a transaction (that has not necessarily + * started). This method will only return false when the {@link Connection} is in autocommit + * mode and no explicit transaction has been started by calling {@link + * Connection#beginTransaction()}. If the {@link Connection} is not in autocommit mode, there + * will always be a transaction. + */ + boolean isInTransaction() throws SQLException; + + /** + * @return true if this connection has a transaction that has started. A transaction + * is automatically started by the first statement that is executed in the transaction. + */ + boolean isTransactionStarted() throws SQLException; + /** * @return the commit {@link Timestamp} of the last read/write transaction. If the last * transaction was not a read/write transaction, or a read/write transaction that did not diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 4e2318092866..3d79c5efb9b4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -19,8 +19,11 @@ import com.google.api.client.util.Preconditions; import com.google.cloud.spanner.Mutation; 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.ConnectionOptions; import com.google.cloud.spanner.connection.StatementParser; +import com.google.cloud.spanner.connection.TransactionMode; import com.google.common.base.Function; import com.google.common.collect.Iterators; import java.sql.Array; @@ -74,6 +77,66 @@ public String nativeSQL(String sql) throws SQLException { .sqlWithNamedParameters; } + @Override + public void setTransactionMode(TransactionMode mode) throws SQLException { + checkClosed(); + getSpannerConnection().setTransactionMode(mode); + } + + @Override + public TransactionMode getTransactionMode() throws SQLException { + checkClosed(); + return getSpannerConnection().getTransactionMode(); + } + + @Override + public void setAutocommitDmlMode(AutocommitDmlMode mode) throws SQLException { + checkClosed(); + getSpannerConnection().setAutocommitDmlMode(mode); + } + + @Override + public AutocommitDmlMode getAutocommitDmlMode() throws SQLException { + checkClosed(); + return getSpannerConnection().getAutocommitDmlMode(); + } + + @Override + public void setReadOnlyStaleness(TimestampBound staleness) throws SQLException { + checkClosed(); + getSpannerConnection().setReadOnlyStaleness(staleness); + } + + @Override + public TimestampBound getReadOnlyStaleness() throws SQLException { + checkClosed(); + return getSpannerConnection().getReadOnlyStaleness(); + } + + @Override + public void setOptimizerVersion(String optimizerVersion) throws SQLException { + checkClosed(); + getSpannerConnection().setOptimizerVersion(optimizerVersion); + } + + @Override + public String getOptimizerVersion() throws SQLException { + checkClosed(); + return getSpannerConnection().getOptimizerVersion(); + } + + @Override + public boolean isInTransaction() throws SQLException { + checkClosed(); + return getSpannerConnection().isInTransaction(); + } + + @Override + public boolean isTransactionStarted() throws SQLException { + checkClosed(); + return getSpannerConnection().isTransactionStarted(); + } + @Override public void setAutoCommit(boolean autoCommit) throws SQLException { checkClosed(); From abfd344e05536c41ab1f8ec4f70f98d13d1d19e2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 5 Dec 2020 10:40:10 +0100 Subject: [PATCH 0259/1979] chore: release 1.17.4-SNAPSHOT (#276) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 956c1888d00d..0db5fa92ba3d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.3 + 1.17.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d062d58e5add..ef055198d826 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.3 + 1.17.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e2424ad9507d..3115ab74ae7c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.3:1.17.3 +google-cloud-spanner-jdbc:1.17.3:1.17.4-SNAPSHOT From b9181b8f8709a14f91a19b8c3052176000f260ac Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 9 Dec 2020 15:35:23 -0800 Subject: [PATCH 0260/1979] chore: Update publish_javadoc.sh (#289) * (chore) Update publish_javadoc.sh * add `export` to the envVar's to make sure maven knows about them. * report the Java version * chore: update script * remove `java -version` Co-authored-by: Jeffrey Rennie Source-Author: Les Vogel Source-Date: Mon Dec 7 09:37:58 2020 -0800 Source-Repo: googleapis/synthtool Source-Sha: 5d11bd2888c38ce1fb6fa6bf25494a4219a73928 Source-Link: https://github.com/googleapis/synthtool/commit/5d11bd2888c38ce1fb6fa6bf25494a4219a73928 --- java-spanner-jdbc/.kokoro/release/publish_javadoc.sh | 7 ++++--- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 3c87c1b7f8f4..7325bdc741cd 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -38,8 +38,8 @@ python3 -m pip install gcp-docuploader # compile all packages mvn clean install -B -q -DskipTests=true -NAME=google-cloud-spanner-jdbc -VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) +export NAME=google-cloud-spanner-jdbc +export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) # build the docs mvn site -B -q @@ -59,7 +59,8 @@ python3 -m docuploader upload . \ popd -# V2 +# V2 due to problems w/ the released javadoc plugin doclava, Java 8 is required. Beware of accidental updates. + mvn clean site -B -q -Ddevsite.template="${KOKORO_GFILE_DIR}/java/" pushd target/devsite/reference diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 9752b2767798..f231fec1c2f3 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "9b1b9067241736c7e2f6d75d3f34824bc4ea1aca" + "sha": "5531536d406e1fe3043a9d379c8102f1b0a5ade7" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "943bb78606d035001123030067dffcc34f4645f2" + "sha": "5d11bd2888c38ce1fb6fa6bf25494a4219a73928" } } ], From 68857d1fdb22e69b5552c9e2bb3faecdee8cb2c1 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 9 Dec 2020 15:54:02 -0800 Subject: [PATCH 0261/1979] chore: regenerate README (#292) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-12-09 23:37:42,284 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2020-12-09 23:37:43,159 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/1366ec45-7bc4-4111-8b8c-3a6ccc88a0cf/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 0d720cda1de3..fe8ac6901c26 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "0065a9b319b09e71bf285f85c33514442a163dea" + "sha": "9eea34c4206845a5e23b5b6ac78509497fd06069" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c2de32114ec484aa708d32012d1fa8d75232daf5" + "sha": "352f25621c28d2fa0784984ea0ed5ea697aa1525" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index f1207a9b90b5..5df90dbc1555 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -126,6 +126,8 @@ Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] +Java is a registered trademark of Oracle and/or its affiliates. + [product-docs]: https://cloud.google.com/spanner/docs/use-oss-jdbc [javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html [kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg From 40c1b6a95449f481fe9204fe545cfb5c0afe9e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 10 Dec 2020 12:54:51 +0100 Subject: [PATCH 0262/1979] feat: report whether column is generated in JDBC metadata (#291) Cloud Spanner now supports generated columns. These were reported as normal columns in the JDBC metadata. These are now reported correctly as generated columns. Fixes #290 --- .../jdbc/DatabaseMetaData_GetColumns.sql | 5 ++- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 33 +++++++++++++++++-- .../spanner/jdbc/it/CreateMusicTables.sql | 4 ++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 8b29c15b1493..69b1f6a8ec3e 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -72,7 +72,10 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU NULL AS SCOPE_TABLE, NULL AS SOURCE_DATA_TYPE, 'NO' AS IS_AUTOINCREMENT, - 'NO' AS IS_GENERATEDCOLUMN + CASE + WHEN (IS_GENERATED = 'NEVER') THEN 'NO' + ELSE 'YES' + END AS IS_GENERATEDCOLUMN FROM INFORMATION_SCHEMA.COLUMNS C WHERE UPPER(C.TABLE_CATALOG) LIKE ? AND UPPER(C.TABLE_SCHEMA) LIKE ? diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 711363c29159..755539987f1e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -53,7 +54,8 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { @BeforeClass public static void skipOnEmulator() { - assumeFalse("foreign keys are not supported on the emulator", env.getTestHelper().isEmulator()); + assumeFalse( + "foreign keys are not supported on the emulator", EmulatorSpannerHelper.isUsingEmulator()); } @Override @@ -70,6 +72,7 @@ private static final class Column { private final Integer radix; private final boolean nullable; private final Integer charOctetLength; + private final boolean computed; private Column( String name, @@ -80,6 +83,19 @@ private Column( Integer radix, boolean nullable, Integer charOctetLength) { + this(name, type, typeName, colSize, decimalDigits, radix, nullable, charOctetLength, false); + } + + private Column( + String name, + int type, + String typeName, + Integer colSize, + Integer decimalDigits, + Integer radix, + boolean nullable, + Integer charOctetLength, + boolean computed) { this.name = name; this.type = type; this.typeName = typeName; @@ -88,6 +104,7 @@ private Column( this.radix = radix; this.nullable = nullable; this.charOctetLength = charOctetLength; + this.computed = computed; } } @@ -133,7 +150,17 @@ private Column( new Column("ColDateArray", Types.ARRAY, "ARRAY", 10, null, null, true, null), new Column( "ColTimestampArray", Types.ARRAY, "ARRAY", 35, null, null, true, null), - new Column("ColNumericArray", Types.ARRAY, "ARRAY", 15, null, 10, true, null)); + new Column("ColNumericArray", Types.ARRAY, "ARRAY", 15, null, 10, true, null), + new Column( + "ColComputed", + Types.NVARCHAR, + "STRING(MAX)", + 2621440, + null, + null, + true, + 2621440, + true)); @Test public void testGetColumns() throws SQLException { @@ -195,7 +222,7 @@ public void testGetColumns() throws SQLException { assertThat(rs.getShort("SOURCE_DATA_TYPE"), is(equalTo((short) 0))); assertThat(rs.wasNull(), is(true)); assertThat(rs.getString("IS_AUTOINCREMENT"), is(equalTo("NO"))); - assertThat(rs.getString("IS_GENERATEDCOLUMN"), is(equalTo("NO"))); + assertThat(rs.getString("IS_GENERATEDCOLUMN"), is(equalTo(col.computed ? "YES" : "NO"))); assertThat(rs.getMetaData().getColumnCount(), is(equalTo(24))); pos++; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 4d05cdfb55d7..6a8c4616d1d6 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -84,7 +84,9 @@ CREATE TABLE TableWithAllColumnTypes ( ColBytesMaxArray ARRAY, ColDateArray ARRAY, ColTimestampArray ARRAY, - ColNumericArray ARRAY + ColNumericArray ARRAY, + + ColComputed STRING(MAX) AS (CONCAT(COALESCE(ColString, ''), ' ', COALESCE(ColStringMax, ''))) STORED, ) PRIMARY KEY (ColInt64) ; From c9d4659b1abdabf077e6b16a3c9c8338d23203a5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 11 Dec 2020 12:15:44 +1100 Subject: [PATCH 0263/1979] chore: release 1.18.0 (#288) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 22 ++++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8aae6b617915..e9772f916b79 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [1.18.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.3...v1.18.0) (2020-12-10) + + +### Features + +* expose more methods from Connection in JDBC ([#255](https://www.github.com/googleapis/java-spanner-jdbc/issues/255)) ([697837c](https://www.github.com/googleapis/java-spanner-jdbc/commit/697837ce0ce646a9ca45a0afc3a2e1e368c712f7)), closes [#253](https://www.github.com/googleapis/java-spanner-jdbc/issues/253) +* report whether column is generated in JDBC metadata ([#291](https://www.github.com/googleapis/java-spanner-jdbc/issues/291)) ([9aa9a1f](https://www.github.com/googleapis/java-spanner-jdbc/commit/9aa9a1f8f673554ae71e78937007166f220dd255)), closes [#290](https://www.github.com/googleapis/java-spanner-jdbc/issues/290) + + +### Documentation + +* add connection example to readme ([#281](https://www.github.com/googleapis/java-spanner-jdbc/issues/281)) ([00314e6](https://www.github.com/googleapis/java-spanner-jdbc/commit/00314e643ee6570ed6025630616ad0df70789447)) +* fix product docs link ([#282](https://www.github.com/googleapis/java-spanner-jdbc/issues/282)) ([0065a9b](https://www.github.com/googleapis/java-spanner-jdbc/commit/0065a9b319b09e71bf285f85c33514442a163dea)) + + +### Dependencies + +* do not re-declare grpc dependencies as test dependencies ([#278](https://www.github.com/googleapis/java-spanner-jdbc/issues/278)) ([4bc59f8](https://www.github.com/googleapis/java-spanner-jdbc/commit/4bc59f8d7f27cee0bbc54b91271e2aadd7cb31da)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.16.0 ([#286](https://www.github.com/googleapis/java-spanner-jdbc/issues/286)) ([2d804f5](https://www.github.com/googleapis/java-spanner-jdbc/commit/2d804f5b52271356598588764c77d1a13f3b7183)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v3 ([#260](https://www.github.com/googleapis/java-spanner-jdbc/issues/260)) ([40cdbc0](https://www.github.com/googleapis/java-spanner-jdbc/commit/40cdbc01c91c153c8c3fd36cf7bf91d80b187f03)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v3.0.5 ([#287](https://www.github.com/googleapis/java-spanner-jdbc/issues/287)) ([9cef4d5](https://www.github.com/googleapis/java-spanner-jdbc/commit/9cef4d57f6b63caba71ba77160677f73569a8fea)) + ### [1.17.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.2...v1.17.3) (2020-11-17) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0db5fa92ba3d..40cc28c159cb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.17.4-SNAPSHOT + 1.18.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ef055198d826..d8d1386b94b9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.4-SNAPSHOT + 1.18.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3115ab74ae7c..453fd664f33b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.17.3:1.17.4-SNAPSHOT +google-cloud-spanner-jdbc:1.18.0:1.18.0 From f8128abb32241a71076b74b1263fb593681e94f0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 11 Dec 2020 07:50:31 +0100 Subject: [PATCH 0264/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.18.0 (#294) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f6888f0e5a73..df43e40370e0 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.17.3 + 1.18.0 From 3a221fe6900220f5379df77f6fb1eaaeef013662 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 11 Dec 2020 07:08:04 +0000 Subject: [PATCH 0265/1979] chore: release 1.18.1-SNAPSHOT (#295) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 40cc28c159cb..bc1b4086a306 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.0 + 1.18.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d8d1386b94b9..5b460eb0bb1a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.0 + 1.18.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 453fd664f33b..a7c9ca48f151 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.0:1.18.0 +google-cloud-spanner-jdbc:1.18.0:1.18.1-SNAPSHOT From 71aeac01f80d60d6d34a9eed595d0653632a42fd Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 10 Dec 2020 23:10:04 -0800 Subject: [PATCH 0266/1979] chore: regenerate README (#296) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-12-11 06:52:44,370 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2020-12-11 06:52:45,353 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/7cbd341c-d26d-4b29-b8c7-fa75aeee0c64/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index fe8ac6901c26..71f3c74f8632 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "9eea34c4206845a5e23b5b6ac78509497fd06069" + "sha": "53b459e334fdbf391d080817f8b782cff3b12d1b" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "352f25621c28d2fa0784984ea0ed5ea697aa1525" + "sha": "996775eca5fd934edac3c2ae34b80ff0395b1717" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 5df90dbc1555..c623b61a4736 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,17 +17,17 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.17.3 + 1.18.0 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.17.3' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.17.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.0" ``` ## Authentication From 6301359fb88cc4d016bd218529f8f56c9ba3324b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 14 Dec 2020 22:23:07 +0100 Subject: [PATCH 0267/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.16.1 --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bc1b4086a306..614a59a1a7d4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.16.0 + 0.16.1 pom import From 120d5c77519b3d5761ed1631b4d2dbf57cad3eef Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 14 Dec 2020 22:26:10 +0000 Subject: [PATCH 0268/1979] chore: release 1.18.1 (#299) :robot: I have created a release \*beep\* \*boop\* --- ### [1.18.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.0...v1.18.1) (2020-12-14) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v0.16.1 ([6301359](https://www.github.com/googleapis/java-spanner-jdbc/commit/6301359fb88cc4d016bd218529f8f56c9ba3324b)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e9772f916b79..7be3b0032e70 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.18.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.0...v1.18.1) (2020-12-14) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.16.1 ([5d5e5fc](https://www.github.com/googleapis/java-spanner-jdbc/commit/5d5e5fccef229e4edd9d34a93553a85a1e97b14f)) + ## [1.18.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.17.3...v1.18.0) (2020-12-10) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 614a59a1a7d4..f3ade3fdbf48 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.1-SNAPSHOT + 1.18.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5b460eb0bb1a..4e2ea8afcf9a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.1-SNAPSHOT + 1.18.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a7c9ca48f151..e642cd38b68b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.0:1.18.1-SNAPSHOT +google-cloud-spanner-jdbc:1.18.1:1.18.1 From cf938edc248d35a5ebbdb6241648a4a1b82d7ebe Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 15 Dec 2020 09:24:02 +0000 Subject: [PATCH 0269/1979] chore: release 1.18.2-SNAPSHOT (#300) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f3ade3fdbf48..df384fadd5f4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.1 + 1.18.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4e2ea8afcf9a..24743c4256a6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.1 + 1.18.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e642cd38b68b..8960c0693df3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.1:1.18.1 +google-cloud-spanner-jdbc:1.18.1:1.18.2-SNAPSHOT From 17b490393cda2fdad7b526269ec0347a8e9e93c5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Dec 2020 19:36:07 +0100 Subject: [PATCH 0270/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.17.0 (#302) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.16.1` -> `0.17.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.17.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0170-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0161v0170-2020-12-15) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.16.1...v0.17.0) ##### Dependencies - update dependency com.google.guava:guava-bom to v30.1-android ([#​236](https://www.github.com/googleapis/java-shared-dependencies/issues/236)) ([78ebf7f](https://www.github.com/googleapis/java-shared-dependencies/commit/78ebf7fcec3ec0308ccd5103b719f02dde7ec6d8)) - update dependency io.grpc:grpc-bom to v1.34.1 ([#​238](https://www.github.com/googleapis/java-shared-dependencies/issues/238)) ([ee7e020](https://www.github.com/googleapis/java-shared-dependencies/commit/ee7e020a4631f2b288d1c6f5d681423d156e3c2d)) - update iam.version to v1.0.5 ([#​237](https://www.github.com/googleapis/java-shared-dependencies/issues/237)) ([bbe6be6](https://www.github.com/googleapis/java-shared-dependencies/commit/bbe6be650a93cf365f2439ae9c8bebf2ade83ddd)) ##### [0.16.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.16.0...v0.16.1) (2020-12-14) ##### Dependencies - rollback gRPC to 1.33.1 ([#​234](https://www.github.com/googleapis/java-shared-dependencies/issues/234)) ([67cc384](https://www.github.com/googleapis/java-shared-dependencies/commit/67cc384bacab8592d5bbc92db2469affee473eb7)) - update dependency com.google.auth:google-auth-library-bom to v0.22.1 ([#​229](https://www.github.com/googleapis/java-shared-dependencies/issues/229)) ([1c13161](https://www.github.com/googleapis/java-shared-dependencies/commit/1c13161fa289cd5f3923f389fd5b14f3b7b4a84d)) - update dependency com.google.auth:google-auth-library-bom to v0.22.2 ([#​235](https://www.github.com/googleapis/java-shared-dependencies/issues/235)) ([67434eb](https://www.github.com/googleapis/java-shared-dependencies/commit/67434eb4bb0789abcabb3055155672b2c2e70125)) - update iam.version to v1.0.4 ([#​231](https://www.github.com/googleapis/java-shared-dependencies/issues/231)) ([5edf99e](https://www.github.com/googleapis/java-shared-dependencies/commit/5edf99e0149a1b70eb52b8921e9eb04fb84d9160))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index df384fadd5f4..48999a0ed020 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.16.1 + 0.17.0 pom import From ad4efc333e40608bb563c7372e65263e0c855ae3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Dec 2020 23:32:11 +0100 Subject: [PATCH 0271/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v16.2.0 (#304) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:libraries-bom](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | minor | `16.1.0` -> `16.2.0` | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 974bf1c3a060..cee3617f995a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 16.1.0 + 16.2.0 pom import From bdcdd3b1b43ca7a685d134e38067a8f707feef29 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 16 Dec 2020 08:44:26 -0800 Subject: [PATCH 0272/1979] ci(java): ignore bot users for generate-files-bot (#305) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/88a97252-efa1-41f8-87c9-1a1ef3bd41cf/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/3f67ceece7e797a5736a25488aae35405649b90b --- java-spanner-jdbc/.github/generated-files-bot.yml | 4 ++++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/generated-files-bot.yml b/java-spanner-jdbc/.github/generated-files-bot.yml index 20f3acc28172..47c2ba132e01 100644 --- a/java-spanner-jdbc/.github/generated-files-bot.yml +++ b/java-spanner-jdbc/.github/generated-files-bot.yml @@ -5,3 +5,7 @@ externalManifests: - type: json file: '.github/readme/synth.metadata/synth.metadata' jsonpath: '$.generatedFiles[*]' +ignoreAuthors: +- 'renovate-bot' +- 'yoshi-automation' +- 'release-please[bot]' diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index f231fec1c2f3..da0f470af899 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "5531536d406e1fe3043a9d379c8102f1b0a5ade7" + "sha": "8e01a57aad6d2ea85b37c5782d566b1587d0f41c" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5d11bd2888c38ce1fb6fa6bf25494a4219a73928" + "sha": "3f67ceece7e797a5736a25488aae35405649b90b" } } ], From 115de470e0a6b91deab838234a47191768a717d1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Dec 2020 21:28:02 +0000 Subject: [PATCH 0273/1979] chore: release 1.18.2 (#303) :robot: I have created a release \*beep\* \*boop\* --- ### [1.18.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.1...v1.18.2) (2020-12-16) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v0.17.0 ([#302](https://www.github.com/googleapis/java-spanner-jdbc/issues/302)) ([17b4903](https://www.github.com/googleapis/java-spanner-jdbc/commit/17b490393cda2fdad7b526269ec0347a8e9e93c5)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 7be3b0032e70..8a4ac6462419 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.18.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.1...v1.18.2) (2020-12-16) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.17.0 ([#302](https://www.github.com/googleapis/java-spanner-jdbc/issues/302)) ([9a2efa1](https://www.github.com/googleapis/java-spanner-jdbc/commit/9a2efa14ad402130ca542d5b8b9f9bbb58587404)) + ### [1.18.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.0...v1.18.1) (2020-12-14) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 48999a0ed020..0372b25111ca 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.2-SNAPSHOT + 1.18.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 24743c4256a6..ae10b65379c7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.2-SNAPSHOT + 1.18.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8960c0693df3..4ce3c806154e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.1:1.18.2-SNAPSHOT +google-cloud-spanner-jdbc:1.18.2:1.18.2 From 463cfbc09357f312808dc26ff47a46f673074410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 17 Dec 2020 00:16:52 +0100 Subject: [PATCH 0274/1979] deps: update spanner to 3.1.2 (#306) --- java-spanner-jdbc/pom.xml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0372b25111ca..4047cdc7b946 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 3.0.5 + 3.1.2 pom import @@ -105,6 +105,11 @@ com.google.cloud google-cloud-spanner
    + + + io.grpc + grpc-alts + com.google.protobuf protobuf-java @@ -145,10 +150,6 @@ com.google.api.grpc proto-google-cloud-spanner-v1 - - com.google.api.grpc - proto-google-cloud-spanner-v1 - @@ -295,6 +296,8 @@ maven-dependency-plugin + + io.grpc:grpc-alts com.google.api:gax-grpc com.google.cloud:google-cloud-core-grpc com.google.api.grpc:grpc-google-cloud-spanner-v1 From 87d771f7123de3b551b3c58fb00e03db124c8832 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 17 Dec 2020 00:17:50 +0100 Subject: [PATCH 0275/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.18.2 (#307) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index df43e40370e0..8dbf1e05129b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.0 + 1.18.2 From 1d5317925000328dc10fdd0ed55305919636368b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 16 Dec 2020 15:44:04 -0800 Subject: [PATCH 0276/1979] chore: regenerate README (#309) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2020-12-16 23:19:08,755 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2020-12-16 23:19:09,646 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/d04e13d0-1c27-4d1c-909d-c732b8561d9f/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 71f3c74f8632..6ea3040199c9 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "53b459e334fdbf391d080817f8b782cff3b12d1b" + "sha": "bf2cdae2b42d3b3c3bc5bb01deee3a32e66ebd0e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "996775eca5fd934edac3c2ae34b80ff0395b1717" + "sha": "41e998d5afdc2c2143a23c9b044b9931936f7318" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c623b61a4736..fde4a8872656 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,17 +17,17 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.18.0 + 1.18.2 ``` If you are using Gradle, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.2' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.2" ``` ## Authentication From 0d2b4c6a03ee18f45769728f5a0a55fc6e0146c5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Dec 2020 23:50:03 +0000 Subject: [PATCH 0277/1979] chore: release 1.18.3-SNAPSHOT (#308) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4047cdc7b946..2383c3b3b6dd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.2 + 1.18.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ae10b65379c7..52458b928c7e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.2 + 1.18.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4ce3c806154e..4280217202c9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.2:1.18.2 +google-cloud-spanner-jdbc:1.18.2:1.18.3-SNAPSHOT From beffcfd73784afc21abc213e8b66ba96e1d7c29e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 17 Dec 2020 00:12:05 +0000 Subject: [PATCH 0278/1979] chore: release 1.18.3 (#310) :robot: I have created a release \*beep\* \*boop\* --- ### [1.18.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.2...v1.18.3) (2020-12-16) ### Dependencies * update spanner to 3.1.2 ([#306](https://www.github.com/googleapis/java-spanner-jdbc/issues/306)) ([463cfbc](https://www.github.com/googleapis/java-spanner-jdbc/commit/463cfbc09357f312808dc26ff47a46f673074410)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8a4ac6462419..b7a9ece56304 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [1.18.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.2...v1.18.3) (2020-12-16) + + +### Dependencies + +* update spanner to 3.1.2 ([#306](https://www.github.com/googleapis/java-spanner-jdbc/issues/306)) ([596e8ed](https://www.github.com/googleapis/java-spanner-jdbc/commit/596e8ed01dc8ffc01c37b233f688d163b8693f85)) + ### [1.18.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.1...v1.18.2) (2020-12-16) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2383c3b3b6dd..0483a60a62a7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.3-SNAPSHOT + 1.18.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 52458b928c7e..f3a997305c73 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.3-SNAPSHOT + 1.18.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4280217202c9..b2dabc8200cc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.2:1.18.3-SNAPSHOT +google-cloud-spanner-jdbc:1.18.3:1.18.3 From c3a41313b5cc2a56af147109d791eaa1e78890a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 18 Dec 2020 06:43:12 +0100 Subject: [PATCH 0279/1979] feat: allow unknown properties in connection url with lenient mode (#284) * feat: allow unknown properties in connection url with lenient mode * Update src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java Co-authored-by: yoshi-code-bot <70984784+yoshi-code-bot@users.noreply.github.com> * fix: add credentials to prevent the use of env credentials Co-authored-by: yoshi-code-bot <70984784+yoshi-code-bot@users.noreply.github.com> --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 7 ++++- .../cloud/spanner/jdbc/JdbcDriverTest.java | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 65b944dbbcb8..d2a2fea2e436 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -28,6 +28,7 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; import java.util.Map.Entry; import java.util.Properties; import java.util.logging.Logger; @@ -172,7 +173,11 @@ public Connection connect(String url, Properties info) throws SQLException { // Connection API String connectionUri = appendPropertiesToUrl(url.substring(5), info); ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build(); - return new JdbcConnection(url, options); + JdbcConnection connection = new JdbcConnection(url, options); + if (options.getWarnings() != null) { + connection.pushWarning(new SQLWarning(options.getWarnings())); + } + return connection; } } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 9eb1047487e9..014d9bde0ae5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -161,4 +161,32 @@ public String apply(DriverPropertyInfo input) { }); assertThat(driverPropertyNames).containsExactlyElementsIn(validConnectionPropertyNames); } + + @Test + public void testLenient() throws SQLException { + // With lenient=true the driver should accept unknown properties and only generate a warning. + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner://localhost:%d/projects/p/instances/i/databases/d?usePlainText=true;credentials=%s;lenient=true;foo=bar", + server.getPort(), TEST_KEY_PATH))) { + assertThat(connection.isClosed()).isFalse(); + assertThat((Throwable) connection.getWarnings()).isNotNull(); + assertThat(connection.getWarnings().getMessage()).contains("foo"); + } + + // Without lenient the driver should throw an exception for unknown properties. + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner://localhost:%d/projects/p/instances/i/databases/d?usePlainText=true;credentials=%s;foo=bar", + server.getPort(), TEST_KEY_PATH))) { + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException jdbc = (JdbcSqlException) e; + assertThat(jdbc.getMessage()).contains("foo"); + assertThat(jdbc.getCode()).isEqualTo(Code.INVALID_ARGUMENT); + } + } } From 26b9f83ad4eaeef7e04746870aaf229437c6bd88 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 29 Dec 2020 14:37:50 -0800 Subject: [PATCH 0280/1979] chore(java): remove formatter action Source-Author: Jeff Ching Source-Date: Tue Dec 29 10:50:17 2020 -0800 Source-Repo: googleapis/synthtool Source-Sha: 6133907dbb3ddab204a17a15d5c53ec0aae9b033 Source-Link: https://github.com/googleapis/synthtool/commit/6133907dbb3ddab204a17a15d5c53ec0aae9b033 --- .../.github/workflows/formatting.yaml | 25 ------------------- java-spanner-jdbc/synth.metadata | 5 ++-- 2 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 java-spanner-jdbc/.github/workflows/formatting.yaml diff --git a/java-spanner-jdbc/.github/workflows/formatting.yaml b/java-spanner-jdbc/.github/workflows/formatting.yaml deleted file mode 100644 index 6844407b4d97..000000000000 --- a/java-spanner-jdbc/.github/workflows/formatting.yaml +++ /dev/null @@ -1,25 +0,0 @@ -on: - pull_request_target: - types: [opened, synchronize] - branches: - - master -name: format -jobs: - format-code: - runs-on: ubuntu-latest - env: - ACCESS_TOKEN: ${{ secrets.YOSHI_CODE_BOT_TOKEN }} - steps: - - uses: actions/checkout@v2 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} - - uses: actions/setup-java@v1 - with: - java-version: 11 - - run: "mvn com.coveo:fmt-maven-plugin:format" - - uses: googleapis/code-suggester@v1 - with: - command: review - pull_number: ${{ github.event.pull_request.number }} - git_dir: '.' diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index da0f470af899..f442a9f210d5 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "8e01a57aad6d2ea85b37c5782d566b1587d0f41c" + "sha": "0e557ef7657cae04d263daa6717ee34290338b7a" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "3f67ceece7e797a5736a25488aae35405649b90b" + "sha": "6133907dbb3ddab204a17a15d5c53ec0aae9b033" } } ], @@ -30,7 +30,6 @@ ".github/workflows/approve-readme.yaml", ".github/workflows/auto-release.yaml", ".github/workflows/ci.yaml", - ".github/workflows/formatting.yaml", ".github/workflows/samples.yaml", ".kokoro/build.bat", ".kokoro/build.sh", From 8372245335c418fbfd0f7dd0caddbbc13e15d2ae Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 7 Jan 2021 11:25:41 +1100 Subject: [PATCH 0281/1979] chore: release 1.18.4-SNAPSHOT (#313) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0483a60a62a7..2eb4c5d53361 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.3 + 1.18.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f3a997305c73..50cb9e519750 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.3 + 1.18.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b2dabc8200cc..0df459ffac8e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.3:1.18.3 +google-cloud-spanner-jdbc:1.18.3:1.18.4-SNAPSHOT From 2a233e11baea04146e415631b311b4ff1cd5d0cd Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 6 Jan 2021 16:46:07 -0800 Subject: [PATCH 0282/1979] chore: regenerate README (#315) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-01-07 00:27:55,212 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-01-07 00:27:56,101 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/89773a7d-6719-43aa-97b1-4ac196b3ee3d/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 6ea3040199c9..6230cb543154 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "bf2cdae2b42d3b3c3bc5bb01deee3a32e66ebd0e" + "sha": "5115ed8f45b4fe1c0424d25190cdfc8681ef388f" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "41e998d5afdc2c2143a23c9b044b9931936f7318" + "sha": "a3e990f3545dc8ccd384a75d20ce9cb185ca6a28" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index fde4a8872656..ae46cf8b02a7 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,17 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.18.2 + 1.18.3 ``` -If you are using Gradle, add this to your dependencies +If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.2' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.3' ``` + If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.3" ``` ## Authentication From b4435f72dbc958b9fc9ff6825cddde388ddb0f13 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 12 Jan 2021 12:51:28 +0100 Subject: [PATCH 0283/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v16.2.1 (#318) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index cee3617f995a..6cef2b5fde41 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 16.2.0 + 16.2.1 pom import From 91c57bc4218aef513086b8a03c2e76a77a66e030 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 12 Jan 2021 12:51:47 +0100 Subject: [PATCH 0284/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.18.3 (#317) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 8dbf1e05129b..5df6d9a72d7b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.2 + 1.18.3 From f5e80e2c5c5ac2ca9ad79283b3572c6cdec5096b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 14 Jan 2021 01:48:26 +0100 Subject: [PATCH 0285/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.18.0 (#320) [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [com.google.cloud:google-cloud-shared-dependencies](https://togithub.com/googleapis/java-shared-dependencies) | minor | `0.17.0` -> `0.18.0` | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.18.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0180-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0171v0180-2021-01-13) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.17.1...v0.18.0) ##### Features - add commons-codec to dependencyManagement ([#​251](https://www.github.com/googleapis/java-shared-dependencies/issues/251)) ([4ee990d](https://www.github.com/googleapis/java-shared-dependencies/commit/4ee990d79c9207c81155f6ee9279308a2d4d0f9d)) ##### Dependencies - update dependency com.google.errorprone:error_prone_annotations to v2.5.0 ([#​247](https://www.github.com/googleapis/java-shared-dependencies/issues/247)) ([37c0861](https://www.github.com/googleapis/java-shared-dependencies/commit/37c0861cfb89f13a0682c98067c633b13b30b827)) ##### [0.17.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.17.0...v0.17.1) (2021-01-12) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.12.1 ([#​245](https://www.github.com/googleapis/java-shared-dependencies/issues/245)) ([5ffc8a0](https://www.github.com/googleapis/java-shared-dependencies/commit/5ffc8a0d173ea0222ac9610ece0ac2aeb1d17f27)) ### [`v0.17.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0171-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0170v0171-2021-01-12) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.17.0...v0.17.1)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2eb4c5d53361..ae04a0882366 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.17.0 + 0.18.0 pom import From 8a9be527e47cfc89ecbc85d250b700b843b36fb7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 18 Jan 2021 00:36:53 +0100 Subject: [PATCH 0286/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v3.3.1 (#319) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ae04a0882366..97977984fb5a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 3.1.2 + 3.3.1 pom import From b90c64d6bcf6ff4cf318b17200f516b03a3989e2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 18 Jan 2021 00:37:15 +0100 Subject: [PATCH 0287/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v16.3.0 (#321) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6cef2b5fde41..69cbd880c542 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 16.2.1 + 16.3.0 pom import From 234a136b1ea6f7603a4fecf5a4f4f9e298400cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 18 Jan 2021 00:38:46 +0100 Subject: [PATCH 0288/1979] fix: getting resultset metadata twice could skip row (#323) * fix: getting resultset metadata twice could skip row If the client application would call ResultSet#getMetaData() more than once **before** calling ResultSet#next(), the ResultSet would skip a row when the rows would be consumed. Fixes #322 * test: add test for getMetaData twice --- .../cloud/spanner/jdbc/JdbcResultSet.java | 2 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 3f10b0c18853..c4ca6b5e220d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -547,7 +547,7 @@ public InputStream getBinaryStream(String columnLabel) throws SQLException { @Override public JdbcResultSetMetaData getMetaData() throws SQLException { checkClosed(); - if (isBeforeFirst()) { + if (isBeforeFirst() && !nextCalledForMetaData) { // do a call to next() on the underlying resultset to initialize metadata nextCalledForMetaData = true; nextCalledForMetaDataResult = spanner.next(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 9429288d2fd3..2ad4a6d4831c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.cloud.ByteArray; import com.google.cloud.Date; @@ -802,6 +803,32 @@ public void testGetMetaData() throws SQLException { assertNotNull(metadata); } + @Test + public void testGetMetaDataBeforeNext() throws SQLException { + ResultSet spannerResultSet = mock(ResultSet.class); + when(spannerResultSet.next()).thenReturn(true, false); + + JdbcResultSet resultSet = JdbcResultSet.of(spannerResultSet); + assertNotNull(resultSet.getMetaData()); + assertTrue(resultSet.next()); + assertFalse(resultSet.next()); + } + + @Test + public void testGetMetaDataTwiceBeforeNext() throws SQLException { + ResultSet spannerResultSet = mock(ResultSet.class); + when(spannerResultSet.next()).thenReturn(true, false); + + JdbcResultSet resultSet = JdbcResultSet.of(spannerResultSet); + assertNotNull(resultSet.getMetaData()); + assertNotNull(resultSet.getMetaData()); + + // This would have returned false before the fix in + // https://github.com/googleapis/java-spanner-jdbc/pull/323 + assertTrue(resultSet.next()); + assertFalse(resultSet.next()); + } + @Test public void testFindColumn() throws SQLException { assertEquals(2, subject.findColumn(STRING_COL_NOT_NULL)); From 98e6ace60f52d85495548efd348f1acc3394ef14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 18 Jan 2021 00:50:09 +0100 Subject: [PATCH 0289/1979] feat: support default ClientInfo properties (#324) --- .../spanner/jdbc/AbstractJdbcConnection.java | 35 +++++++++-- .../cloud/spanner/jdbc/JdbcConnection.java | 2 +- .../spanner/jdbc/JdbcDatabaseMetaData.java | 61 +++++++++++++++++-- .../JdbcConnectionGeneratedSqlScriptTest.java | 20 +++--- .../spanner/jdbc/JdbcConnectionTest.java | 49 +++++++++++++-- .../jdbc/JdbcDatabaseMetaDataTest.java | 12 ++++ 6 files changed, 157 insertions(+), 22 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index aad5ad82c7ec..385a46faec91 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -45,19 +45,21 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper private static final String ABORT_UNSUPPORTED = "Abort is not supported"; private static final String NETWORK_TIMEOUT_UNSUPPORTED = "Network timeout is not supported"; static final String CLIENT_INFO_NOT_SUPPORTED = - "Cloud Spanner does not support any ClientInfo properties"; + "Cloud Spanner does not support ClientInfo property %s"; private final String connectionUrl; private final ConnectionOptions options; private final com.google.cloud.spanner.connection.Connection spanner; + private final Properties clientInfo; private SQLWarning firstWarning = null; private SQLWarning lastWarning = null; - AbstractJdbcConnection(String connectionUrl, ConnectionOptions options) { + AbstractJdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException { this.connectionUrl = connectionUrl; this.options = options; this.spanner = options.getConnection(); + this.clientInfo = new Properties(JdbcDatabaseMetaData.getDefaultClientInfoProperties()); } /** Return the corresponding {@link com.google.cloud.spanner.connection.Connection} */ @@ -168,8 +170,10 @@ public SQLXML createSQLXML() throws SQLException { @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { + Properties supported = null; try { checkClosed(); + supported = JdbcDatabaseMetaData.getDefaultClientInfoProperties(); } catch (SQLException e) { if (e instanceof JdbcSqlException) { throw JdbcSqlExceptionFactory.clientInfoException( @@ -178,7 +182,23 @@ public void setClientInfo(String name, String value) throws SQLClientInfoExcepti throw JdbcSqlExceptionFactory.clientInfoException(e.getMessage(), Code.UNKNOWN); } } - pushWarning(new SQLWarning(CLIENT_INFO_NOT_SUPPORTED)); + if (value == null) { + throw JdbcSqlExceptionFactory.clientInfoException( + "Null-value is not allowed for client info.", Code.INVALID_ARGUMENT); + } + if (value.length() > JdbcDatabaseMetaData.MAX_CLIENT_INFO_VALUE_LENGTH) { + throw JdbcSqlExceptionFactory.clientInfoException( + String.format( + "Max length of value is %d characters.", + JdbcDatabaseMetaData.MAX_CLIENT_INFO_VALUE_LENGTH), + Code.INVALID_ARGUMENT); + } + name = name.toUpperCase(); + if (supported.containsKey(name)) { + clientInfo.setProperty(name, value); + } else { + pushWarning(new SQLWarning(String.format(CLIENT_INFO_NOT_SUPPORTED, name))); + } } @Override @@ -193,19 +213,22 @@ public void setClientInfo(Properties properties) throws SQLClientInfoException { throw JdbcSqlExceptionFactory.clientInfoException(e.getMessage(), Code.UNKNOWN); } } - pushWarning(new SQLWarning(CLIENT_INFO_NOT_SUPPORTED)); + clientInfo.clear(); + for (String property : properties.stringPropertyNames()) { + setClientInfo(property, properties.getProperty(property)); + } } @Override public String getClientInfo(String name) throws SQLException { checkClosed(); - return null; + return clientInfo.getProperty(name.toUpperCase()); } @Override public Properties getClientInfo() throws SQLException { checkClosed(); - return null; + return (Properties) clientInfo.clone(); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 3d79c5efb9b4..6c23db4960cb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -53,7 +53,7 @@ class JdbcConnection extends AbstractJdbcConnection { private Map> typeMap = new HashMap<>(); - JdbcConnection(String connectionUrl, ConnectionOptions options) { + JdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException { super(connectionUrl, options); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 508a2c3715e1..a5d79b14e9bf 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -36,6 +36,7 @@ import java.sql.Types; import java.util.Arrays; import java.util.Collections; +import java.util.Properties; import java.util.Scanner; /** {@link DatabaseMetaData} implementation for Cloud Spanner */ @@ -1495,16 +1496,68 @@ public boolean autoCommitFailureClosesAllResultSets() throws SQLException { return false; } - @Override - public ResultSet getClientInfoProperties() throws SQLException { + /** + * The max length for client info values is 63 to make them fit in Cloud Spanner session labels. + */ + static final int MAX_CLIENT_INFO_VALUE_LENGTH = 63; + + static Properties getDefaultClientInfoProperties() throws SQLException { + Properties info = new Properties(); + try (ResultSet rs = getDefaultClientInfo()) { + while (rs.next()) { + info.put(rs.getString("NAME"), rs.getString("DEFAULT_VALUE")); + } + } + return info; + } + + private static ResultSet getDefaultClientInfo() throws SQLException { return JdbcResultSet.of( ResultSets.forRows( Type.struct( StructField.of("NAME", Type.string()), - StructField.of("MAX_LEN", Type.string()), + StructField.of("MAX_LEN", Type.int64()), StructField.of("DEFAULT_VALUE", Type.string()), StructField.of("DESCRIPTION", Type.string())), - Collections.emptyList())); + Arrays.asList( + Struct.newBuilder() + .set("NAME") + .to("APPLICATIONNAME") + .set("MAX_LEN") + .to(MAX_CLIENT_INFO_VALUE_LENGTH) + .set("DEFAULT_VALUE") + .to("") + .set("DESCRIPTION") + .to("The name of the application currently utilizing the connection.") + .build(), + Struct.newBuilder() + .set("NAME") + .to("CLIENTHOSTNAME") + .set("MAX_LEN") + .to(MAX_CLIENT_INFO_VALUE_LENGTH) + .set("DEFAULT_VALUE") + .to("") + .set("DESCRIPTION") + .to( + "The hostname of the computer the application using the connection is running on.") + .build(), + Struct.newBuilder() + .set("NAME") + .to("CLIENTUSER") + .set("MAX_LEN") + .to(MAX_CLIENT_INFO_VALUE_LENGTH) + .set("DEFAULT_VALUE") + .to("") + .set("DESCRIPTION") + .to( + "The name of the user that the application using the connection is performing work for. " + + "This may not be the same as the user name that was used in establishing the connection.") + .build()))); + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return getDefaultClientInfo(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index b835668bf009..b818c63fe4ea 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -19,12 +19,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.connection.ConnectionImplTest; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import java.sql.SQLException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -46,13 +48,17 @@ public GenericConnection getConnection() { com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); when(options.getConnection()).thenReturn(spannerConnection); - JdbcConnection connection = - new JdbcConnection( - "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", - options); - JdbcGenericConnection res = JdbcGenericConnection.of(connection); - res.setStripCommentsBeforeExecute(true); - return res; + try { + JdbcConnection connection = + new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options); + JdbcGenericConnection res = JdbcGenericConnection.of(connection); + res.setStripCommentsBeforeExecute(true); + return res; + } catch (SQLException e) { + throw SpannerExceptionFactory.asSpannerException(e); + } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 82e26d03a10f..27389b4c02d8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -59,7 +59,7 @@ public class JdbcConnectionTest { Type.struct(StructField.of("", Type.int64())), Arrays.asList(Struct.newBuilder().set("").to(1L).build())); - private JdbcConnection createConnection(ConnectionOptions options) { + private JdbcConnection createConnection(ConnectionOptions options) throws SQLException { com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); when(options.getConnection()).thenReturn(spannerConnection); @@ -405,14 +405,24 @@ public void testWarnings() throws SQLException { } @Test - public void testSetClientInfo() throws SQLException { + public void getDefaultClientInfo() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + Properties defaultProperties = connection.getClientInfo(); + assertThat(defaultProperties.stringPropertyNames()) + .containsExactly("APPLICATIONNAME", "CLIENTHOSTNAME", "CLIENTUSER"); + } + } + + @Test + public void testSetInvalidClientInfo() throws SQLException { ConnectionOptions options = mock(ConnectionOptions.class); try (JdbcConnection connection = createConnection(options)) { assertThat((Object) connection.getWarnings()).isNull(); connection.setClientInfo("test", "foo"); assertThat((Object) connection.getWarnings()).isNotNull(); assertThat(connection.getWarnings().getMessage()) - .isEqualTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED); + .isEqualTo(String.format(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED, "TEST")); connection.clearWarnings(); assertThat((Object) connection.getWarnings()).isNull(); @@ -422,7 +432,38 @@ public void testSetClientInfo() throws SQLException { connection.setClientInfo(props); assertThat((Object) connection.getWarnings()).isNotNull(); assertThat(connection.getWarnings().getMessage()) - .isEqualTo(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED); + .isEqualTo(String.format(AbstractJdbcConnection.CLIENT_INFO_NOT_SUPPORTED, "TEST")); + } + } + + @Test + public void testSetClientInfo() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + try (JdbcConnection connection = createConnection(options)) { + try (ResultSet validProperties = connection.getMetaData().getClientInfoProperties()) { + while (validProperties.next()) { + assertThat((Object) connection.getWarnings()).isNull(); + String name = validProperties.getString("NAME"); + + connection.setClientInfo(name, "new-client-info-value"); + assertThat((Object) connection.getWarnings()).isNull(); + assertThat(connection.getClientInfo(name)).isEqualTo("new-client-info-value"); + + Properties props = new Properties(); + props.setProperty(name.toLowerCase(), "some-other-value"); + connection.setClientInfo(props); + assertThat((Object) connection.getWarnings()).isNull(); + assertThat(connection.getClientInfo(name)).isEqualTo("some-other-value"); + assertThat(connection.getClientInfo().keySet()).hasSize(1); + for (String key : connection.getClientInfo().stringPropertyNames()) { + if (key.equals(name)) { + assertThat(connection.getClientInfo().getProperty(key)).isEqualTo("some-other-value"); + } else { + assertThat(connection.getClientInfo().getProperty(key)).isEqualTo(""); + } + } + } + } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index b3697a071aec..ac8ab7bf6371 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -322,6 +322,18 @@ public void testGetClientInfoProperties() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getClientInfoProperties()) { + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("APPLICATIONNAME"))); + assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("CLIENTHOSTNAME"))); + assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + + assertThat(rs.next(), is(true)); + assertThat(rs.getString("NAME"), is(equalTo("CLIENTUSER"))); + assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + assertThat(rs.next(), is(false)); ResultSetMetaData rsmd = rs.getMetaData(); assertThat(rsmd.getColumnCount(), is(equalTo(4))); From 6afee8d5a4346ae89763df9a7675bd20c7b7f5f3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 20 Jan 2021 21:11:05 +0100 Subject: [PATCH 0290/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v3.3.2 (#325) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97977984fb5a..146c7ee51a7c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 3.3.1 + 3.3.2 pom import From 84a1099e0f4f10725d32873631f0fba3e1056f6b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 25 Jan 2021 18:30:03 +0100 Subject: [PATCH 0291/1979] test(deps): update dependency com.google.truth:truth to v1.1.2 (#328) [![WhiteSource 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.truth:truth](com/google/truth/truth) | `1.1` -> `1.1.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.2/compatibility-slim/1.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.2/confidence-slim/1.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5df6d9a72d7b..029ad86c420d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1 + 1.1.2 test
    diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 50cb9e519750..36049d482433 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1 + 1.1.2 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 69cbd880c542..be53fa13e9b2 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.1 + 1.1.2 test From 812e54d3284b9d424b4f7f9e387c58dabdf6d022 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 26 Jan 2021 19:30:18 +0100 Subject: [PATCH 0292/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.10.0 (#331) [![WhiteSource 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) | `0.9.4` -> `0.10.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.10.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.10.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.10.0/compatibility-slim/0.9.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.10.0/confidence-slim/0.9.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.10.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​0100-httpswwwgithubcomgoogleapisjava-shared-configcomparev094v0100-2021-01-21) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.9.4...v0.10.0) ##### Features - adding pom profile to generate docfx yml from javadoc ([#​213](https://www.github.com/googleapis/java-shared-config/issues/213)) ([3527c47](https://www.github.com/googleapis/java-shared-config/commit/3527c47ff413d415f87fccca84358da2c837841d)) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v8.39 ([#​209](https://www.github.com/googleapis/java-shared-config/issues/209)) ([fb53922](https://www.github.com/googleapis/java-shared-config/commit/fb539226d407001822a56c7fff792922cd85d1fe)) ##### [0.9.4](https://www.github.com/googleapis/java-shared-config/compare/v0.9.3...v0.9.4) (2020-10-21) ##### Documentation - Latest for Cloud-RAD ([#​199](https://www.github.com/googleapis/java-shared-config/issues/199)) ([34712af](https://www.github.com/googleapis/java-shared-config/commit/34712afac58aa0d148f0843026b3ff770ee030c2)) ##### [0.9.3](https://www.github.com/googleapis/java-shared-config/compare/v0.9.2...v0.9.3) (2020-10-15) ##### Dependencies - update auto-value-annotation.version to v1.7.4 ([#​157](https://www.github.com/googleapis/java-shared-config/issues/157)) ([5d7e394](https://www.github.com/googleapis/java-shared-config/commit/5d7e394d964010a3e32af492cec4be85aabc3ebf)) ##### [0.9.2](https://www.github.com/googleapis/java-shared-config/compare/v0.9.1...v0.9.2) (2020-07-02) ##### Dependencies - update dependency org.apache.maven.surefire:surefire-junit47 to v3.0.0-M5 ([#​180](https://www.github.com/googleapis/java-shared-config/issues/180)) ([802d9c5](https://www.github.com/googleapis/java-shared-config/commit/802d9c528d34b386face69ca75a014ce57fc3ac1)) ##### [0.9.1](https://www.github.com/googleapis/java-shared-config/compare/v0.9.0...v0.9.1) (2020-07-01) ##### Bug Fixes - maven-dependency-plugin configuration breaking downstream config ([#​174](https://www.github.com/googleapis/java-shared-config/issues/174)) ([507217f](https://www.github.com/googleapis/java-shared-config/commit/507217fe509cd4f16eb50c8075ab43229238e08d)) ##### Documentation - change Devsite output path to /java/docs/reference ([#​176](https://www.github.com/googleapis/java-shared-config/issues/176)) ([8b98af5](https://www.github.com/googleapis/java-shared-config/commit/8b98af54bf503d97bb86b6d02a5c4301b39384e1))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 146c7ee51a7c..173c0a84fa3c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.9.4 + 0.10.0 From 7255645fd1d14692e0c7509d78b105505ca68bcb Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 26 Jan 2021 11:18:06 -0800 Subject: [PATCH 0293/1979] chore: adding docfx doclet resource (#330) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/1376fa4d-7801-4cd6-9cc9-093147d097de/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/3816b080296d4d52975079fd26c110dd26ba25af --- java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg | 3 +++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index 33cb6e725134..fa2437d6eeec 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -27,3 +27,6 @@ before_action { } } } + +# Downloads docfx doclet resource. This will be in ${KOKORO_GFILE_DIR}/ +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index f442a9f210d5..e4e8ea454ec0 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "0e557ef7657cae04d263daa6717ee34290338b7a" + "sha": "7e5a13374ec6f343b2b2ea2320e8c12f895f3e87" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6133907dbb3ddab204a17a15d5c53ec0aae9b033" + "sha": "3816b080296d4d52975079fd26c110dd26ba25af" } } ], From 1884cb2567b4aaefb4d6fc92800aa5726ed0eaa8 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 28 Jan 2021 22:14:33 -0800 Subject: [PATCH 0294/1979] build: migrate to flakybot (#336) --- java-spanner-jdbc/.kokoro/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index b4005cc6879f..27d9f2a1c640 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -110,8 +110,8 @@ bash .kokoro/coerce_logs.sh if [[ "${ENABLE_BUILD_COP}" == "true" ]] then - chmod +x ${KOKORO_GFILE_DIR}/linux_amd64/buildcop - ${KOKORO_GFILE_DIR}/linux_amd64/buildcop -repo=googleapis/java-spanner-jdbc + chmod +x ${KOKORO_GFILE_DIR}/linux_amd64/flakybot + ${KOKORO_GFILE_DIR}/linux_amd64/flakybot -repo=googleapis/java-spanner-jdbc fi echo "exiting with ${RETURN_CODE}" From 793cdc7672b27531b963c9291ecf932f31a50905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 1 Feb 2021 00:31:48 +0100 Subject: [PATCH 0295/1979] feat: support creating shaded jars (#333) Some applications that load multiple JDBC drivers may run into dependency conflicts if other JDBC drivers use the same dependencies but different versions. This problem can be mitigated by creating a jar with shaded dependencies. This change adds a Maven profile for creating shaded jars. Fixes #316 --- java-spanner-jdbc/.readme-partials.yaml | 11 +++++++ java-spanner-jdbc/pom.xml | 44 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml index 47e65e1488b5..c407ffc2c4b2 100644 --- a/java-spanner-jdbc/.readme-partials.yaml +++ b/java-spanner-jdbc/.readme-partials.yaml @@ -23,3 +23,14 @@ custom_content: | } } ``` + + ### Creating a Shaded Jar + + A jar with all dependencies included is automatically generated when you execute `mvn package`. + The dependencies in this jar are not shaded. To create a jar with shaded dependencies you must + activate the `shade` profile like this: + + ``` + mvn package -Pshade + ``` + \ No newline at end of file diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 173c0a84fa3c..b971e4e5f74a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -309,6 +309,50 @@ + + + + shade + + + + org.apache.maven.plugins + maven-shade-plugin + + + + com + com.google.cloud.spanner.jdbc.shaded.com + + com.google.cloud.spanner.** + + + + android + com.google.cloud.spanner.jdbc.shaded.android + + + io + com.google.cloud.spanner.jdbc.shaded.io + + io.grpc.netty.shaded.** + + + + org + com.google.cloud.spanner.jdbc.shaded.org + + org.conscrypt.** + + + + + + + + + + From 5a0c51889c771d257b67b5e3993339f3e6c31666 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 31 Jan 2021 15:50:01 -0800 Subject: [PATCH 0296/1979] chore: regenerate README (#337) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-01-31 23:34:10,379 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-01-31 23:34:11,331 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/c457d563-a78f-4df4-9e52-78d49fa9db85/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 6230cb543154..69ebebb4e41b 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "5115ed8f45b4fe1c0424d25190cdfc8681ef388f" + "sha": "8b4e50d10a9121334be3d8b5ed0d8fc9ff63c182" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "a3e990f3545dc8ccd384a75d20ce9cb185ca6a28" + "sha": "d1bb9173100f62c0cfc8f3138b62241e7f47ca6a" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ae46cf8b02a7..bcdfb375fc21 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -84,6 +84,16 @@ try (Connection connection = } ``` +### Creating a Shaded Jar + +A jar with all dependencies included is automatically generated when you execute `mvn package`. +The dependencies in this jar are not shaded. To create a jar with shaded dependencies you must +activate the `shade` profile like this: + + ``` + mvn package -Pshade + ``` + From 3ee18bc910912cd88b0df56a5f8fa1d13ed4d284 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 3 Feb 2021 09:43:19 -0800 Subject: [PATCH 0297/1979] chore: Re-generated to pick up changes from synthtool. (#341) * changes without context autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. * build: migrate to flakybot Source-Author: Justin Beckwith Source-Date: Thu Jan 28 22:22:38 2021 -0800 Source-Repo: googleapis/synthtool Source-Sha: d1bb9173100f62c0cfc8f3138b62241e7f47ca6a Source-Link: https://github.com/googleapis/synthtool/commit/d1bb9173100f62c0cfc8f3138b62241e7f47ca6a * build(java): generate docfx yml on release * feat: generate docfx yml on release * fix: updates name variable * fix: remove non needed resource * fix: update date Source-Author: Emily Ball Source-Date: Mon Feb 1 15:24:59 2021 -0800 Source-Repo: googleapis/synthtool Source-Sha: 5de29e9434b63ea6d7e46dc348521c62969af1a1 Source-Link: https://github.com/googleapis/synthtool/commit/5de29e9434b63ea6d7e46dc348521c62969af1a1 * build(java): run linkage monitor as GitHub action Source-Author: Tomo Suzuki Source-Date: Tue Feb 2 16:20:26 2021 -0500 Source-Repo: googleapis/synthtool Source-Sha: e935c9ecb47da0f2e054f5f1845f7cf7c95fa625 Source-Link: https://github.com/googleapis/synthtool/commit/e935c9ecb47da0f2e054f5f1845f7cf7c95fa625 --- java-spanner-jdbc/.github/workflows/ci.yaml | 13 ++++- java-spanner-jdbc/.kokoro/linkage-monitor.sh | 46 ---------------- .../.kokoro/release/publish_javadoc.cfg | 5 +- .../.kokoro/release/publish_javadoc11.cfg | 30 ++++++++++ .../.kokoro/release/publish_javadoc11.sh | 55 +++++++++++++++++++ java-spanner-jdbc/synth.metadata | 7 ++- 6 files changed, 102 insertions(+), 54 deletions(-) delete mode 100755 java-spanner-jdbc/.kokoro/linkage-monitor.sh create mode 100644 java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg create mode 100755 java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 683022075665..98a472e132d6 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -54,7 +54,18 @@ jobs: with: java-version: 8 - run: java -version - - run: .kokoro/linkage-monitor.sh + - name: Install artifacts to local Maven repository + run: | + source .kokoro/common.sh + retry_with_backoff 3 10 \ + mvn install -B -V \ + -Dmaven.test.skip -DskipTests=true \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dmaven.javadoc.skip=true \ + -Dgcloud.download.skip=true + shell: bash + - uses: GoogleCloudPlatform/cloud-opensource-java/linkage-monitor@v1-linkagemonitor lint: runs-on: ubuntu-latest steps: diff --git a/java-spanner-jdbc/.kokoro/linkage-monitor.sh b/java-spanner-jdbc/.kokoro/linkage-monitor.sh deleted file mode 100755 index 759ab4e2c220..000000000000 --- a/java-spanner-jdbc/.kokoro/linkage-monitor.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# Copyright 2019 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. - -set -eo pipefail -# Display commands being run. -set -x - -## Get the directory of the build script -scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) -## cd to the parent directory, i.e. the root of the git repo -cd ${scriptDir}/.. - -# include common functions -source ${scriptDir}/common.sh - -# Print out Java version -java -version -echo ${JOB_TYPE} - -# attempt to install 3 times with exponential backoff (starting with 10 seconds) -retry_with_backoff 3 10 \ - mvn install -B -V \ - -DskipTests=true \ - -Dclirr.skip=true \ - -Denforcer.skip=true \ - -Dmaven.javadoc.skip=true \ - -Dgcloud.download.skip=true - -# Kokoro job cloud-opensource-java/ubuntu/linkage-monitor-gcs creates this JAR -JAR=linkage-monitor-latest-all-deps.jar -curl -v -O "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/${JAR}" - -# Fails if there's new linkage errors compared with baseline -java -jar ${JAR} com.google.cloud:libraries-bom diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index fa2437d6eeec..448a04ed4c59 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -26,7 +26,4 @@ before_action { keyname: "docuploader_service_account" } } -} - -# Downloads docfx doclet resource. This will be in ${KOKORO_GFILE_DIR}/ -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" \ No newline at end of file +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg new file mode 100644 index 000000000000..2ddd71ce63ec --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg @@ -0,0 +1,30 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "STAGING_BUCKET_V2" + value: "docs-staging-v2" + # Production will be at: docs-staging-v2 +} + +# Configure the docker image for kokoro-trampoline +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-memcache/.kokoro/release/publish_javadoc11.sh" +} + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "docuploader_service_account" + } + } +} + +# Downloads docfx doclet resource. This will be in ${KOKORO_GFILE_DIR}/ +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh new file mode 100755 index 000000000000..dc26611cbcf8 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2021 Google Inc. +# +# 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. + +set -eo pipefail + +if [[ -z "${CREDENTIALS}" ]]; then + CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account +fi + +if [[ -z "${STAGING_BUCKET_V2}" ]]; then + echo "Need to set STAGING_BUCKET_V2 environment variable" + exit 1 +fi + +# work from the git root directory +pushd $(dirname "$0")/../../ + +# install docuploader package +python3 -m pip install gcp-docuploader + +# compile all packages +mvn clean install -B -q -DskipTests=true + +export NAME=google-cloud-spanner-jdbc +export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) + +# V3 generates docfx yml from javadoc +# generate yml +mvn clean site -B -q -P docFX + +pushd target/docfx-yml + +# create metadata +python3 -m docuploader create-metadata \ + --name ${NAME} \ + --version ${VERSION} \ + --language java + +# upload yml +python3 -m docuploader upload . \ + --credentials ${CREDENTIALS} \ + --staging-bucket ${STAGING_BUCKET_V2} \ + --destination-prefix docfx- diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index e4e8ea454ec0..e9ff51a44d0c 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "7e5a13374ec6f343b2b2ea2320e8c12f895f3e87" + "sha": "acf76ee06c49cc2c47825b8654a9a81b7407d24a" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "3816b080296d4d52975079fd26c110dd26ba25af" + "sha": "e935c9ecb47da0f2e054f5f1845f7cf7c95fa625" } } ], @@ -40,7 +40,6 @@ ".kokoro/continuous/java8.cfg", ".kokoro/continuous/readme.cfg", ".kokoro/dependencies.sh", - ".kokoro/linkage-monitor.sh", ".kokoro/nightly/common.cfg", ".kokoro/nightly/integration.cfg", ".kokoro/nightly/java11.cfg", @@ -72,6 +71,8 @@ ".kokoro/release/promote.sh", ".kokoro/release/publish_javadoc.cfg", ".kokoro/release/publish_javadoc.sh", + ".kokoro/release/publish_javadoc11.cfg", + ".kokoro/release/publish_javadoc11.sh", ".kokoro/release/snapshot.cfg", ".kokoro/release/snapshot.sh", ".kokoro/release/stage.cfg", From a1f94cf1420e240f8c0c6b9b035d8ed58ff6be25 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 4 Feb 2021 10:02:07 -0800 Subject: [PATCH 0298/1979] build(java): update autorelease branch name check (#345) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/aa15b03c-7629-4b5d-b5c2-a0ea5047610d/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/140ba24a136c63e7f10a998a63e7898aed63ea7d --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 2b6cdbc976c4..76e6404b4e09 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -17,7 +17,7 @@ jobs: } // only approve PRs like "chore: release " - if ( !context.payload.pull_request.title.startsWith("chore: release") ) { + if ( !context.payload.pull_request.title.startsWith("chore(master): release") ) { return; } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index e9ff51a44d0c..320a81fc145a 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "acf76ee06c49cc2c47825b8654a9a81b7407d24a" + "sha": "4daa18d69e2976964e5aae24043ada1fabba04a4" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "e935c9ecb47da0f2e054f5f1845f7cf7c95fa625" + "sha": "140ba24a136c63e7f10a998a63e7898aed63ea7d" } } ], From c16b6fff7fdbe3f9e832ee9a46e63ae57e80ffae Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 4 Feb 2021 15:32:34 -0800 Subject: [PATCH 0299/1979] chore: Re-generated to pick up changes from synthtool. (#346) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/b107ca23-cc03-4d8e-82d2-0b35f1361777/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/692715c0f23a7bb3bfbbaa300f7620ddfa8c47e5 Source-Link: https://github.com/googleapis/synthtool/commit/27b2d4f4674840628d0b75c5941e89c12af4764f --- java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg | 4 ++-- java-spanner-jdbc/LICENSE | 1 - java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg index 2ddd71ce63ec..28074bc69f9b 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg @@ -14,7 +14,7 @@ env_vars: { env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-memcache/.kokoro/release/publish_javadoc11.sh" + value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh" } before_action { @@ -27,4 +27,4 @@ before_action { } # Downloads docfx doclet resource. This will be in ${KOKORO_GFILE_DIR}/ -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" \ No newline at end of file +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" diff --git a/java-spanner-jdbc/LICENSE b/java-spanner-jdbc/LICENSE index d64569567334..261eeb9e9f8b 100644 --- a/java-spanner-jdbc/LICENSE +++ b/java-spanner-jdbc/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 320a81fc145a..6c9056a43591 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "4daa18d69e2976964e5aae24043ada1fabba04a4" + "sha": "81a844413be775520dcf15ba74938a6c1cf36442" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "140ba24a136c63e7f10a998a63e7898aed63ea7d" + "sha": "692715c0f23a7bb3bfbbaa300f7620ddfa8c47e5" } } ], From 0e6691a28ac4405ba8d0ed0658fac3d3d591c150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 8 Feb 2021 02:37:48 +0100 Subject: [PATCH 0300/1979] feat: Support Array conversion to ResultSet (#326) * feat: add support for array as ResultSet * feat: add support for array as ResultSet JDBC arrays can optionally be converted to ResultSets. This feature was not implemented for the Cloud Spanner JDBC driver. This would cause DBeaver to show an error message instead of the actual data when fetching a NUMERIC array. Other arrays would be fetched correctly by DBeaver, as those array types do not use the conversion to a ResultSet. * test: add tests for invalid data types --- .../google/cloud/spanner/jdbc/JdbcArray.java | 85 ++++++- .../cloud/spanner/jdbc/JdbcArrayTest.java | 212 ++++++++++++++++-- 2 files changed, 270 insertions(+), 27 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 67d8e0c15724..2a9d9e77635c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -16,11 +16,21 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.ByteArray; +import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.ValueBinder; +import com.google.common.collect.ImmutableList; import com.google.rpc.Code; +import java.math.BigDecimal; import java.sql.Array; +import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.Timestamp; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -137,28 +147,89 @@ public Object getArray(long index, int count, Map> map) throws return null; } - private static final String RESULTSET_NOT_SUPPORTED = - "Getting a ResultSet from an array is not supported"; + private static final String RESULTSET_WITH_TYPE_MAPPING_NOT_SUPPORTED = + "Getting a ResultSet with a custom type mapping from an array is not supported"; @Override public ResultSet getResultSet() throws SQLException { - throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + return getResultSet(1L, Integer.MAX_VALUE); } @Override public ResultSet getResultSet(Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + throw new SQLFeatureNotSupportedException(RESULTSET_WITH_TYPE_MAPPING_NOT_SUPPORTED); } @Override - public ResultSet getResultSet(long index, int count) throws SQLException { - throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + public ResultSet getResultSet(long startIndex, int count) throws SQLException { + JdbcPreconditions.checkArgument( + startIndex + count - 1L <= Integer.MAX_VALUE, + String.format("End index cannot exceed %d", Integer.MAX_VALUE)); + JdbcPreconditions.checkArgument(startIndex >= 1L, "Start index must be >= 1"); + JdbcPreconditions.checkArgument(count >= 0, "Count must be >= 0"); + checkFree(); + ImmutableList.Builder rows = ImmutableList.builder(); + int added = 0; + if (data != null) { + // Note that array index in JDBC is base-one. + for (int index = (int) startIndex; + added < count && index <= ((Object[]) data).length; + index++) { + Object value = ((Object[]) data)[index - 1]; + ValueBinder binder = + Struct.newBuilder().set("INDEX").to(index).set("VALUE"); + Struct.Builder builder = null; + switch (type.getCode()) { + case BOOL: + builder = binder.to((Boolean) value); + break; + case BYTES: + builder = binder.to(ByteArray.copyFrom((byte[]) value)); + break; + case DATE: + builder = binder.to(JdbcTypeConverter.toGoogleDate((Date) value)); + break; + case FLOAT64: + builder = binder.to((Double) value); + break; + case INT64: + builder = binder.to((Long) value); + break; + case NUMERIC: + builder = binder.to((BigDecimal) value); + break; + case STRING: + builder = binder.to((String) value); + break; + case TIMESTAMP: + builder = binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); + break; + case ARRAY: + case STRUCT: + default: + throw new SQLFeatureNotSupportedException( + String.format( + "Array of type %s cannot be converted to a ResultSet", type.getCode().name())); + } + rows.add(builder.build()); + added++; + if (added == count) { + break; + } + } + } + return JdbcResultSet.of( + ResultSets.forRows( + Type.struct( + StructField.of("INDEX", Type.int64()), + StructField.of("VALUE", type.getSpannerType())), + rows.build())); } @Override public ResultSet getResultSet(long index, int count, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException(RESULTSET_NOT_SUPPORTED); + throw new SQLFeatureNotSupportedException(RESULTSET_WITH_TYPE_MAPPING_NOT_SUPPORTED); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 01184c2d2226..24e3e57362e6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -16,10 +16,16 @@ package com.google.cloud.spanner.jdbc; -import static org.junit.Assert.assertEquals; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlDate; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import java.math.BigDecimal; import java.sql.Date; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; @@ -35,42 +41,208 @@ public void testCreateArrayTypeName() throws SQLException { // Note that JDBC array indices start at 1. JdbcArray array; array = JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}); - assertEquals(array.getBaseType(), Types.BOOLEAN); - assertEquals(((Boolean[]) array.getArray(1, 1))[0], Boolean.TRUE); + assertThat(array.getBaseType()).isEqualTo(Types.BOOLEAN); + assertThat(((Boolean[]) array.getArray(1, 1))[0]).isEqualTo(Boolean.TRUE); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getBoolean(2)).isEqualTo(true); + assertThat(rs.next()).isTrue(); + assertThat(rs.getBoolean(2)).isEqualTo(false); + assertThat(rs.next()).isTrue(); + assertThat(rs.getBoolean(2)).isEqualTo(true); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray("BYTES", new byte[][] {new byte[] {1, 2}, new byte[] {3, 4}}); - assertEquals(array.getBaseType(), Types.BINARY); - assertEquals(((byte[][]) array.getArray(1, 1))[0][1], (byte) 2); + assertThat(array.getBaseType()).isEqualTo(Types.BINARY); + assertThat(((byte[][]) array.getArray(1, 1))[0][1]).isEqualTo((byte) 2); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getBytes(2)).isEqualTo(new byte[] {1, 2}); + assertThat(rs.next()).isTrue(); + assertThat(rs.getBytes(2)).isEqualTo(new byte[] {3, 4}); + assertThat(rs.next()).isFalse(); + } array = - JdbcArray.createArray("DATE", new Date[] {new Date(1L), new Date(100L), new Date(1000L)}); - assertEquals(array.getBaseType(), Types.DATE); - assertEquals(((Date[]) array.getArray(1, 1))[0], new Date(1L)); + JdbcArray.createArray( + "DATE", + new Date[] { + toSqlDate(com.google.cloud.Date.fromYearMonthDay(2021, 1, 18)), + toSqlDate(com.google.cloud.Date.fromYearMonthDay(2000, 2, 29)), + toSqlDate(com.google.cloud.Date.fromYearMonthDay(2019, 8, 31)) + }); + assertThat(array.getBaseType()).isEqualTo(Types.DATE); + assertThat(((Date[]) array.getArray(1, 1))[0]) + .isEqualTo(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2021, 1, 18))); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getDate(2)) + .isEqualTo(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2021, 1, 18))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getDate(2)) + .isEqualTo(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2000, 2, 29))); + assertThat(rs.next()).isTrue(); + assertThat(rs.getDate(2)) + .isEqualTo(toSqlDate(com.google.cloud.Date.fromYearMonthDay(2019, 8, 31))); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray("FLOAT64", new Double[] {1.1D, 2.2D, Math.PI}); - assertEquals(array.getBaseType(), Types.DOUBLE); - assertEquals(((Double[]) array.getArray(1, 3))[2], Double.valueOf(Math.PI)); + assertThat(array.getBaseType()).isEqualTo(Types.DOUBLE); + assertThat(((Double[]) array.getArray(1, 3))[2]).isEqualTo(Double.valueOf(Math.PI)); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getDouble(2)).isEqualTo(1.1D); + assertThat(rs.next()).isTrue(); + assertThat(rs.getDouble(2)).isEqualTo(2.2D); + assertThat(rs.next()).isTrue(); + assertThat(rs.getDouble(2)).isEqualTo(Math.PI); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}); - assertEquals(array.getBaseType(), Types.BIGINT); - assertEquals(((Long[]) array.getArray(1, 1))[0], Long.valueOf(1L)); + assertThat(array.getBaseType()).isEqualTo(Types.BIGINT); + assertThat(((Long[]) array.getArray(1, 1))[0]).isEqualTo(Long.valueOf(1L)); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(2)).isEqualTo(1L); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(2)).isEqualTo(2L); + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong(2)).isEqualTo(3L); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}); - assertEquals(array.getBaseType(), Types.NUMERIC); - assertEquals(((BigDecimal[]) array.getArray(1, 1))[0], BigDecimal.ONE); - assertEquals(((BigDecimal[]) array.getArray(2, 1))[0], null); - assertEquals(((BigDecimal[]) array.getArray(3, 1))[0], BigDecimal.TEN); + assertThat(array.getBaseType()).isEqualTo(Types.NUMERIC); + assertThat(((BigDecimal[]) array.getArray(1, 1))[0]).isEqualTo(BigDecimal.ONE); + assertThat(((BigDecimal[]) array.getArray(2, 1))[0]).isNull(); + assertThat(((BigDecimal[]) array.getArray(3, 1))[0]).isEqualTo(BigDecimal.TEN); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getBigDecimal(2)).isEqualTo(BigDecimal.ONE); + assertThat(rs.next()).isTrue(); + assertThat(rs.getBigDecimal(2)).isNull(); + assertThat(rs.next()).isTrue(); + assertThat(rs.getBigDecimal(2)).isEqualTo(BigDecimal.TEN); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); - assertEquals(array.getBaseType(), Types.NVARCHAR); - assertEquals(((String[]) array.getArray(1, 1))[0], "foo"); + assertThat(array.getBaseType()).isEqualTo(Types.NVARCHAR); + assertThat(((String[]) array.getArray(1, 1))[0]).isEqualTo("foo"); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("foo"); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("bar"); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("baz"); + assertThat(rs.next()).isFalse(); + } array = JdbcArray.createArray( "TIMESTAMP", new Timestamp[] {new Timestamp(1L), new Timestamp(100L), new Timestamp(1000L)}); - assertEquals(array.getBaseType(), Types.TIMESTAMP); - assertEquals(((Timestamp[]) array.getArray(1, 1))[0], new Timestamp(1L)); + assertThat(array.getBaseType()).isEqualTo(Types.TIMESTAMP); + assertThat(((Timestamp[]) array.getArray(1, 1))[0]).isEqualTo(new Timestamp(1L)); + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getTimestamp(2)).isEqualTo(new Timestamp(1L)); + assertThat(rs.next()).isTrue(); + assertThat(rs.getTimestamp(2)).isEqualTo(new Timestamp(100L)); + assertThat(rs.next()).isTrue(); + assertThat(rs.getTimestamp(2)).isEqualTo(new Timestamp(1000L)); + assertThat(rs.next()).isFalse(); + } + } + + @Test + public void testCreateArrayOfArray() { + try { + JdbcArray.createArray("ARRAY", new String[][] {{}}); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException jse = (JdbcSqlException) e; + assertThat(jse.getErrorCode()) + .isEqualTo(ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()); + } + } + + @Test + public void testCreateArrayOfStruct() { + try { + JdbcArray.createArray("STRUCT", new Object[] {}); + fail("missing expected exception"); + } catch (SQLException e) { + assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); + JdbcSqlException jse = (JdbcSqlException) e; + assertThat(jse.getErrorCode()) + .isEqualTo(ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()); + } + } + + @Test + public void testGetResultSetMetadata() throws SQLException { + JdbcArray array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); + try (ResultSet rs = array.getResultSet()) { + ResultSetMetaData metadata = rs.getMetaData(); + assertThat(metadata.getColumnCount()).isEqualTo(2); + assertThat(metadata.getColumnType(1)).isEqualTo(Types.BIGINT); + assertThat(metadata.getColumnType(2)).isEqualTo(Types.NVARCHAR); + assertThat(metadata.getColumnName(1)).isEqualTo("INDEX"); + assertThat(metadata.getColumnName(2)).isEqualTo("VALUE"); + } + } + + @Test + public void testGetResultSetWithIndex() throws SQLException { + JdbcArray array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); + try (ResultSet rs = array.getResultSet(2L, 1)) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getLong("INDEX")).isEqualTo(2L); + assertThat(rs.getString("VALUE")).isEqualTo("bar"); + assertThat(rs.next()).isFalse(); + } + + try (ResultSet rs = array.getResultSet(1L, 5)) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("foo"); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("bar"); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString(2)).isEqualTo("baz"); + assertThat(rs.next()).isFalse(); + } + + try (ResultSet rs = array.getResultSet(1L, 0)) { + assertThat(rs.next()).isFalse(); + } + } + + @Test + public void testGetResultSetWithInvalidIndex() throws SQLException { + JdbcArray array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); + try (ResultSet rs = array.getResultSet(0L, 1)) { + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getErrorCode()) + .isEqualTo(ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()); + } + } + + @Test + public void testGetResultSetWithInvalidCount() throws SQLException { + JdbcArray array = JdbcArray.createArray("STRING", new String[] {"foo", "bar", "baz"}); + try (ResultSet rs = array.getResultSet(1L, -1)) { + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getErrorCode()) + .isEqualTo(ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()); + } } } From 4140e5fb8c8ce06a0518d5a76c4ac016f60599bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 8 Feb 2021 03:13:05 +0100 Subject: [PATCH 0301/1979] docs: fix javadoc formatting (#343) * docs: fix javadoc formatting One of the descriptions of the supported connection properties missed an ending
    block, which caused the entire formatting to be incorrect. Fixes #342 * fix: 'will be' => 'is' --- .../com/google/cloud/spanner/jdbc/JdbcDriver.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index d2a2fea2e436..f7214ea74abd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -67,7 +67,7 @@ * The property-value strings should be url-encoded. * *

    The project-id part of the URI may be filled with the placeholder DEFAULT_PROJECT_ID. This - * placeholder will be replaced by the default project id of the environment that is requesting a + * placeholder is replaced by the default project id of the environment that is requesting a * connection. * *

    The supported properties are: @@ -75,7 +75,7 @@ *

      *
    • credentials (String): URL for the credentials file to use for the connection. If you do not * specify any credentials at all, the default credentials of the environment as returned by - * {@link GoogleCredentials#getApplicationDefault()} will be used. + * {@link GoogleCredentials#getApplicationDefault()} is used. *
    • oauthtoken (String): A valid OAuth2 token to use for the JDBC connection. The token must * have been obtained with one or both of the scopes * 'https://www.googleapis.com/auth/spanner.admin' and/or @@ -89,8 +89,15 @@ * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} * for more information. *
    • numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - *
    • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to the server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. - *
    • optimizerVersion (string): The query optimizer version to use for the connection. The value must be either a valid version number or LATEST. If no value is specified, the query optimizer version specified in the environment variable SPANNER_OPTIMIZER_VERSION will be used. If no query optimizer version is specified in the connection URL or in the environment variable, the default query optimizer version of Cloud Spanner will be used. + *
    • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted + * connection to the server. This option can only be used when connecting to a local emulator + * that does not require an encrypted connection, and that does not require authentication. + *
    • optimizerVersion (string): The query optimizer version to use for the connection. The value + * must be either a valid version number or LATEST. If no value is specified, the + * query optimizer version specified in the environment variable + * SPANNER_OPTIMIZER_VERSION is used. If no query optimizer version is specified in the + * connection URL or in the environment variable, the default query optimizer version of Cloud + * Spanner is used. *
    */ public class JdbcDriver implements Driver { From a3148f8eba4fc98426e56146694cde5aa3256c48 Mon Sep 17 00:00:00 2001 From: Zoe Date: Mon, 8 Feb 2021 18:39:03 +1100 Subject: [PATCH 0302/1979] Fix: Return entire stack trace for deadline exceeded error (#347) * Use original exception rather than message only * Use original exception rather than message only --- .../google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java index a6fc2bfaa30f..b7d1130d24cd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java @@ -68,6 +68,10 @@ public static class JdbcSqlTimeoutException extends SQLTimeoutException implements JdbcSqlException { private static final long serialVersionUID = 2363793358642102814L; + private JdbcSqlTimeoutException(SpannerException e) { + super(e.getMessage(), "Timed out", Code.DEADLINE_EXCEEDED_VALUE, e); + } + private JdbcSqlTimeoutException(String message) { super(message, "Timed out", Code.DEADLINE_EXCEEDED_VALUE); } @@ -188,7 +192,7 @@ static SQLException of(SpannerException e) { return new JdbcAbortedException((AbortedException) e); } case DEADLINE_EXCEEDED: - return new JdbcSqlTimeoutException(e.getMessage()); + return new JdbcSqlTimeoutException(e); case ALREADY_EXISTS: case CANCELLED: case DATA_LOSS: From 6c214ed04187e80ed65ce7a2dc62fa178ca8c2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 9 Feb 2021 02:24:00 +0100 Subject: [PATCH 0303/1979] test: re-enable JDBC converter test (#348) --- .../com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index d7c844a787ff..19f760bb6b59 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -51,7 +51,6 @@ import java.util.Calendar; import java.util.List; import java.util.TimeZone; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -620,7 +619,6 @@ public void testSetTimestampInCalendar() throws SQLException { } } - @Ignore("ignore until java-core 1.93.3 is available") @SuppressWarnings("deprecation") @Test public void testToGoogleTimestamp() { From 0f6422050ab1c13609d0a594a0f03ff1b161492b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Feb 2021 14:37:04 +0100 Subject: [PATCH 0304/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v16.4.0 (#349) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index be53fa13e9b2..509b8c9c1eee 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 16.3.0 + 16.4.0 pom import From 0466bb4b746cb8b005b8e2d8fc6b973575a53b71 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 10 Feb 2021 09:00:23 -0800 Subject: [PATCH 0305/1979] build(java): update autorelease script (#350) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/d3b31218-a85c-4976-9854-6b0543a40737/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/2414b817065726eae0bc525346c7e874f969369d --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 4 ++-- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 76e6404b4e09..7c8816a7d7b1 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -4,7 +4,7 @@ name: auto-release jobs: approve: runs-on: ubuntu-latest - if: contains(github.head_ref, 'release-v') + if: contains(github.head_ref, 'release-please') steps: - uses: actions/github-script@v3 with: @@ -16,7 +16,7 @@ jobs: return; } - // only approve PRs like "chore: release " + // only approve PRs like "chore(master): release " if ( !context.payload.pull_request.title.startsWith("chore(master): release") ) { return; } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 6c9056a43591..46e5f5b1c89d 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "81a844413be775520dcf15ba74938a6c1cf36442" + "sha": "907760fefd67e806f5d56910705d3d01049abf17" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "692715c0f23a7bb3bfbbaa300f7620ddfa8c47e5" + "sha": "2414b817065726eae0bc525346c7e874f969369d" } } ], From 0b6f1c57ef4cd26aab8d0c097cd7d55ba929f8a3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Feb 2021 00:12:17 +0100 Subject: [PATCH 0306/1979] test(deps): update dependency junit:junit to v4.13.2 (#352) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b971e4e5f74a..bcb72f2d63eb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -58,7 +58,7 @@ google-cloud-spanner-jdbc - 4.13.1 + 4.13.2 3.0.2 1.4.4 1.1 From a65179385071b29c56654cf8f11b26f6aa75c170 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 16 Feb 2021 10:50:11 +1100 Subject: [PATCH 0307/1979] chore(master): release 1.19.0 (#344) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 28 ++++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b7a9ece56304..37b52cae3d17 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [1.19.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.3...v1.19.0) (2021-02-15) + + +### Features + +* allow unknown properties in connection url with lenient mode ([#284](https://www.github.com/googleapis/java-spanner-jdbc/issues/284)) ([0e557ef](https://www.github.com/googleapis/java-spanner-jdbc/commit/0e557ef7657cae04d263daa6717ee34290338b7a)) +* Support Array conversion to ResultSet ([#326](https://www.github.com/googleapis/java-spanner-jdbc/issues/326)) ([6ea0a26](https://www.github.com/googleapis/java-spanner-jdbc/commit/6ea0a26ca82565858d8049cc5403a4475edcce33)) +* support creating shaded jars ([#333](https://www.github.com/googleapis/java-spanner-jdbc/issues/333)) ([8b4e50d](https://www.github.com/googleapis/java-spanner-jdbc/commit/8b4e50d10a9121334be3d8b5ed0d8fc9ff63c182)), closes [#316](https://www.github.com/googleapis/java-spanner-jdbc/issues/316) +* support default ClientInfo properties ([#324](https://www.github.com/googleapis/java-spanner-jdbc/issues/324)) ([250c4c1](https://www.github.com/googleapis/java-spanner-jdbc/commit/250c4c127f75cc4979e511e2459813f22fec67de)) + + +### Bug Fixes + +* getting resultset metadata twice could skip row ([#323](https://www.github.com/googleapis/java-spanner-jdbc/issues/323)) ([f8149af](https://www.github.com/googleapis/java-spanner-jdbc/commit/f8149afb63b9a66e89119290c594b50e599f351a)) +* Return entire stack trace for deadline exceeded error ([#347](https://www.github.com/googleapis/java-spanner-jdbc/issues/347)) ([2f94976](https://www.github.com/googleapis/java-spanner-jdbc/commit/2f94976514bfd08afaacc25e802ef1c9717aa75a)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.18.0 ([#320](https://www.github.com/googleapis/java-spanner-jdbc/issues/320)) ([e1cd90d](https://www.github.com/googleapis/java-spanner-jdbc/commit/e1cd90d8afbfa725a92186b85bd446413c8ed4bc)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v3.3.1 ([#319](https://www.github.com/googleapis/java-spanner-jdbc/issues/319)) ([7cd990b](https://www.github.com/googleapis/java-spanner-jdbc/commit/7cd990b5ba49f05fba4b1a1ce49f8de133b04868)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v3.3.2 ([#325](https://www.github.com/googleapis/java-spanner-jdbc/issues/325)) ([9d65dab](https://www.github.com/googleapis/java-spanner-jdbc/commit/9d65dab248efb5c8e8c5ad56775731891e225b3e)) + + +### Documentation + +* fix javadoc formatting ([#343](https://www.github.com/googleapis/java-spanner-jdbc/issues/343)) ([2ac1964](https://www.github.com/googleapis/java-spanner-jdbc/commit/2ac19641d9496eca33f57a034367a4f17bc14f1c)) + ### [1.18.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.2...v1.18.3) (2020-12-16) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bcb72f2d63eb..8a72d970a4ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.18.4-SNAPSHOT + 1.19.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 36049d482433..8077b5c649e5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.4-SNAPSHOT + 1.19.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0df459ffac8e..c43f7c4dddeb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.18.3:1.18.4-SNAPSHOT +google-cloud-spanner-jdbc:1.19.0:1.19.0 From d504f2e774248c509bc1c594ee26b4783ba35078 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Feb 2021 00:50:53 +0100 Subject: [PATCH 0308/1979] test(deps): update dependency junit:junit to v4.13.2 (#353) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 029ad86c420d..30bf149e6efb 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -36,7 +36,7 @@ junit junit - 4.13.1 + 4.13.2 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8077b5c649e5..571e3a3bde0f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -35,7 +35,7 @@ junit junit - 4.13.1 + 4.13.2 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 509b8c9c1eee..7896b72e28d2 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -47,7 +47,7 @@ junit junit - 4.13.1 + 4.13.2 test From 1680184a07d37be8ac463f00ca4b3c5eb943d332 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 16 Feb 2021 00:08:06 +0000 Subject: [PATCH 0309/1979] chore(master): release 1.19.1-SNAPSHOT (#354) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8a72d970a4ab..8e6847416caa 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.19.0 + 1.19.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 571e3a3bde0f..a77bac704f2e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.19.0 + 1.19.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c43f7c4dddeb..6537895801ed 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.19.0:1.19.0 +google-cloud-spanner-jdbc:1.19.0:1.19.1-SNAPSHOT From 32d21bc356f28c01c772922b296682de29c97169 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 16 Feb 2021 16:18:31 -0800 Subject: [PATCH 0310/1979] ci: linkage monitor CI job to use build.sh (#356) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/96c62e92-13ae-4f3c-9727-c854ec8b7488/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/f327d3b657a63ae4a8efd7f011a15eacae36b59c --- java-spanner-jdbc/.github/workflows/ci.yaml | 13 +++---------- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 98a472e132d6..def8b3a2c84d 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -55,17 +55,10 @@ jobs: java-version: 8 - run: java -version - name: Install artifacts to local Maven repository - run: | - source .kokoro/common.sh - retry_with_backoff 3 10 \ - mvn install -B -V \ - -Dmaven.test.skip -DskipTests=true \ - -Dclirr.skip=true \ - -Denforcer.skip=true \ - -Dmaven.javadoc.skip=true \ - -Dgcloud.download.skip=true + run: .kokoro/build.sh shell: bash - - uses: GoogleCloudPlatform/cloud-opensource-java/linkage-monitor@v1-linkagemonitor + - name: Validate any conflicts with regard to com.google.cloud:libraries-bom (latest release) + uses: GoogleCloudPlatform/cloud-opensource-java/linkage-monitor@v1-linkagemonitor lint: runs-on: ubuntu-latest steps: diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 46e5f5b1c89d..63da2e618923 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "907760fefd67e806f5d56910705d3d01049abf17" + "sha": "994b2935b0c0c966f958408efc951c665392ade2" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "2414b817065726eae0bc525346c7e874f969369d" + "sha": "f327d3b657a63ae4a8efd7f011a15eacae36b59c" } } ], From 35e23cce82e63582a85efc4a031ad1024da780db Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 16 Feb 2021 16:54:07 -0800 Subject: [PATCH 0311/1979] chore: regenerate README (#358) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-02-17 00:23:36,788 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-02-17 00:23:38,272 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/05814b29-71ca-4400-9962-ee9d469b6688/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 69ebebb4e41b..b3040ef3a426 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "8b4e50d10a9121334be3d8b5ed0d8fc9ff63c182" + "sha": "653de1642291e60f0b28de0d1332b6504b7a9274" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "d1bb9173100f62c0cfc8f3138b62241e7f47ca6a" + "sha": "f327d3b657a63ae4a8efd7f011a15eacae36b59c" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index bcdfb375fc21..06b68e452910 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.18.3 + 1.19.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.18.3' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.19.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.18.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.19.0" ``` ## Authentication From 53fa2442609303733de1f9fc8012d3cd889b2a10 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Feb 2021 13:56:41 +0100 Subject: [PATCH 0312/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v4 (#359) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8e6847416caa..4ca45a604e50 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 3.3.2 + 4.0.0 pom import From 3e21986b1f79184ec091dfed96dca463751905ab Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Feb 2021 13:57:14 +0100 Subject: [PATCH 0313/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.19.0 (#355) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 30bf149e6efb..d3f1d6332c88 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.18.3 + 1.19.0 From 5e82e099d7b1f4367fc37215665175fb6a452276 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 17 Feb 2021 09:06:21 -0800 Subject: [PATCH 0314/1979] chore: update cloud-rad buckets (#360) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/0a285685-944f-4f44-84fb-761c5c361020/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/b416a7befcdbc42de41cf387dcf428f894fb812b --- java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg | 4 ++-- java-spanner-jdbc/.kokoro/release/publish_javadoc.sh | 2 +- java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg | 2 +- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index 448a04ed4c59..71efe308f8c9 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -7,10 +7,10 @@ env_vars: { value: "docs-staging" } +# cloud-rad staging env_vars: { key: "STAGING_BUCKET_V2" - value: "docs-staging-v2" - # Production will be at: docs-staging-v2 + value: "docs-staging-v2-staging" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 7325bdc741cd..024aee4f3976 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -71,7 +71,7 @@ python3 -m docuploader create-metadata \ --version ${VERSION} \ --language java -# upload docs +# upload docs to staging bucket python3 -m docuploader upload . \ --credentials ${CREDENTIALS} \ --staging-bucket ${STAGING_BUCKET_V2} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg index 28074bc69f9b..15fdc9840226 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg @@ -1,9 +1,9 @@ # Format: //devtools/kokoro/config/proto/build.proto +# cloud-rad production env_vars: { key: "STAGING_BUCKET_V2" value: "docs-staging-v2" - # Production will be at: docs-staging-v2 } # Configure the docker image for kokoro-trampoline diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index dc26611cbcf8..712821c7e499 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -48,7 +48,7 @@ python3 -m docuploader create-metadata \ --version ${VERSION} \ --language java -# upload yml +# upload yml to production bucket python3 -m docuploader upload . \ --credentials ${CREDENTIALS} \ --staging-bucket ${STAGING_BUCKET_V2} \ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 63da2e618923..4f7548182726 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "994b2935b0c0c966f958408efc951c665392ade2" + "sha": "3d4647f9fa748ed3c437f2d0f458e32403cea8d6" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "f327d3b657a63ae4a8efd7f011a15eacae36b59c" + "sha": "b416a7befcdbc42de41cf387dcf428f894fb812b" } } ], From 447fb7c685431179fd7a58e97740b07308c0928c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 18 Feb 2021 08:11:12 +0100 Subject: [PATCH 0315/1979] feat: allow setting min/max sessions (#335) * feat: allow setting min/max sessions * chore: run code formatter --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 4 + .../spanner/jdbc/JdbcConnectionUrlTest.java | 121 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 21 +-- 3 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index f7214ea74abd..3f4a433526bc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -88,6 +88,10 @@ * connection. Default is true. @see {@link * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} * for more information. + *
  • minSessions (int): Sets the minimum number of sessions in the backing session pool. + * Defaults to 100. + *
  • maxSessions (int): Sets the maximum number of sessions in the backing session pool. + * Defaults to 400. *
  • numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. *
  • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted * connection to the server. This option can only be used when connecting to a local emulator diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java new file mode 100644 index 000000000000..64ebe95562a2 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021 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 com.google.common.truth.Truth.assertThat; + +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.common.base.Predicate; +import com.google.protobuf.AbstractMessage; +import com.google.spanner.v1.BatchCreateSessionsRequest; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +@RunWith(Enclosed.class) +public class JdbcConnectionUrlTest { + + public static class ConnectionMinSessionsTest extends AbstractMockServerTest { + @AfterClass + public static void reset() { + mockSpanner.reset(); + } + + protected String getBaseUrl() { + return super.getBaseUrl() + ";minSessions=1"; + } + + @Test + public void testMinSessions() throws InterruptedException, TimeoutException, SQLException { + try (Connection connection = createJdbcConnection()) { + mockSpanner.waitForRequestsToContain( + new Predicate() { + @Override + public boolean apply(AbstractMessage input) { + return input instanceof BatchCreateSessionsRequest + && ((BatchCreateSessionsRequest) input).getSessionCount() == 1; + } + }, + 5000L); + } + } + } + + public static class ConnectionMaxSessionsTest extends AbstractMockServerTest { + + @AfterClass + public static void reset() { + mockSpanner.reset(); + } + + protected String getBaseUrl() { + return super.getBaseUrl() + ";maxSessions=1"; + } + + @Test + public void testMaxSessions() + throws InterruptedException, TimeoutException, ExecutionException, SQLException { + ExecutorService executor1 = Executors.newSingleThreadExecutor(); + ExecutorService executor2 = Executors.newSingleThreadExecutor(); + + try (Connection connection1 = createJdbcConnection(); + Connection connection2 = createJdbcConnection()) { + final CountDownLatch latch = new CountDownLatch(1); + Future fut1 = + executor1.submit( + new Callable() { + @Override + public Void call() throws SQLException, InterruptedException { + latch.await(5L, TimeUnit.SECONDS); + connection1.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection1.commit(); + return null; + } + }); + Future fut2 = + executor2.submit( + new Callable() { + @Override + public Void call() throws SQLException { + latch.countDown(); + connection2.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection2.commit(); + return null; + } + }); + // Wait until both finishes. + fut1.get(5L, TimeUnit.SECONDS); + fut2.get(5L, TimeUnit.SECONDS); + } finally { + executor1.shutdown(); + executor2.shutdown(); + } + assertThat(mockSpanner.numSessionsCreated()).isEqualTo(1); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index bdeda19cfbd3..51e9ab07bbcb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -46,7 +46,6 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -133,7 +132,7 @@ public void reset() { private String createUrl() { return String.format( - "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;minSessions=0", server.getPort(), "proj", "inst", "db"); } @@ -141,13 +140,13 @@ private Connection createConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { + // This triggers a retry with an explicit BeginTransaction RPC. + mockSpanner.abortNextStatement(); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); fail("missing expected exception"); } catch (SQLException e) { @@ -155,8 +154,6 @@ public void autocommitBeginTransaction() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitBeginPDMLTransaction() { mockSpanner.setBeginTransactionExecutionTime( @@ -170,14 +167,14 @@ public void autocommitBeginPDMLTransaction() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void transactionalBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); + // This triggers a retry with an explicit BeginTransaction RPC. + mockSpanner.abortNextStatement(); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); fail("missing expected exception"); } catch (SQLException e) { @@ -185,8 +182,6 @@ public void transactionalBeginTransaction() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void readOnlyBeginTransaction() { mockSpanner.setBeginTransactionExecutionTime( @@ -368,8 +363,6 @@ public void readOnlyExecuteStreamingSql() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void autocommitCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( @@ -382,8 +375,6 @@ public void autocommitCreateSession() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void transactionalCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( @@ -397,8 +388,6 @@ public void transactionalCreateSession() { } } - @Ignore( - "This can only be guaranteed with MinSessions=0. Re-enable when MinSessions is configurable for JDBC.") @Test public void readOnlyCreateSession() { mockSpanner.setBatchCreateSessionsExecutionTime( From d63d39732322dba3c06600539a9525391c623767 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 18 Feb 2021 16:18:18 -0800 Subject: [PATCH 0316/1979] build: skip Maven download logs (#361) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/8440e2da-528d-412a-bf89-385b5618d6dd/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/1aeca92e4a38f47134cb955f52ea76f84f09ff88 --- java-spanner-jdbc/.kokoro/build.sh | 2 ++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 27d9f2a1c640..96fe6b7cebd9 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -60,6 +60,7 @@ javadoc) ;; integration) mvn -B ${INTEGRATION_TEST_ARGS} \ + -ntp \ -Penable-integration-tests \ -DtrimStackTrace=false \ -Dclirr.skip=true \ @@ -81,6 +82,7 @@ samples) pushd ${SAMPLES_DIR} mvn -B \ -Penable-samples \ + -ntp \ -DtrimStackTrace=false \ -Dclirr.skip=true \ -Denforcer.skip=true \ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 4f7548182726..661965f517e3 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3d4647f9fa748ed3c437f2d0f458e32403cea8d6" + "sha": "a5862a5572721fc898cf9b5f4ab8b99631848110" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "b416a7befcdbc42de41cf387dcf428f894fb812b" + "sha": "1aeca92e4a38f47134cb955f52ea76f84f09ff88" } } ], From ad3ff6790d2cb6b1e480437714400ebd0f8bc874 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 19 Feb 2021 07:46:33 -0800 Subject: [PATCH 0317/1979] build: reduce download junk in log files (#362) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/83fbc024-ecda-4d7c-bdb6-c1f6343e492a/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/6946fd71ae9215b0e7ae188f5057df765ee6d7d2 --- java-spanner-jdbc/.kokoro/build.sh | 2 +- java-spanner-jdbc/.kokoro/dependencies.sh | 4 ++-- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 96fe6b7cebd9..5566bac3f5c8 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -29,7 +29,7 @@ echo ${JOB_TYPE} # attempt to install 3 times with exponential backoff (starting with 10 seconds) retry_with_backoff 3 10 \ - mvn install -B -V \ + mvn install -B -V -ntp \ -DskipTests=true \ -Dclirr.skip=true \ -Denforcer.skip=true \ diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index c91e5a56937a..0fb8c8436ccc 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -31,7 +31,7 @@ export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" # this should run maven enforcer retry_with_backoff 3 10 \ - mvn install -B -V \ + mvn install -B -V -ntp \ -DskipTests=true \ -Dclirr.skip=true @@ -86,4 +86,4 @@ then else msg "Errors found. See log statements above." exit 1 -fi \ No newline at end of file +fi diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 661965f517e3..7b859ad358a5 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a5862a5572721fc898cf9b5f4ab8b99631848110" + "sha": "02164fefc5dd847ebb6d4ca4d4d6e9a8030da2a5" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "1aeca92e4a38f47134cb955f52ea76f84f09ff88" + "sha": "6946fd71ae9215b0e7ae188f5057df765ee6d7d2" } } ], From 1598fa6dfb55d13f092c91d21b86c7569a5fa024 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 23 Feb 2021 04:41:45 +0100 Subject: [PATCH 0318/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v4.0.1 (#366) deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.19.0 --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4ca45a604e50..94d9e68572dd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,14 +71,14 @@ com.google.cloud google-cloud-spanner-bom - 4.0.0 + 4.0.1 pom import com.google.cloud google-cloud-shared-dependencies - 0.18.0 + 0.19.0 pom import From f3546f2c511de29217d96cf0378be3663633be12 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 23 Feb 2021 15:10:50 +1100 Subject: [PATCH 0319/1979] chore(master): release 1.20.0 (#357) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 37b52cae3d17..867fd0b5ec9b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [1.20.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.19.0...v1.20.0) (2021-02-23) + + +### Features + +* allow setting min/max sessions ([#335](https://www.github.com/googleapis/java-spanner-jdbc/issues/335)) ([a5862a5](https://www.github.com/googleapis/java-spanner-jdbc/commit/a5862a5572721fc898cf9b5f4ab8b99631848110)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.19.0 ([fa3721b](https://www.github.com/googleapis/java-spanner-jdbc/commit/fa3721b5d42e0f71247937366f1fa9e3a454beef)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v4 ([#359](https://www.github.com/googleapis/java-spanner-jdbc/issues/359)) ([49aa337](https://www.github.com/googleapis/java-spanner-jdbc/commit/49aa337dae08c4c39a7c32c14f92a7c858ad3dc8)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v4.0.1 ([#366](https://www.github.com/googleapis/java-spanner-jdbc/issues/366)) ([fa3721b](https://www.github.com/googleapis/java-spanner-jdbc/commit/fa3721b5d42e0f71247937366f1fa9e3a454beef)) + ## [1.19.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.18.3...v1.19.0) (2021-02-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 94d9e68572dd..693846936307 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.19.1-SNAPSHOT + 1.20.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a77bac704f2e..cd4b2f5af65d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.19.1-SNAPSHOT + 1.20.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6537895801ed..ba2add764491 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.19.0:1.19.1-SNAPSHOT +google-cloud-spanner-jdbc:1.20.0:1.20.0 From bc56f0858791a9a745b4f8094ea05a048e6cb519 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 23 Feb 2021 04:28:04 +0000 Subject: [PATCH 0320/1979] chore(master): release 1.20.1-SNAPSHOT (#367) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 693846936307..3302b84300e5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.20.0 + 1.20.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index cd4b2f5af65d..eccd23bb81ed 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.0 + 1.20.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ba2add764491..0b85a67e74ef 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.20.0:1.20.0 +google-cloud-spanner-jdbc:1.20.0:1.20.1-SNAPSHOT From 718018e45a64f2f26d608d6750f84b3093278bc4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 24 Feb 2021 06:38:13 +0100 Subject: [PATCH 0321/1979] test(deps): update dependency com.google.truth:truth to v1.1.2 (#327) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3302b84300e5..322aedd37607 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ 4.13.2 3.0.2 1.4.4 - 1.1 + 1.1.2 1.10.19 2.2 From d04c3c2a0dc80dd5e2d16b97c8e322567b69d62e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 24 Feb 2021 06:38:35 +0100 Subject: [PATCH 0322/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.20.0 (#368) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d3f1d6332c88..9d47192d1770 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.19.0 + 1.20.0 From 03dc85b5988c9d462232d7e852bc9c246f4ef531 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 23 Feb 2021 21:56:04 -0800 Subject: [PATCH 0323/1979] chore: regenerate README (#370) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-02-24 05:40:26,653 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-02-24 05:40:28,195 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/bd8294fd-3f74-41f8-9b4f-f765058d87ee/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index b3040ef3a426..bd3a24053813 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "653de1642291e60f0b28de0d1332b6504b7a9274" + "sha": "eb9c6a80005ea9658cbe57ac0b9e7f8596a016ab" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "f327d3b657a63ae4a8efd7f011a15eacae36b59c" + "sha": "79ab0b44a2cc7d803d07c107f9faf07729fc4012" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 06b68e452910..7b53e80a5709 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.19.0 + 1.20.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.19.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.20.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.19.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.20.0" ``` ## Authentication From d29ac40f3a80bf93231eee52a6d55de5e6ade715 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 24 Feb 2021 20:38:24 +0100 Subject: [PATCH 0324/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v17 (#371) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `16.4.0` -> `17.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/17.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/17.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/17.0.0/compatibility-slim/16.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/17.0.0/confidence-slim/16.4.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7896b72e28d2..d23277e0ed0e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 16.4.0 + 17.0.0 pom import From 8de228fb6dc8fb453f3f8871a0823c1baf7b0415 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 25 Feb 2021 02:02:07 +0100 Subject: [PATCH 0325/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v18 (#372) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `17.0.0` -> `18.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/18.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/18.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/18.0.0/compatibility-slim/17.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/18.0.0/confidence-slim/17.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d23277e0ed0e..172882e2a958 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 17.0.0 + 18.0.0 pom import From a20ae075cc8bfcd6ca54f0a824cb32c6a593b940 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 25 Feb 2021 22:56:07 +0100 Subject: [PATCH 0326/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.20.0 (#374) [![WhiteSource 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/java-shared-dependencies) | `0.19.0` -> `0.20.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.20.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.20.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.20.0/compatibility-slim/0.19.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.20.0/confidence-slim/0.19.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.20.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0200-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0190v0200-2021-02-25) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.19.0...v0.20.0) ##### Dependencies - update dependency com.google.auth:google-auth-library-bom to v0.24.0 ([#​284](https://www.github.com/googleapis/java-shared-dependencies/issues/284)) ([5e4914c](https://www.github.com/googleapis/java-shared-dependencies/commit/5e4914cc4a8ccd41a219f150a7455da116d1594b)) - update dependency com.google.http-client:google-http-client-bom to v1.39.0 ([#​288](https://www.github.com/googleapis/java-shared-dependencies/issues/288)) ([70bb862](https://www.github.com/googleapis/java-shared-dependencies/commit/70bb862029b840fbd99ba0109fa2b8f585812793)) - update dependency com.google.protobuf:protobuf-bom to v3.15.1 ([#​282](https://www.github.com/googleapis/java-shared-dependencies/issues/282)) ([44283bd](https://www.github.com/googleapis/java-shared-dependencies/commit/44283bdfdc9288b4a8d16b6ed3a61541792d147e)) - update dependency com.google.protobuf:protobuf-bom to v3.15.2 ([#​287](https://www.github.com/googleapis/java-shared-dependencies/issues/287)) ([bdae560](https://www.github.com/googleapis/java-shared-dependencies/commit/bdae5600f9033219ef8beb6c4d1c521fb062eaec)) - update dependency io.grpc:grpc-bom to v1.36.0 ([#​285](https://www.github.com/googleapis/java-shared-dependencies/issues/285)) ([c59771b](https://www.github.com/googleapis/java-shared-dependencies/commit/c59771b2436ac1a4fbc92b48049900472dd6d3ff)) - update gax.version to v1.62.0 ([#​291](https://www.github.com/googleapis/java-shared-dependencies/issues/291)) ([66bd070](https://www.github.com/googleapis/java-shared-dependencies/commit/66bd0702bd3deb64e0f6c73635e0ffd51a4d637e)) - update google.common-protos.version to v2.1.0 ([#​289](https://www.github.com/googleapis/java-shared-dependencies/issues/289)) ([43c9f02](https://www.github.com/googleapis/java-shared-dependencies/commit/43c9f026b1fa82f38dcb93b902281c2559e82d8e)) - update iam.version to v1.0.9 ([#​281](https://www.github.com/googleapis/java-shared-dependencies/issues/281)) ([ee44d0b](https://www.github.com/googleapis/java-shared-dependencies/commit/ee44d0b41e101931ccf5de2561dfcfcc9ff88b88))
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 322aedd37607..dc47077d4aa3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.19.0 + 0.20.0 pom import From 803be78beb0f81d8dad43db4ca3677ca2bfffaad Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 26 Feb 2021 18:42:20 +0100 Subject: [PATCH 0327/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v4.0.2 (#369) [![WhiteSource 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) | `4.0.1` -> `4.0.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/4.0.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/4.0.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/4.0.2/compatibility-slim/4.0.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/4.0.2/confidence-slim/4.0.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v4.0.2`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​402-httpswwwgithubcomgoogleapisjava-spannercomparev401v402-2021-02-23) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v4.0.1...v4.0.2)
    --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dc47077d4aa3..7634829e402c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 4.0.1 + 4.0.2 pom import From b93165f14731b09157038439fc792250e1ecf000 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 26 Feb 2021 18:00:26 +0000 Subject: [PATCH 0328/1979] chore(master): release 1.20.1 (#375) :robot: I have created a release \*beep\* \*boop\* --- ### [1.20.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.20.0...v1.20.1) (2021-02-26) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v0.20.0 ([#374](https://www.github.com/googleapis/java-spanner-jdbc/issues/374)) ([a20ae07](https://www.github.com/googleapis/java-spanner-jdbc/commit/a20ae075cc8bfcd6ca54f0a824cb32c6a593b940)) * update dependency com.google.cloud:google-cloud-spanner-bom to v4.0.2 ([#369](https://www.github.com/googleapis/java-spanner-jdbc/issues/369)) ([803be78](https://www.github.com/googleapis/java-spanner-jdbc/commit/803be78beb0f81d8dad43db4ca3677ca2bfffaad)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 867fd0b5ec9b..6b9ae0c82140 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### [1.20.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.20.0...v1.20.1) (2021-02-26) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.20.0 ([#374](https://www.github.com/googleapis/java-spanner-jdbc/issues/374)) ([398d886](https://www.github.com/googleapis/java-spanner-jdbc/commit/398d8864a72029a62b0a3adfaeafaeae76af3e1a)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v4.0.2 ([#369](https://www.github.com/googleapis/java-spanner-jdbc/issues/369)) ([3a984c2](https://www.github.com/googleapis/java-spanner-jdbc/commit/3a984c26076f187a710b59c8487e330636319f7c)) + ## [1.20.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.19.0...v1.20.0) (2021-02-23) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7634829e402c..9a71852a54b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.20.1-SNAPSHOT + 1.20.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index eccd23bb81ed..cc26003392ff 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.1-SNAPSHOT + 1.20.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0b85a67e74ef..34579099dc89 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.20.0:1.20.1-SNAPSHOT +google-cloud-spanner-jdbc:1.20.1:1.20.1 From 0e09f72afdca0883ad8c0aa16ebda7bbc4e0fdc9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 26 Feb 2021 18:18:05 +0000 Subject: [PATCH 0329/1979] chore(master): release 1.20.2-SNAPSHOT (#376) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9a71852a54b0..a59e5de7e790 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.20.1 + 1.20.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index cc26003392ff..b9af5cd73394 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.1 + 1.20.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 34579099dc89..4ac31ec0922b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.20.1:1.20.1 +google-cloud-spanner-jdbc:1.20.1:1.20.2-SNAPSHOT From 900f6ac0c2fc1164b7528a627538dbe74359f22a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 1 Mar 2021 05:54:40 +0100 Subject: [PATCH 0330/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.20.1 (#377) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9d47192d1770..e70c46899909 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.0 + 1.20.1 From 6537d084b8d6c4b38c5afd3cff8a6c5b2f1fe2d3 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 28 Feb 2021 21:16:02 -0800 Subject: [PATCH 0331/1979] chore: regenerate README (#378) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-03-01 04:56:52,060 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-03-01 04:56:53,654 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/968851b6-f8e2-44a3-862d-22d02bb1ed7a/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index bd3a24053813..873d0189ea96 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "eb9c6a80005ea9658cbe57ac0b9e7f8596a016ab" + "sha": "a7c44b0837caaa42933f252249eac938eeb0ef11" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "79ab0b44a2cc7d803d07c107f9faf07729fc4012" + "sha": "8c5628b86cfa8386de7b8fc1675e6b528b552d57" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7b53e80a5709..7e3e78a20986 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.20.0 + 1.20.1 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.20.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.20.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.20.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.20.1" ``` ## Authentication From 1b0dee61aefa20e93f10f90a35fb67a2a166edc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 1 Mar 2021 09:09:42 +0100 Subject: [PATCH 0332/1979] feat: allow using UUID in PreparedStatement (#365) Enables the usage of UUIDs as a parameter in PreparedStatements. UUIDs are automatically translated to strings. Fixes #364 --- .../spanner/jdbc/JdbcParameterStore.java | 5 + .../spanner/jdbc/JdbcParameterStoreTest.java | 385 ++++++++---------- .../jdbc/JdbcPreparedStatementTest.java | 154 ++++--- .../jdbc/it/ITJdbcPreparedStatementTest.java | 376 ++++++++--------- 4 files changed, 424 insertions(+), 496 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 807666ce4f97..10de0f839c33 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.UUID; /** This class handles the parameters of a {@link PreparedStatement}. */ class JdbcParameterStore { @@ -507,6 +508,8 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } } else if (value instanceof URL) { return binder.to(((URL) value).toString()); + } else if (value instanceof UUID) { + return binder.to(((UUID) value).toString()); } throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); case Types.DATE: @@ -649,6 +652,8 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu return binder.to(String.valueOf((char[]) value)); } else if (URL.class.isAssignableFrom(value.getClass())) { return binder.to(((URL) value).toString()); + } else if (UUID.class.isAssignableFrom(value.getClass())) { + return binder.to(((UUID) value).toString()); } else if (byte[].class.isAssignableFrom(value.getClass())) { return binder.to(ByteArray.copyFrom((byte[]) value)); } else if (InputStream.class.isAssignableFrom(value.getClass())) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 624a031ef90b..502ef5457d2c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -17,9 +17,9 @@ package com.google.cloud.spanner.jdbc; import static com.google.cloud.spanner.jdbc.JdbcParameterStore.convertPositionalParametersToNamedParameters; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.cloud.ByteArray; @@ -44,6 +44,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Arrays; +import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -58,66 +59,62 @@ public void testSetParameterWithType() throws SQLException, IOException { JdbcParameterStore params = new JdbcParameterStore(); // test the valid default combinations params.setParameter(1, true, Types.BOOLEAN); - assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + assertTrue((Boolean) params.getParameter(1)); verifyParameter(params, Value.bool(true)); params.setParameter(1, (byte) 1, Types.TINYINT); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (short) 1, Types.SMALLINT); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1, Types.INTEGER); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1L, Types.BIGINT); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, Types.FLOAT); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, Types.DOUBLE); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, new Date(1970 - 1900, 0, 1), Types.DATE); - assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); params.setParameter(1, new Time(0L), Types.TIME); - assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + assertEquals(new Time(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new Timestamp(0L), Types.TIMESTAMP); - assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new byte[] {1, 2, 3}, Types.BINARY); - assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); params.setParameter(1, "test", Types.NVARCHAR); - assertThat((String) params.getParameter(1), is(equalTo("test"))); + assertEquals("test", params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), Types.BLOB); - assertThat((JdbcBlob) params.getParameter(1), is(equalTo(new JdbcBlob(new byte[] {1, 2, 3})))); + assertEquals(new JdbcBlob(new byte[] {1, 2, 3}), params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); params.setParameter(1, new ByteArrayInputStream(new byte[] {1, 2, 3}), Types.BLOB); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); params.setParameter(1, new JdbcClob("test"), Types.CLOB); - assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, new StringReader("test"), Types.CLOB); - assertThat( - stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), - is(true)); + assertTrue(stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test"))); verifyParameter(params, Value.string("test")); params.setParameter(1, new JdbcClob("test"), Types.NCLOB); - assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, new StringReader("test"), Types.NCLOB); - assertThat( - stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), - is(true)); + assertTrue(stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test"))); verifyParameter(params, Value.string("test")); params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); @@ -126,80 +123,78 @@ public void testSetParameterWithType() throws SQLException, IOException { // types that should lead to int64 for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { params.setParameter(1, (byte) 1, type); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (short) 1, type); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1, type); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1L, type); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, type); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.int64(1)); params.setParameter(1, (double) 1, type); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.int64(1)); params.setParameter(1, BigDecimal.ONE, type); - assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + assertEquals(BigDecimal.ONE, params.getParameter(1)); verifyParameter(params, Value.int64(1)); } // types that should lead to float64 for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) { params.setParameter(1, (byte) 1, type); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.float64(1)); params.setParameter(1, (short) 1, type); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.float64(1)); params.setParameter(1, 1, type); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.float64(1)); params.setParameter(1, 1L, type); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.float64(1)); params.setParameter(1, (float) 1, type); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, type); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, BigDecimal.ONE, type); - assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + assertEquals(BigDecimal.ONE, params.getParameter(1)); verifyParameter(params, Value.float64(1)); } // types that should lead to date for (int type : new int[] {Types.DATE}) { params.setParameter(1, new Date(1970 - 1900, 0, 1), type); - assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); params.setParameter(1, new Time(0L), type); - assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + assertEquals(new Time(0L), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); params.setParameter(1, new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0), type); - assertThat( - (Timestamp) params.getParameter(1), - is(equalTo(new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0)))); + assertEquals(new Timestamp(1970 - 1900, 0, 1, 0, 0, 0, 0), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); } // types that should lead to timestamp for (int type : new int[] {Types.TIME, Types.TIMESTAMP}) { params.setParameter(1, new Date(0L), type); - assertThat((Date) params.getParameter(1), is(equalTo(new Date(0L)))); + assertEquals(new Date(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new Time(0L), type); - assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + assertEquals(new Time(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new Timestamp(0L), type); - assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); } @@ -207,7 +202,7 @@ public void testSetParameterWithType() throws SQLException, IOException { // types that should lead to bytes (except BLOB which is handled separately) for (int type : new int[] {Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY}) { params.setParameter(1, new byte[] {1, 2, 3}, type); - assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); } @@ -222,81 +217,78 @@ public void testSetParameterWithType() throws SQLException, IOException { Types.LONGNVARCHAR }) { params.setParameter(1, "test", type); - assertThat((String) params.getParameter(1), is(equalTo("test"))); + assertEquals("test", params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, new StringReader("test"), type); - assertThat( - stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test")), - is(true)); + assertTrue( + stringReadersEqual((StringReader) params.getParameter(1), new StringReader("test"))); verifyParameter(params, Value.string("test")); params.setParameter( 1, new ByteArrayInputStream(StandardCharsets.US_ASCII.encode("test").array()), type); - assertThat( + assertTrue( asciiStreamsEqual( (ByteArrayInputStream) params.getParameter(1), - new ByteArrayInputStream(StandardCharsets.US_ASCII.encode("test").array())), - is(true)); + new ByteArrayInputStream(StandardCharsets.US_ASCII.encode("test").array()))); verifyParameter(params, Value.string("test")); params.setParameter(1, new URL("https://cloud.google.com/spanner"), type); - assertThat( - (URL) params.getParameter(1), is(equalTo(new URL("https://cloud.google.com/spanner")))); + assertEquals(new URL("https://cloud.google.com/spanner"), params.getParameter(1)); verifyParameter(params, Value.string("https://cloud.google.com/spanner")); } // types that should lead to bool for (int type : new int[] {Types.BOOLEAN, Types.BIT}) { params.setParameter(1, true, type); - assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + assertTrue((Boolean) params.getParameter(1)); verifyParameter(params, Value.bool(true)); params.setParameter(1, (byte) 1, type); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.bool(true)); params.setParameter(1, (short) 0, type); - assertThat((Short) params.getParameter(1), is(equalTo((short) 0))); + assertEquals(0, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.bool(false)); params.setParameter(1, 1, type); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.bool(true)); params.setParameter(1, 1L, type); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.bool(true)); params.setParameter(1, (float) 1, type); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.bool(true)); params.setParameter(1, (double) 1, type); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.bool(true)); params.setParameter(1, BigDecimal.ZERO, type); - assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ZERO))); + assertEquals(BigDecimal.ZERO, params.getParameter(1)); verifyParameter(params, Value.bool(false)); } // types that should lead to numeric for (int type : new int[] {Types.DECIMAL, Types.NUMERIC}) { params.setParameter(1, BigDecimal.ONE, type); - assertThat((BigDecimal) params.getParameter(1), is(equalTo(BigDecimal.ONE))); + assertEquals(BigDecimal.ONE, params.getParameter(1)); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, (byte) 1, type); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, (short) 1, type); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, 1, type); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, 1L, type); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, (float) 1, type); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); params.setParameter(1, (double) 1, type); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); } } @@ -404,7 +396,7 @@ private void assertInvalidParameter(JdbcParameterStore params, Object value, int params.setParameter(1, value, type); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertEquals(Code.INVALID_ARGUMENT, e.getCode()); } } @@ -417,53 +409,56 @@ private void assertInvalidParameter(JdbcParameterStore params, Object value, int public void testSetParameterWithoutType() throws SQLException { JdbcParameterStore params = new JdbcParameterStore(); params.setParameter(1, (byte) 1, null); - assertThat((Byte) params.getParameter(1), is(equalTo((byte) 1))); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (short) 1, null); - assertThat((Short) params.getParameter(1), is(equalTo((short) 1))); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1, null); - assertThat((Integer) params.getParameter(1), is(equalTo(1))); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, 1L, null); - assertThat((Long) params.getParameter(1), is(equalTo(1L))); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, null); - assertThat((Float) params.getParameter(1), is(equalTo((float) 1))); + assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, null); - assertThat((Double) params.getParameter(1), is(equalTo((double) 1))); + assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, new Date(1970 - 1900, 0, 1), null); - assertThat((Date) params.getParameter(1), is(equalTo(new Date(1970 - 1900, 0, 1)))); + assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); params.setParameter(1, new Time(0L), null); - assertThat((Time) params.getParameter(1), is(equalTo(new Time(0L)))); + assertEquals(new Time(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new Timestamp(0L), null); - assertThat((Timestamp) params.getParameter(1), is(equalTo(new Timestamp(0L)))); + assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new byte[] {1, 2, 3}, null); - assertThat((byte[]) params.getParameter(1), is(equalTo(new byte[] {1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), null); - assertThat((JdbcBlob) params.getParameter(1), is(equalTo(new JdbcBlob(new byte[] {1, 2, 3})))); + assertEquals(new JdbcBlob(new byte[] {1, 2, 3}), params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); params.setParameter(1, new JdbcClob("test"), null); - assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, true, null); - assertThat((Boolean) params.getParameter(1), is(equalTo(true))); + assertTrue((Boolean) params.getParameter(1)); verifyParameter(params, Value.bool(true)); params.setParameter(1, "test", null); - assertThat((String) params.getParameter(1), is(equalTo("test"))); + assertEquals("test", params.getParameter(1)); verifyParameter(params, Value.string("test")); params.setParameter(1, new JdbcClob("test"), null); - assertThat((JdbcClob) params.getParameter(1), is(equalTo(new JdbcClob("test")))); + assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); + params.setParameter(1, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), null); + assertEquals(UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), params.getParameter(1)); + verifyParameter(params, Value.string("83b988cf-1f4e-428a-be3d-cc712621942e")); } private boolean stringReadersEqual(StringReader r1, StringReader r2) throws IOException { @@ -489,110 +484,92 @@ public void testSetArrayParameter() throws SQLException { JdbcParameterStore params = new JdbcParameterStore(); params.setParameter( 1, JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("BOOL", new Boolean[] {true, false, true})))); + assertEquals( + JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}), params.getParameter(1)); verifyParameter(params, Value.boolArray(new boolean[] {true, false, true})); params.setParameter( 1, JdbcArray.createArray("BOOL", new Boolean[] {true, false, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("BOOL", new Boolean[] {true, false, null})))); + assertEquals( + JdbcArray.createArray("BOOL", new Boolean[] {true, false, null}), params.getParameter(1)); verifyParameter(params, Value.boolArray(Arrays.asList(true, false, null))); params.setParameter(1, JdbcArray.createArray("BOOL", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("BOOL", null)))); + assertEquals(JdbcArray.createArray("BOOL", null), params.getParameter(1)); verifyParameter(params, Value.boolArray((boolean[]) null)); params.setParameter(1, JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L})))); + assertEquals(JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}), params.getParameter(1)); verifyParameter(params, Value.int64Array(new long[] {1, 2, 3})); params.setParameter(1, JdbcArray.createArray("INT64", new Long[] {1L, 2L, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("INT64", new Long[] {1L, 2L, null})))); + assertEquals(JdbcArray.createArray("INT64", new Long[] {1L, 2L, null}), params.getParameter(1)); verifyParameter(params, Value.int64Array(Arrays.asList(1L, 2L, null))); params.setParameter(1, JdbcArray.createArray("INT64", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("INT64", null)))); + assertEquals(JdbcArray.createArray("INT64", null), params.getParameter(1)); verifyParameter(params, Value.int64Array((long[]) null)); params.setParameter( 1, JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, 3D}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, 3D})))); + assertEquals( + JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, 3D}), params.getParameter(1)); verifyParameter(params, Value.float64Array(new double[] {1, 2, 3})); params.setParameter( 1, JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, null})))); + assertEquals( + JdbcArray.createArray("FLOAT64", new Double[] {1D, 2D, null}), params.getParameter(1)); verifyParameter(params, Value.float64Array(Arrays.asList(1D, 2D, null))); params.setParameter(1, JdbcArray.createArray("FLOAT64", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("FLOAT64", null)))); + assertEquals(JdbcArray.createArray("FLOAT64", null), params.getParameter(1)); verifyParameter(params, Value.float64Array((double[]) null)); @SuppressWarnings("deprecation") Date sqlDate = new Date(2018 - 1900, 12 - 1, 14); params.setParameter(1, JdbcArray.createArray("DATE", new Date[] {sqlDate}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("DATE", new Date[] {sqlDate})))); + assertEquals(JdbcArray.createArray("DATE", new Date[] {sqlDate}), params.getParameter(1)); verifyParameter( params, Value.dateArray(Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14)))); params.setParameter(1, JdbcArray.createArray("DATE", new Date[] {sqlDate, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("DATE", new Date[] {sqlDate, null})))); + assertEquals(JdbcArray.createArray("DATE", new Date[] {sqlDate, null}), params.getParameter(1)); verifyParameter( params, Value.dateArray(Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14), null))); params.setParameter(1, JdbcArray.createArray("DATE", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("DATE", null)))); + assertEquals(JdbcArray.createArray("DATE", null), params.getParameter(1)); verifyParameter(params, Value.dateArray(null)); Timestamp sqlTimestamp = new Timestamp(System.currentTimeMillis()); params.setParameter( 1, JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp})))); + assertEquals( + JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp}), params.getParameter(1)); verifyParameter( params, Value.timestampArray(Arrays.asList(com.google.cloud.Timestamp.of(sqlTimestamp)))); params.setParameter( 1, JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null})))); + assertEquals( + JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null}), + params.getParameter(1)); verifyParameter( params, Value.timestampArray(Arrays.asList(com.google.cloud.Timestamp.of(sqlTimestamp), null))); params.setParameter(1, JdbcArray.createArray("TIMESTAMP", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("TIMESTAMP", null)))); + assertEquals(JdbcArray.createArray("TIMESTAMP", null), params.getParameter(1)); verifyParameter(params, Value.timestampArray(null)); params.setParameter( 1, JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}})))); + assertEquals( + JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}}), + params.getParameter(1)); verifyParameter( params, Value.bytesArray( @@ -602,9 +579,9 @@ public void testSetArrayParameter() throws SQLException { params.setParameter( 1, JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}, null}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}, null})))); + assertEquals( + JdbcArray.createArray("BYTES", new byte[][] {{1, 2, 3}, {4, 5, 6}, null}), + params.getParameter(1)); verifyParameter( params, Value.bytesArray( @@ -614,38 +591,34 @@ public void testSetArrayParameter() throws SQLException { null))); params.setParameter(1, JdbcArray.createArray("BYTES", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("BYTES", null)))); + assertEquals(JdbcArray.createArray("BYTES", null), params.getParameter(1)); verifyParameter(params, Value.bytesArray(null)); params.setParameter( 1, JdbcArray.createArray("STRING", new String[] {"test1", "test2", "test3"}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is(equalTo(JdbcArray.createArray("STRING", new String[] {"test1", "test2", "test3"})))); + assertEquals( + JdbcArray.createArray("STRING", new String[] {"test1", "test2", "test3"}), + params.getParameter(1)); verifyParameter(params, Value.stringArray(Arrays.asList("test1", "test2", "test3"))); params.setParameter( 1, JdbcArray.createArray("STRING", new String[] {"test1", null, "test2", "test3"}), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), - is( - equalTo( - JdbcArray.createArray("STRING", new String[] {"test1", null, "test2", "test3"})))); + assertEquals( + JdbcArray.createArray("STRING", new String[] {"test1", null, "test2", "test3"}), + params.getParameter(1)); verifyParameter(params, Value.stringArray(Arrays.asList("test1", null, "test2", "test3"))); params.setParameter(1, JdbcArray.createArray("STRING", null), Types.ARRAY); - assertThat( - (JdbcArray) params.getParameter(1), is(equalTo(JdbcArray.createArray("STRING", null)))); + assertEquals(JdbcArray.createArray("STRING", null), params.getParameter(1)); verifyParameter(params, Value.stringArray(null)); } private void verifyParameter(JdbcParameterStore params, Value value) throws SQLException { Statement.Builder builder = Statement.newBuilder("SELECT * FROM FOO WHERE BAR=:p1"); params.bindParameterValue(builder.bind("p1"), 1); - assertThat(builder.build().getParameters().get("p1"), is(equalTo(value))); + assertEquals(value, builder.build().getParameters().get("p1")); } private void verifyParameterBindFails(JdbcParameterStore params) throws SQLException { @@ -654,80 +627,82 @@ private void verifyParameterBindFails(JdbcParameterStore params) throws SQLExcep params.bindParameterValue(builder.bind("p1"), 1); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertEquals(Code.INVALID_ARGUMENT, e.getCode()); } } @Test public void testConvertPositionalParametersToNamedParameters() throws SQLException { - assertThat( + assertEquals( + "select * from foo where name=@p1", convertPositionalParametersToNamedParameters("select * from foo where name=?") - .sqlWithNamedParameters, - is(equalTo("select * from foo where name=@p1"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "@p1'?test?\"?test?\"?'@p2", convertPositionalParametersToNamedParameters("?'?test?\"?test?\"?'?") - .sqlWithNamedParameters, - is(equalTo("@p1'?test?\"?test?\"?'@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?'?it\\'?s'?").sqlWithNamedParameters, - is(equalTo("@p1'?it\\'?s'@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?'?it\\\"?s'?").sqlWithNamedParameters, - is(equalTo("@p1'?it\\\"?s'@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?\"?it\\\"?s\"?").sqlWithNamedParameters, - is(equalTo("@p1\"?it\\\"?s\"@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?`?it\\`?s`?").sqlWithNamedParameters, - is(equalTo("@p1`?it\\`?s`@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?'''?it\\'?s'''?").sqlWithNamedParameters, - is(equalTo("@p1'''?it\\'?s'''@p2"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "@p1'?it\\'?s'@p2", + convertPositionalParametersToNamedParameters("?'?it\\'?s'?").sqlWithNamedParameters); + assertEquals( + "@p1'?it\\\"?s'@p2", + convertPositionalParametersToNamedParameters("?'?it\\\"?s'?").sqlWithNamedParameters); + assertEquals( + "@p1\"?it\\\"?s\"@p2", + convertPositionalParametersToNamedParameters("?\"?it\\\"?s\"?").sqlWithNamedParameters); + assertEquals( + "@p1`?it\\`?s`@p2", + convertPositionalParametersToNamedParameters("?`?it\\`?s`?").sqlWithNamedParameters); + assertEquals( + "@p1'''?it\\'?s'''@p2", + convertPositionalParametersToNamedParameters("?'''?it\\'?s'''?").sqlWithNamedParameters); + assertEquals( + "@p1\"\"\"?it\\\"?s\"\"\"@p2", convertPositionalParametersToNamedParameters("?\"\"\"?it\\\"?s\"\"\"?") - .sqlWithNamedParameters, - is(equalTo("@p1\"\"\"?it\\\"?s\"\"\"@p2"))); - assertThat( - convertPositionalParametersToNamedParameters("?```?it\\`?s```?").sqlWithNamedParameters, - is(equalTo("@p1```?it\\`?s```@p2"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "@p1```?it\\`?s```@p2", + convertPositionalParametersToNamedParameters("?```?it\\`?s```?").sqlWithNamedParameters); + assertEquals( + "@p1'''?it\\'?s \n ?it\\'?s'''@p2", convertPositionalParametersToNamedParameters("?'''?it\\'?s \n ?it\\'?s'''?") - .sqlWithNamedParameters, - is(equalTo("@p1'''?it\\'?s \n ?it\\'?s'''@p2"))); + .sqlWithNamedParameters); assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); - assertThat( + assertEquals( + "select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'", convertPositionalParametersToNamedParameters( "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") - .sqlWithNamedParameters, - is( - equalTo( - "select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'"))); + .sqlWithNamedParameters); - assertThat( + assertEquals( + "select * " + "from foo " + "where name=@p1 " + "and col2 like @p2 " + "and col3 > @p3", convertPositionalParametersToNamedParameters( "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") - .sqlWithNamedParameters, - is( - equalTo( - "select * " - + "from foo " - + "where name=@p1 " - + "and col2 like @p2 " - + "and col3 > @p3"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "select * " + "from foo " + "where id between @p1 and @p2", convertPositionalParametersToNamedParameters( "select * " + "from foo " + "where id between ? and ?") - .sqlWithNamedParameters, - is(equalTo("select * " + "from foo " + "where id between @p1 and @p2"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "select * " + "from foo " + "limit @p1 offset @p2", convertPositionalParametersToNamedParameters("select * " + "from foo " + "limit ? offset ?") - .sqlWithNamedParameters, - is(equalTo("select * " + "from foo " + "limit @p1 offset @p2"))); - assertThat( + .sqlWithNamedParameters); + assertEquals( + "select * " + + "from foo " + + "where col1=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3 " + + "and col4 < @p4 " + + "and col5 != @p5 " + + "and col6 not in (@p6, @p7, @p8) " + + "and col7 in (@p9, @p10, @p11) " + + "and col8 between @p12 and @p13", convertPositionalParametersToNamedParameters( "select * " + "from foo " @@ -739,19 +714,7 @@ public void testConvertPositionalParametersToNamedParameters() throws SQLExcepti + "and col6 not in (?, ?, ?) " + "and col7 in (?, ?, ?) " + "and col8 between ? and ?") - .sqlWithNamedParameters, - is( - equalTo( - "select * " - + "from foo " - + "where col1=@p1 " - + "and col2 like @p2 " - + "and col3 > @p3 " - + "and col4 < @p4 " - + "and col5 != @p5 " - + "and col6 not in (@p6, @p7, @p8) " - + "and col7 in (@p9, @p10, @p11) " - + "and col8 between @p12 and @p13"))); + .sqlWithNamedParameters); } private void assertUnclosedLiteral(String sql) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index c5d939601b0b..85334b2f74ce 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -16,9 +16,10 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; @@ -49,7 +50,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.TimeZone; -import org.junit.Assert; +import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -148,94 +149,89 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setTimestamp(46, new Timestamp(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); ps.setUnicodeStream(47, new ByteArrayInputStream("TEST".getBytes()), 4); ps.setURL(48, new URL("https://spanner.google.com")); + ps.setObject(49, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e")); testSetUnsupportedTypes(ps); JdbcParameterMetaData pmd = ps.getParameterMetaData(); - Assert.assertEquals(numberOfParams, pmd.getParameterCount()); - Assert.assertEquals(JdbcArray.class.getName(), pmd.getParameterClassName(1)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(2)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(3)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(4)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(6)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(7)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(8)); - Assert.assertEquals(JdbcBlob.class.getName(), pmd.getParameterClassName(9)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(10)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(11)); - Assert.assertEquals(Boolean.class.getName(), pmd.getParameterClassName(12)); - Assert.assertEquals(Byte.class.getName(), pmd.getParameterClassName(13)); - Assert.assertEquals(byte[].class.getName(), pmd.getParameterClassName(14)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(15)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(16)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(17)); - Assert.assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(18)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(19)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(20)); - Assert.assertEquals(Date.class.getName(), pmd.getParameterClassName(21)); - Assert.assertEquals(Date.class.getName(), pmd.getParameterClassName(22)); - Assert.assertEquals(Double.class.getName(), pmd.getParameterClassName(23)); - Assert.assertEquals(Float.class.getName(), pmd.getParameterClassName(24)); - Assert.assertEquals(Integer.class.getName(), pmd.getParameterClassName(25)); - Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(26)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(27)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(28)); - Assert.assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(29)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(30)); - Assert.assertEquals(StringReader.class.getName(), pmd.getParameterClassName(31)); - Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(32)); - Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(33)); - Assert.assertEquals(Long.class.getName(), pmd.getParameterClassName(34)); - Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(35)); - Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(36)); - Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(37)); - Assert.assertNull(pmd.getParameterClassName(38)); - Assert.assertNull(pmd.getParameterClassName(39)); - Assert.assertEquals(Short.class.getName(), pmd.getParameterClassName(40)); - Assert.assertNull(pmd.getParameterClassName(41)); - Assert.assertEquals(String.class.getName(), pmd.getParameterClassName(42)); - Assert.assertEquals(Time.class.getName(), pmd.getParameterClassName(43)); - Assert.assertEquals(Time.class.getName(), pmd.getParameterClassName(44)); - Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(45)); - Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(46)); - Assert.assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(47)); - Assert.assertEquals(URL.class.getName(), pmd.getParameterClassName(48)); + assertEquals(numberOfParams, pmd.getParameterCount()); + assertEquals(JdbcArray.class.getName(), pmd.getParameterClassName(1)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(2)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(3)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(4)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(6)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(7)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(8)); + assertEquals(JdbcBlob.class.getName(), pmd.getParameterClassName(9)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(10)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(11)); + assertEquals(Boolean.class.getName(), pmd.getParameterClassName(12)); + assertEquals(Byte.class.getName(), pmd.getParameterClassName(13)); + assertEquals(byte[].class.getName(), pmd.getParameterClassName(14)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(15)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(16)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(17)); + assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(18)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(19)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(20)); + assertEquals(Date.class.getName(), pmd.getParameterClassName(21)); + assertEquals(Date.class.getName(), pmd.getParameterClassName(22)); + assertEquals(Double.class.getName(), pmd.getParameterClassName(23)); + assertEquals(Float.class.getName(), pmd.getParameterClassName(24)); + assertEquals(Integer.class.getName(), pmd.getParameterClassName(25)); + assertEquals(Long.class.getName(), pmd.getParameterClassName(26)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(27)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(28)); + assertEquals(JdbcClob.class.getName(), pmd.getParameterClassName(29)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(30)); + assertEquals(StringReader.class.getName(), pmd.getParameterClassName(31)); + assertEquals(String.class.getName(), pmd.getParameterClassName(32)); + assertEquals(Long.class.getName(), pmd.getParameterClassName(33)); + assertEquals(Long.class.getName(), pmd.getParameterClassName(34)); + assertEquals(String.class.getName(), pmd.getParameterClassName(35)); + assertEquals(String.class.getName(), pmd.getParameterClassName(36)); + assertEquals(String.class.getName(), pmd.getParameterClassName(37)); + assertNull(pmd.getParameterClassName(38)); + assertNull(pmd.getParameterClassName(39)); + assertEquals(Short.class.getName(), pmd.getParameterClassName(40)); + assertNull(pmd.getParameterClassName(41)); + assertEquals(String.class.getName(), pmd.getParameterClassName(42)); + assertEquals(Time.class.getName(), pmd.getParameterClassName(43)); + assertEquals(Time.class.getName(), pmd.getParameterClassName(44)); + assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(45)); + assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(46)); + assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(47)); + assertEquals(URL.class.getName(), pmd.getParameterClassName(48)); + assertEquals(UUID.class.getName(), pmd.getParameterClassName(49)); ps.clearParameters(); pmd = ps.getParameterMetaData(); - Assert.assertEquals(numberOfParams, pmd.getParameterCount()); + assertEquals(numberOfParams, pmd.getParameterCount()); } } private void testSetUnsupportedTypes(PreparedStatement ps) { - // TODO: Rewrite these tests using functional interfaces when Java8 is available. - boolean expectedException = false; try { ps.setRef(38, (Ref) null); + fail("missing expected exception"); } catch (SQLException e) { - if (e instanceof JdbcSqlException) { - expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; - } + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } - assertThat(expectedException, is(true)); - expectedException = false; try { ps.setRowId(39, (RowId) null); + fail("missing expected exception"); } catch (SQLException e) { - if (e instanceof JdbcSqlException) { - expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; - } + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } - assertThat(expectedException, is(true)); - expectedException = false; try { ps.setSQLXML(41, (SQLXML) null); + fail("missing expected exception"); } catch (SQLException e) { - if (e instanceof JdbcSqlException) { - expectedException = ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT; - } + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } - assertThat(expectedException, is(true)); } @Test @@ -269,12 +265,12 @@ public void testSetNullValues() throws SQLException { ps.setNull(27, Types.VARCHAR); JdbcParameterMetaData pmd = ps.getParameterMetaData(); - Assert.assertEquals(27, pmd.getParameterCount()); - Assert.assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(14)); + assertEquals(27, pmd.getParameterCount()); + assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(14)); ps.clearParameters(); pmd = ps.getParameterMetaData(); - Assert.assertEquals(27, pmd.getParameterCount()); + assertEquals(27, pmd.getParameterCount()); } } @@ -301,13 +297,13 @@ public void testGetResultSetMetadata() throws SQLException { try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(connection), sql)) { ResultSetMetaData metadata = ps.getMetaData(); - assertThat(metadata.getColumnCount(), is(equalTo(3))); - assertThat(metadata.getColumnLabel(1), is(equalTo("ID"))); - assertThat(metadata.getColumnLabel(2), is(equalTo("NAME"))); - assertThat(metadata.getColumnLabel(3), is(equalTo("AMOUNT"))); - assertThat(metadata.getColumnType(1), is(equalTo(Types.BIGINT))); - assertThat(metadata.getColumnType(2), is(equalTo(Types.NVARCHAR))); - assertThat(metadata.getColumnType(3), is(equalTo(Types.DOUBLE))); + assertEquals(3, metadata.getColumnCount()); + assertEquals("ID", metadata.getColumnLabel(1)); + assertEquals("NAME", metadata.getColumnLabel(2)); + assertEquals("AMOUNT", metadata.getColumnLabel(3)); + assertEquals(Types.BIGINT, metadata.getColumnType(1)); + assertEquals(Types.NVARCHAR, metadata.getColumnType(2)); + assertEquals(Types.DOUBLE, metadata.getColumnType(3)); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 799b494d0e62..b4e02a985a0b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -16,13 +16,13 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertArrayEquals; +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.assertTrue; import static org.junit.Assert.fail; -import static org.junit.Assume.assumeFalse; import com.google.api.client.util.Base64; import com.google.cloud.spanner.IntegrationTest; @@ -47,7 +47,7 @@ import java.util.List; import java.util.Scanner; import java.util.TimeZone; -import org.junit.BeforeClass; +import java.util.UUID; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -257,11 +257,6 @@ private List createConcerts() { return res; } - @BeforeClass - public static void notOnEmulator() { - assumeFalse("foreign keys are not supported on the emulator", env.getTestHelper().isEmulator()); - } - @Override protected boolean doCreateMusicTables() { return true; @@ -289,7 +284,7 @@ public void test01_InsertTestData() throws SQLException { } int[] results = ps.executeBatch(); for (int res : results) { - assertThat(res, is(equalTo(1))); + assertEquals(1, res); } } try (PreparedStatement ps = @@ -302,7 +297,7 @@ public void test01_InsertTestData() throws SQLException { ps.setString(3, album.albumTitle); ps.setLong(4, album.marketingBudget); assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); - assertThat(ps.executeUpdate(), is(equalTo(1))); + assertEquals(1, ps.executeUpdate()); // check that calling executeUpdate will not reset the meta data assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); } @@ -319,7 +314,7 @@ public void test01_InsertTestData() throws SQLException { ps.setLong(5, song.duration); ps.setCharacterStream(6, new StringReader(song.songGenre)); assertInsertSongParameterMetadata(ps.getParameterMetaData()); - assertThat(ps.executeUpdate(), is(equalTo(1))); + assertEquals(1, ps.executeUpdate()); // check that calling executeUpdate will not reset the meta data assertInsertSongParameterMetadata(ps.getParameterMetaData()); } @@ -336,7 +331,7 @@ public void test01_InsertTestData() throws SQLException { ps.setTimestamp(5, concert.endTime); ps.setArray(6, connection.createArrayOf("INT64", concert.ticketPrices)); assertInsertConcertParameterMetadata(ps.getParameterMetaData()); - assertThat(ps.executeUpdate(), is(equalTo(1))); + assertEquals(1, ps.executeUpdate()); // check that calling executeUpdate will not reset the meta data assertInsertConcertParameterMetadata(ps.getParameterMetaData()); } @@ -350,26 +345,26 @@ public void test02_VerifyTestData() throws SQLException { try (Connection connection = createConnection()) { try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Singers")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getInt(1), is(equalTo(30))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(30, rs.getInt(1)); + assertFalse(rs.next()); } try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Albums")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getByte(1), is(equalTo((byte) 60))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(60, rs.getByte(1)); + assertFalse(rs.next()); } try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Songs")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getShort(1), is(equalTo((short) 149))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(149, rs.getShort(1)); + assertFalse(rs.next()); } try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Concerts")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(100L))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(100L, rs.getLong(1)); + assertFalse(rs.next()); } try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM Concerts WHERE VenueId=? AND SingerId=?")) { @@ -379,13 +374,13 @@ public void test02_VerifyTestData() throws SQLException { // (1,1,DATE '2003-06-19',TIMESTAMP '2003-06-19T12:30:05Z',TIMESTAMP // '2003-06-19T18:57:15Z',[11,93,140,923]); try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(1L))); - assertThat(rs.getLong(2), is(equalTo(1L))); - assertThat(rs.getDate(3), is(equalTo(Date.valueOf("2003-06-19")))); - assertThat(rs.getTimestamp(4), is(equalTo(Timestamp.valueOf("2003-06-19 12:30:05")))); - assertThat(rs.getTimestamp(5), is(equalTo(Timestamp.valueOf("2003-06-19 18:57:15")))); - assertThat(((Long[]) rs.getArray(6).getArray())[0], is(equalTo(11L))); + assertTrue(rs.next()); + assertEquals(1L, rs.getLong(1)); + assertEquals(1L, rs.getLong(2)); + assertEquals(Date.valueOf("2003-06-19"), rs.getDate(3)); + assertEquals(Timestamp.valueOf("2003-06-19 12:30:05"), rs.getTimestamp(4)); + assertEquals(Timestamp.valueOf("2003-06-19 18:57:15"), rs.getTimestamp(5)); + assertArrayEquals(new Long[] {11L, 93L, 140L, 923L}, (Long[]) rs.getArray(6).getArray()); } } } @@ -461,9 +456,9 @@ public void test03_Dates() throws SQLException { ps.setLong(1, 100L); ps.setLong(2, 19L); try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); + assertTrue(rs.next()); if (testCalendar == null) { - assertThat(rs.getDate(3), is(equalTo(Date.valueOf(expectedValues.get(index))))); + assertEquals(Date.valueOf(expectedValues.get(index)), rs.getDate(3)); } else { // Parse the date in the local timezone. Date date = Date.valueOf(expectedValues.get(index)); @@ -473,9 +468,8 @@ public void test03_Dates() throws SQLException { localCalendar.set(date.getYear() + 1900, date.getMonth(), date.getDate()); // Check that the actual time of the date returned by the ResultSet is equal to the // local time in the timezone of the Calendar that is used. - assertThat( - rs.getDate(3, testCalendar), - is(equalTo(new Date(localCalendar.getTimeInMillis())))); + assertEquals( + new Date(localCalendar.getTimeInMillis()), rs.getDate(3, testCalendar)); } } } @@ -567,38 +561,34 @@ public void test04_Timestamps() throws SQLException { ps.setLong(1, 100L); ps.setLong(2, 19L); try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); + assertTrue(rs.next()); // First test the timestamp that was sent to Spanner using the default timezone. // Get the timestamp in the default timezone. Timestamp inDefaultTZ = rs.getTimestamp(4); - assertThat(inDefaultTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); // Then get it in the test timezone. if (testCalendar != null) { Timestamp inOtherTZ = rs.getTimestamp(4, testCalendar); - assertThat( - inOtherTZ.getTime(), - is( - equalTo( - testTimestamp.getTime() + testCalendar.getTimeZone().getRawOffset()))); + assertEquals( + testTimestamp.getTime() + testCalendar.getTimeZone().getRawOffset(), + inOtherTZ.getTime()); } // Then test the timestamp that was sent to Spanner using a specific timezone. // Get the timestamp in the default timezone. inDefaultTZ = rs.getTimestamp(5); if (testCalendar == null) { - assertThat(inDefaultTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); } else { - assertThat( - inDefaultTZ.getTime(), - is( - equalTo( - testTimestamp.getTime() - testCalendar.getTimeZone().getRawOffset()))); + assertEquals( + testTimestamp.getTime() - testCalendar.getTimeZone().getRawOffset(), + inDefaultTZ.getTime()); } // Then get it in the test timezone. if (testCalendar != null) { Timestamp inOtherTZ = rs.getTimestamp(5, testCalendar); - assertThat(inOtherTZ.getTime(), is(equalTo(testTimestamp.getTime()))); + assertEquals(testTimestamp.getTime(), inOtherTZ.getTime()); } } } @@ -626,15 +616,15 @@ public void test05_BatchUpdates() throws SQLException { } updateCounts = ps.executeBatch(); } - assertThat(updateCounts.length, is(equalTo(params.length))); + assertEquals(params.length, updateCounts.length); long totalUpdated = 0; try (PreparedStatement ps = con1.prepareStatement("SELECT COUNT(*) FROM Singers WHERE LastName LIKE ?")) { for (int i = 0; i < updateCounts.length; i++) { ps.setString(1, params[i]); try (ResultSet rs = ps.executeQuery()) { - assertThat(rs.next(), is(true)); - assertThat(updateCounts[i], is(equalTo(rs.getInt(1)))); + assertTrue(rs.next()); + assertEquals(rs.getInt(1), updateCounts[i]); totalUpdated += updateCounts[i]; } } @@ -643,11 +633,11 @@ public void test05_BatchUpdates() throws SQLException { try (ResultSet rs = con2.createStatement() .executeQuery("SELECT COUNT(*) FROM Singers WHERE FirstName=LastName")) { - assertThat(rs.next(), is(true)); + assertTrue(rs.next()); if (autocommit) { - assertThat(rs.getLong(1), is(equalTo(totalUpdated))); + assertEquals(totalUpdated, rs.getLong(1)); } else { - assertThat(rs.getLong(1), is(equalTo(0L))); + assertEquals(0, rs.getLong(1)); } } // If not in autocommit mode --> commit and verify. @@ -656,15 +646,15 @@ public void test05_BatchUpdates() throws SQLException { try (ResultSet rs = con2.createStatement() .executeQuery("SELECT COUNT(*) FROM Singers WHERE FirstName=LastName")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(totalUpdated))); + assertTrue(rs.next()); + assertEquals(totalUpdated, rs.getLong(1)); } } // Set first names to null for the updated records for the next test run. - assertThat( + int updateCount = con2.createStatement() - .executeUpdate("UPDATE Singers SET FirstName=null WHERE FirstName=LastName"), - is(equalTo((int) totalUpdated))); + .executeUpdate("UPDATE Singers SET FirstName=null WHERE FirstName=LastName"); + assertEquals(totalUpdated, updateCount); } } } @@ -688,7 +678,7 @@ public void test06_BatchUpdatesWithException() throws SQLException { ps.executeBatch(); fail("missing expected BatchUpdateException"); } catch (BatchUpdateException e) { - assertThat(e.getUpdateCounts().length, is(equalTo(2))); + assertEquals(2, e.getUpdateCounts().length); } // If not in autocommit mode --> rollback before the next run. if (!autocommit) { @@ -719,7 +709,7 @@ public void test07_StatementBatchUpdateWithException() throws SQLException { statement.executeBatch(); fail("missing expected BatchUpdateException"); } catch (BatchUpdateException e) { - assertThat(e.getUpdateCounts(), is(notNullValue())); + assertNotNull(e.getUpdateCounts()); } // The following statements will fail because the table does not exist. try (Statement statement = con.createStatement()) { @@ -734,7 +724,7 @@ public void test07_StatementBatchUpdateWithException() throws SQLException { statement.executeBatch(); fail(); } catch (BatchUpdateException e) { - assertThat(e.getUpdateCounts(), is(notNullValue())); + assertNotNull(e.getUpdateCounts()); } // The following statements will fail because the primary key values conflict. try (Statement statement = con.createStatement()) { @@ -745,7 +735,7 @@ public void test07_StatementBatchUpdateWithException() throws SQLException { statement.executeBatch(); fail(); } catch (BatchUpdateException e) { - assertThat(e.getUpdateCounts(), is(notNullValue())); + assertNotNull(e.getUpdateCounts()); } } } @@ -763,7 +753,7 @@ public void test08_InsertAllColumnTypes() throws SQLException { ps.setDouble(2, 2D); ps.setBoolean(3, true); ps.setString(4, "test"); - ps.setString(5, "testtest"); + ps.setObject(5, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); ps.setBytes(6, "test".getBytes()); ps.setBytes(7, "testtest".getBytes()); ps.setDate(8, new Date(System.currentTimeMillis())); @@ -797,59 +787,56 @@ public void test08_InsertAllColumnTypes() throws SQLException { ps.setArray( 20, con.createArrayOf("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN})); - assertThat(ps.executeUpdate(), is(equalTo(1))); + assertEquals(1, ps.executeUpdate()); } try (ResultSet rs = con.createStatement().executeQuery("SELECT * FROM TableWithAllColumnTypes")) { - assertThat(rs.next(), is(true)); - assertThat(rs.getLong(1), is(equalTo(1L))); - assertThat(rs.getDouble(2), is(equalTo(2D))); - assertThat(rs.getBoolean(3), is(true)); - assertThat(rs.getString(4), is(equalTo("test"))); - assertThat(rs.getString(5), is(equalTo("testtest"))); - assertThat(rs.getBytes(6), is(equalTo("test".getBytes()))); - assertThat(rs.getBytes(7), is(equalTo("testtest".getBytes()))); - assertThat(rs.getDate(8), is(notNullValue())); - assertThat(rs.getTimestamp(9), is(notNullValue())); - assertThat(rs.getTime(10), is(notNullValue())); // Commit timestamp - assertThat(rs.getBigDecimal(11), is(equalTo(BigDecimal.TEN))); - assertThat((Long[]) rs.getArray(12).getArray(), is(equalTo(new Long[] {1L, 2L, 3L}))); - assertThat( - (Double[]) rs.getArray(13).getArray(), is(equalTo(new Double[] {1.1D, 2.2D, 3.3D}))); - assertThat( - (Boolean[]) rs.getArray(14).getArray(), is(equalTo(new Boolean[] {true, null, false}))); - assertThat( - (String[]) rs.getArray(15).getArray(), is(equalTo(new String[] {"1", "2", "3"}))); - assertThat( - (String[]) rs.getArray(16).getArray(), is(equalTo(new String[] {"3", "2", "1"}))); - assertThat( - (byte[][]) rs.getArray(17).getArray(), - is(equalTo(new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()}))); - assertThat( - (byte[][]) rs.getArray(18).getArray(), - is(equalTo(new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()}))); - assertThat(((Date[]) rs.getArray(19).getArray()).length, is(equalTo(3))); - assertThat(((Timestamp[]) rs.getArray(20).getArray()).length, is(equalTo(3))); - assertThat( - (BigDecimal[]) rs.getArray(21).getArray(), - is(equalTo(new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(1L, rs.getLong(1)); + assertEquals(2d, rs.getDouble(2), 0.0d); + assertTrue(rs.getBoolean(3)); + assertEquals("test", rs.getString(4)); + assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(5)); + assertArrayEquals("test".getBytes(), rs.getBytes(6)); + assertArrayEquals("testtest".getBytes(), rs.getBytes(7)); + assertNotNull(rs.getDate(8)); + assertNotNull(rs.getTimestamp(9)); + assertNotNull(rs.getTime(10)); // Commit timestamp + assertEquals(BigDecimal.TEN, rs.getBigDecimal(11)); + assertArrayEquals(new Long[] {1L, 2L, 3L}, (Long[]) rs.getArray(12).getArray()); + assertArrayEquals(new Double[] {1.1D, 2.2D, 3.3D}, (Double[]) rs.getArray(13).getArray()); + assertArrayEquals( + new Boolean[] {true, null, false}, (Boolean[]) rs.getArray(14).getArray()); + assertArrayEquals(new String[] {"1", "2", "3"}, (String[]) rs.getArray(15).getArray()); + assertArrayEquals(new String[] {"3", "2", "1"}, (String[]) rs.getArray(16).getArray()); + assertArrayEquals( + new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()}, + (byte[][]) rs.getArray(17).getArray()); + assertArrayEquals( + new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()}, + (byte[][]) rs.getArray(18).getArray()); + assertEquals(3, ((Date[]) rs.getArray(19).getArray()).length); + assertEquals(3, ((Timestamp[]) rs.getArray(20).getArray()).length); + assertArrayEquals( + new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}, + (BigDecimal[]) rs.getArray(21).getArray()); + assertFalse(rs.next()); } } } private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) throws SQLException { - assertThat(pmd.getParameterCount(), is(equalTo(expectedParamCount))); + assertEquals(expectedParamCount, pmd.getParameterCount()); for (int param = 1; param <= expectedParamCount; param++) { - assertThat(pmd.getParameterType(param), is(equalTo(Types.OTHER))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("OTHER"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(nullValue())); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertEquals(Types.OTHER, pmd.getParameterType(param)); + assertEquals("OTHER", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertNull(pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } } @@ -877,7 +864,7 @@ private List readValuesFromFile(String filename) { } private void assertInsertSingerParameterMetadata(ParameterMetaData pmd) throws SQLException { - assertThat(pmd.getParameterCount(), is(equalTo(5))); + assertEquals(5, pmd.getParameterCount()); assertByteParam(pmd, 1); assertStringParam(pmd, 2); assertStringParam(pmd, 3); @@ -886,7 +873,7 @@ private void assertInsertSingerParameterMetadata(ParameterMetaData pmd) throws S } private void assertInsertAlbumParameterMetadata(ParameterMetaData pmd) throws SQLException { - assertThat(pmd.getParameterCount(), is(equalTo(4))); + assertEquals(4, pmd.getParameterCount()); assertLongParam(pmd, 1); assertLongParam(pmd, 2); assertStringParam(pmd, 3); @@ -894,7 +881,7 @@ private void assertInsertAlbumParameterMetadata(ParameterMetaData pmd) throws SQ } private void assertInsertSongParameterMetadata(ParameterMetaData pmd) throws SQLException { - assertThat(pmd.getParameterCount(), is(equalTo(6))); + assertEquals(6, pmd.getParameterCount()); assertByteParam(pmd, 1); assertIntParam(pmd, 2); assertShortParam(pmd, 3); @@ -904,7 +891,7 @@ private void assertInsertSongParameterMetadata(ParameterMetaData pmd) throws SQL } private void assertInsertConcertParameterMetadata(ParameterMetaData pmd) throws SQLException { - assertThat(pmd.getParameterCount(), is(equalTo(6))); + assertEquals(6, pmd.getParameterCount()); assertLongParam(pmd, 1); assertLongParam(pmd, 2); assertDateParam(pmd, 3); @@ -914,124 +901,101 @@ private void assertInsertConcertParameterMetadata(ParameterMetaData pmd) throws } private void assertLongParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.BIGINT))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Long.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(true)); + assertEquals(Types.BIGINT, pmd.getParameterType(param)); + assertInt64Param(pmd, param, Long.class); } private void assertIntParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.INTEGER))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Integer.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(true)); + assertEquals(Types.INTEGER, pmd.getParameterType(param)); + assertInt64Param(pmd, param, Integer.class); } private void assertShortParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.SMALLINT))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Short.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(true)); + assertEquals(Types.SMALLINT, pmd.getParameterType(param)); + assertInt64Param(pmd, param, Short.class); } private void assertByteParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.TINYINT))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("INT64"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Byte.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(true)); + assertEquals(Types.TINYINT, pmd.getParameterType(param)); + assertInt64Param(pmd, param, Byte.class); + } + + private void assertInt64Param(ParameterMetaData pmd, int param, Class paramClass) + throws SQLException { + assertEquals("INT64", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals(paramClass.getName(), pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertTrue(pmd.isSigned(param)); } private void assertStringParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(String.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertStringParam(pmd, param, String.class); + } + + private void assertStringParam(ParameterMetaData pmd, int param, Class paramClass) + throws SQLException { + assertEquals(Types.NVARCHAR, pmd.getParameterType(param)); + assertEquals("STRING", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals(paramClass.getName(), pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } private void assertNStringParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(String.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertStringParam(pmd, param); } private void assertStringReaderParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.NVARCHAR))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("STRING"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(StringReader.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertStringParam(pmd, param, StringReader.class); } private void assertBytesParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.BINARY))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("BYTES"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(byte[].class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertEquals(Types.BINARY, pmd.getParameterType(param)); + assertEquals("BYTES", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals(byte[].class.getName(), pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } private void assertDateParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.DATE))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("DATE"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Date.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertEquals(Types.DATE, pmd.getParameterType(param)); + assertEquals("DATE", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals(Date.class.getName(), pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } private void assertTimestampParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.TIMESTAMP))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("TIMESTAMP"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat(pmd.getParameterClassName(param), is(equalTo(Timestamp.class.getName()))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertEquals(Types.TIMESTAMP, pmd.getParameterType(param)); + assertEquals("TIMESTAMP", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } private void assertLongArrayParam(ParameterMetaData pmd, int param) throws SQLException { - assertThat(pmd.getParameterType(param), is(equalTo(Types.ARRAY))); - assertThat(pmd.getParameterTypeName(param), is(equalTo("ARRAY"))); - assertThat(pmd.getPrecision(param), is(equalTo(0))); - assertThat(pmd.getScale(param), is(equalTo(0))); - assertThat( - pmd.getParameterClassName(param), is(equalTo("com.google.cloud.spanner.jdbc.JdbcArray"))); - assertThat(pmd.getParameterMode(param), is(equalTo(ParameterMetaData.parameterModeIn))); - assertThat(pmd.isNullable(param), is(equalTo(ParameterMetaData.parameterNullableUnknown))); - assertThat(pmd.isSigned(param), is(false)); + assertEquals(Types.ARRAY, pmd.getParameterType(param)); + assertEquals("ARRAY", pmd.getParameterTypeName(param)); + assertEquals(0, pmd.getPrecision(param)); + assertEquals(0, pmd.getScale(param)); + assertEquals("com.google.cloud.spanner.jdbc.JdbcArray", pmd.getParameterClassName(param)); + assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); + assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); + assertFalse(pmd.isSigned(param)); } } From 34e0a7f4c9930ba379e5364bef3a5e25e2f4b02a Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 2 Mar 2021 21:18:02 -0800 Subject: [PATCH 0333/1979] chore: remove docLava v2 doc generation (#381) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/fd53b9bb-17c4-48a0-a8eb-0e31c2fe8730/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/21da7d9fa02f6916d9f87cf4072b3547b5c72eb5 --- .../.kokoro/release/publish_javadoc.cfg | 8 +------- .../.kokoro/release/publish_javadoc.sh | 19 ------------------- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg index 71efe308f8c9..8e17cf25b0e5 100644 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg @@ -7,12 +7,6 @@ env_vars: { value: "docs-staging" } -# cloud-rad staging -env_vars: { - key: "STAGING_BUCKET_V2" - value: "docs-staging-v2-staging" -} - env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh" @@ -26,4 +20,4 @@ before_action { keyname: "docuploader_service_account" } } -} \ No newline at end of file +} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 024aee4f3976..0773cfe82fe2 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -56,22 +56,3 @@ python3 -m docuploader create-metadata \ python3 -m docuploader upload . \ --credentials ${CREDENTIALS} \ --staging-bucket ${STAGING_BUCKET} - -popd - -# V2 due to problems w/ the released javadoc plugin doclava, Java 8 is required. Beware of accidental updates. - -mvn clean site -B -q -Ddevsite.template="${KOKORO_GFILE_DIR}/java/" - -pushd target/devsite/reference - -# create metadata -python3 -m docuploader create-metadata \ - --name ${NAME} \ - --version ${VERSION} \ - --language java - -# upload docs to staging bucket -python3 -m docuploader upload . \ - --credentials ${CREDENTIALS} \ - --staging-bucket ${STAGING_BUCKET_V2} diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 7b859ad358a5..e6b70f9b7992 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "02164fefc5dd847ebb6d4ca4d4d6e9a8030da2a5" + "sha": "4cbee6dcc2dfea2515437b55b0ecfc956205d739" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "6946fd71ae9215b0e7ae188f5057df765ee6d7d2" + "sha": "21da7d9fa02f6916d9f87cf4072b3547b5c72eb5" } } ], From ebd254bf87bab0957da8c376bdd0e999ce8b00aa Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 4 Mar 2021 15:08:20 -0800 Subject: [PATCH 0334/1979] chore: copy README to docfx-yml dir (#382) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/55f460c4-bcb1-4d76-b766-e2a8c306b9e5/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/d0bdade9a962042dc0f770cf631086f3db59b5b0 --- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 5 ++++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 712821c7e499..164c473614ba 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -40,6 +40,9 @@ export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) # generate yml mvn clean site -B -q -P docFX +# copy README to docfx-yml dir and rename index.md +cp README.md target/docfx-yml/index.md + pushd target/docfx-yml # create metadata @@ -52,4 +55,4 @@ python3 -m docuploader create-metadata \ python3 -m docuploader upload . \ --credentials ${CREDENTIALS} \ --staging-bucket ${STAGING_BUCKET_V2} \ - --destination-prefix docfx- + --destination-prefix docfx diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index e6b70f9b7992..507032d98923 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "4cbee6dcc2dfea2515437b55b0ecfc956205d739" + "sha": "f18abc9361c1f3535c5fdec8eee45dd1fb821334" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "21da7d9fa02f6916d9f87cf4072b3547b5c72eb5" + "sha": "d0bdade9a962042dc0f770cf631086f3db59b5b0" } } ], From 9ced5cae32b306ec3a773c2f19625de1061c6d43 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Mar 2021 12:13:14 +0100 Subject: [PATCH 0335/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v5 (#386) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a59e5de7e790..b90be151df09 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 4.0.2 + 5.0.0 pom import From bd87fc178119c4f8b27476dfb5c55e6a741a4036 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Mar 2021 12:13:44 +0100 Subject: [PATCH 0336/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v19 (#385) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 172882e2a958..fbdf50898859 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 18.0.0 + 19.0.0 pom import From 135f8a2680ffc5b271c96181031b6e4b0c0f2f6a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Mar 2021 12:28:44 +0100 Subject: [PATCH 0337/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.20.1 (#384) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b90be151df09..ba601e91733c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.20.0 + 0.20.1 pom import From 875759bc1c8d2017d1d5a1390d459c2c04298a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 10 Mar 2021 14:12:53 +0100 Subject: [PATCH 0338/1979] feat: add support for CommitStats (#261) * feat: add support for CommitStats * fix: remove overload delay * fix: gracefully close pool after each test * chore: update copyright year, comments and assertions * deps: use Spanner client lib 5.0.0 * fix: add new methods to clirr * test: add tests for SQLException --- .../clirr-ignored-differences.xml | 17 +++ .../jdbc/CloudSpannerJdbcConnection.java | 20 +++ .../cloud/spanner/jdbc/JdbcConnection.java | 31 +++++ .../spanner/jdbc/JdbcCommitStatsTest.java | 123 ++++++++++++++++++ .../spanner/jdbc/JdbcConnectionTest.java | 90 +++++++++++++ 5 files changed, 281 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index 7e243773992e..ac9c147d1978 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -94,4 +94,21 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setTransactionMode(com.google.cloud.spanner.connection.TransactionMode) + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.CommitResponse getCommitResponse() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isReturnCommitStats() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setReturnCommitStats(boolean) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index f13a64f5b64f..4a5f001a8483 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -17,6 +17,8 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.AbortedException; +import com.google.cloud.spanner.CommitResponse; +import com.google.cloud.spanner.CommitStats; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.TimestampBound; @@ -152,6 +154,24 @@ public interface CloudSpannerJdbcConnection extends Connection { */ Timestamp getCommitTimestamp() throws SQLException; + /** + * @return the {@link CommitResponse} of the last read/write transaction. If the last transaction + * was not a read/write transaction, or a read/write transaction that did not return a {@link + * CommitResponse} because the transaction was not committed, the method will throw a {@link + * SQLException}. The {@link CommitResponse} will include {@link CommitStats} if {@link + * #isReturnCommitStats()} returns true. + */ + CommitResponse getCommitResponse() throws SQLException; + + /** + * Sets whether this connection should request commit statistics from Cloud Spanner for read/write + * transactions and for DML statements in autocommit mode. + */ + void setReturnCommitStats(boolean returnCommitStats) throws SQLException; + + /** @return true if this connection requests commit statistics from Cloud Spanner. */ + boolean isReturnCommitStats() throws SQLException; + /** * @return the read {@link Timestamp} of the last read-only transaction. If the last transaction * was not a read-only transaction, or a read-only transaction that did not return a read diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 6c23db4960cb..bf9120f536fd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.api.client.util.Preconditions; +import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.TimestampBound; @@ -381,6 +382,36 @@ public Timestamp getCommitTimestamp() throws SQLException { } } + @Override + public CommitResponse getCommitResponse() throws SQLException { + checkClosed(); + try { + return getSpannerConnection().getCommitResponse(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void setReturnCommitStats(boolean returnCommitStats) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setReturnCommitStats(returnCommitStats); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public boolean isReturnCommitStats() throws SQLException { + checkClosed(); + try { + return getSpannerConnection().isReturnCommitStats(); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + @Override public Timestamp getReadTimestamp() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java new file mode 100644 index 000000000000..0782566ddfeb --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java @@ -0,0 +1,123 @@ +/* + * Copyright 2021 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 com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.CommitResponse; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.SpannerPool; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcCommitStatsTest extends AbstractMockServerTest { + + @After + public void closeSpannerPool() { + SpannerPool.closeSpannerPool(); + } + + @Test + public void testDefaultReturnCommitStats() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RETURN_COMMIT_STATS")) { + assertTrue(rs.next()); + assertFalse(rs.getBoolean("RETURN_COMMIT_STATS")); + assertFalse(rs.next()); + } + } + } + + @Test + public void testReturnCommitStatsInConnectionUrl() throws SQLException { + try (java.sql.Connection connection = + DriverManager.getConnection( + String.format("jdbc:%s;returnCommitStats=true", getBaseUrl()))) { + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RETURN_COMMIT_STATS")) { + assertTrue(rs.next()); + assertTrue(rs.getBoolean("RETURN_COMMIT_STATS")); + assertFalse(rs.next()); + } + } + } + + @Test + public void testSetReturnCommitStats() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.createStatement().execute("SET RETURN_COMMIT_STATS=true"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RETURN_COMMIT_STATS")) { + assertTrue(rs.next()); + assertTrue(rs.getBoolean("RETURN_COMMIT_STATS")); + assertFalse(rs.next()); + } + connection.createStatement().execute("SET RETURN_COMMIT_STATS=false"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RETURN_COMMIT_STATS")) { + assertTrue(rs.next()); + assertFalse(rs.getBoolean("RETURN_COMMIT_STATS")); + assertFalse(rs.next()); + } + } + } + + @Test + public void testSetAndUseReturnCommitStats() throws SQLException { + try (CloudSpannerJdbcConnection connection = + createJdbcConnection().unwrap(CloudSpannerJdbcConnection.class)) { + connection.setReturnCommitStats(true); + connection.bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); + connection.commit(); + CommitResponse response = connection.getCommitResponse(); + assertNotNull(response); + assertNotNull(response.getCommitStats()); + assertThat(response.getCommitStats().getMutationCount()).isAtLeast(1); + } + } + + @Test + public void testSetAndUseReturnCommitStatsUsingSql() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.createStatement().execute("SET RETURN_COMMIT_STATS=true"); + // Use a Mutation as the mock server only returns a non-zero mutation count for mutations, and + // not for DML statements. + connection + .unwrap(CloudSpannerJdbcConnection.class) + .bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); + connection.commit(); + try (ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE COMMIT_RESPONSE")) { + assertTrue(rs.next()); + assertNotNull(rs.getTimestamp("COMMIT_TIMESTAMP")); + assertThat(rs.getLong("MUTATION_COUNT")).isAtLeast(1L); + assertFalse(rs.next()); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 27389b4c02d8..cd0f944989fc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -18,7 +18,11 @@ import static com.google.common.truth.Truth.assertThat; 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.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -51,6 +55,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.Mockito; @RunWith(JUnit4.class) public class JdbcConnectionTest { @@ -277,6 +282,14 @@ public void testClosedJdbcConnection() "releaseSavepoint", new Class[] {Savepoint.class}, new Object[] {null}); + + testClosed(CloudSpannerJdbcConnection.class, "isReturnCommitStats"); + testClosed( + CloudSpannerJdbcConnection.class, + "setReturnCommitStats", + new Class[] {boolean.class}, + new Object[] {true}); + testClosed(CloudSpannerJdbcConnection.class, "getCommitResponse"); } private void testClosed(Class clazz, String name) @@ -705,4 +718,81 @@ public void testSchema() throws SQLException { } } } + + @Test + public void testIsReturnCommitStats() throws SQLException { + try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + assertFalse(connection.isReturnCommitStats()); + connection.setReturnCommitStats(true); + assertTrue(connection.isReturnCommitStats()); + } + } + + @Test + public void testIsReturnCommitStats_throwsSqlException() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + com.google.cloud.spanner.connection.Connection spannerConnection = + mock(com.google.cloud.spanner.connection.Connection.class); + when(options.getConnection()).thenReturn(spannerConnection); + when(spannerConnection.isReturnCommitStats()) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "test exception")); + try (JdbcConnection connection = + new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options)) { + connection.isReturnCommitStats(); + fail("missing expected exception"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.FAILED_PRECONDITION, ((JdbcSqlException) e).getCode()); + } + } + + @Test + public void testSetReturnCommitStats_throwsSqlException() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + com.google.cloud.spanner.connection.Connection spannerConnection = + mock(com.google.cloud.spanner.connection.Connection.class); + when(options.getConnection()).thenReturn(spannerConnection); + Mockito.doThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "test exception")) + .when(spannerConnection) + .setReturnCommitStats(any(boolean.class)); + try (JdbcConnection connection = + new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options)) { + connection.setReturnCommitStats(true); + fail("missing expected exception"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.FAILED_PRECONDITION, ((JdbcSqlException) e).getCode()); + } + } + + @Test + public void testGetCommitResponse_throwsSqlException() throws SQLException { + ConnectionOptions options = mock(ConnectionOptions.class); + com.google.cloud.spanner.connection.Connection spannerConnection = + mock(com.google.cloud.spanner.connection.Connection.class); + when(options.getConnection()).thenReturn(spannerConnection); + Mockito.doThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "test exception")) + .when(spannerConnection) + .setReturnCommitStats(any(boolean.class)); + try (JdbcConnection connection = + new JdbcConnection( + "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", + options)) { + connection.setReturnCommitStats(true); + fail("missing expected exception"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.FAILED_PRECONDITION, ((JdbcSqlException) e).getCode()); + } + } } From 4b92f18e25679bd3162e2d33eabcb35cf5014c2f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 11 Mar 2021 10:42:47 +1100 Subject: [PATCH 0339/1979] chore: release 1.21.0 (#379) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6b9ae0c82140..aed0b022585c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [1.21.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.20.1...v1.21.0) (2021-03-10) + + +### Features + +* add support for CommitStats ([#261](https://www.github.com/googleapis/java-spanner-jdbc/issues/261)) ([b32e7ae](https://www.github.com/googleapis/java-spanner-jdbc/commit/b32e7aebd4c8d24d052e4616b5dd7735878e01c3)) +* allow using UUID in PreparedStatement ([#365](https://www.github.com/googleapis/java-spanner-jdbc/issues/365)) ([4cbee6d](https://www.github.com/googleapis/java-spanner-jdbc/commit/4cbee6dcc2dfea2515437b55b0ecfc956205d739)), closes [#364](https://www.github.com/googleapis/java-spanner-jdbc/issues/364) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.20.1 ([#384](https://www.github.com/googleapis/java-spanner-jdbc/issues/384)) ([f0cdf11](https://www.github.com/googleapis/java-spanner-jdbc/commit/f0cdf117e20325601f1d1c13641267add5b39955)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v5 ([#386](https://www.github.com/googleapis/java-spanner-jdbc/issues/386)) ([910c50c](https://www.github.com/googleapis/java-spanner-jdbc/commit/910c50c611cb30b96a2d5d0472afd2d8e3687013)) + ### [1.20.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.20.0...v1.20.1) (2021-02-26) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ba601e91733c..d787d0a1a79d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.20.2-SNAPSHOT + 1.21.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b9af5cd73394..3aed79761c71 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.2-SNAPSHOT + 1.21.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4ac31ec0922b..d9d8cbb299d0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.20.1:1.20.2-SNAPSHOT +google-cloud-spanner-jdbc:1.21.0:1.21.0 From 2092e26c9d3e3ff440beef452236b29b85f39a96 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 10 Mar 2021 16:10:31 -0800 Subject: [PATCH 0340/1979] build(java): update autorelease title check in response to the new multi release branch changes (#389) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/640f6b0e-336b-449e-9ca8-5f44a6af38d1/targets - [ ] To automatically regenerate this PR, check this box. Source-Link: https://github.com/googleapis/synthtool/commit/0b064d767537e0675fc053e53fca473c5c701fb8 --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 4 ++-- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 7c8816a7d7b1..9b4fd4d8348d 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -16,8 +16,8 @@ jobs: return; } - // only approve PRs like "chore(master): release " - if ( !context.payload.pull_request.title.startsWith("chore(master): release") ) { + // only approve PRs like "chore: release " + if ( !context.payload.pull_request.title.startsWith("chore: release") ) { return; } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 507032d98923..ac98e78ee5c9 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "f18abc9361c1f3535c5fdec8eee45dd1fb821334" + "sha": "b32e7aebd4c8d24d052e4616b5dd7735878e01c3" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "d0bdade9a962042dc0f770cf631086f3db59b5b0" + "sha": "0b064d767537e0675fc053e53fca473c5c701fb8" } } ], From 49e56947391b4f8a0fcb3b7c6cc25caf6a857948 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 10 Mar 2021 16:40:05 -0800 Subject: [PATCH 0341/1979] chore: regenerate README (#391) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-03-11 00:12:52,132 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-03-11 00:12:53,033 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/f41b860a-107b-4d47-94bd-9b15ac08bdd9/targets - [ ] To automatically regenerate this PR, check this box. --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 873d0189ea96..210b7f7532ad 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a7c44b0837caaa42933f252249eac938eeb0ef11" + "sha": "b83537e08c9f453904ddbe0d1b642477a45c16ac" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8c5628b86cfa8386de7b8fc1675e6b528b552d57" + "sha": "ac8f20f12e7a4c0b0ae1c6fa415f684a25ea82b7" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7e3e78a20986..210ee1a1ffac 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.20.1 + 1.21.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.20.1' +compile 'com.google.cloud:google-cloud-spanner-jdbc:1.21.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.20.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.21.0" ``` ## Authentication From 5f8428242e4b66e8aff460a7fafb85ec5a155927 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Mar 2021 21:08:13 +0100 Subject: [PATCH 0342/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v19.1.0 (#394) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `19.0.0` -> `19.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.1.0/compatibility-slim/19.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.1.0/confidence-slim/19.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fbdf50898859..f77728989d1f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 19.0.0 + 19.1.0 pom import From 70a30012c887cbcb58bc17419f4b48f8852536f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 18 Mar 2021 06:31:54 +0100 Subject: [PATCH 0343/1979] perf: use PLAN mode to get result metadata (#388) * perf: use PLAN mode to get result metadata Getting the result metadata of a PreparedStatement should not execute the query, but should instead just request the query plan. This will also return the metadata of the query. * fix: add support for DML * fix: call .next() before getting metadata * fix: skip test on emulator + remove deprecated code --- .../jdbc/AbstractJdbcPreparedStatement.java | 9 ---- .../spanner/jdbc/AbstractJdbcStatement.java | 34 ++++++++++-- .../spanner/jdbc/JdbcPreparedStatement.java | 22 ++++++++ .../jdbc/JdbcPreparedStatementTest.java | 14 ++++- .../jdbc/it/ITJdbcPreparedStatementTest.java | 54 ++++++++++++++++++- 5 files changed, 118 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index bbd5975bd7b8..09409979e5ed 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -29,7 +29,6 @@ import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLXML; @@ -232,14 +231,6 @@ public void setArray(int parameterIndex, Array value) throws SQLException { parameters.setParameter(parameterIndex, value, Types.ARRAY); } - @Override - public ResultSetMetaData getMetaData() throws SQLException { - checkClosed(); - try (ResultSet rs = executeQuery()) { - return rs.getMetaData(); - } - } - @Override public void setDate(int parameterIndex, Date value, Calendar cal) throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 48a002d57b57..5217396f7e28 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -18,6 +18,7 @@ import com.google.cloud.spanner.Options; import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.StatementResult; import com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType; @@ -147,6 +148,20 @@ private void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLE } } + /** + * Executes a SQL statement on the connection of this {@link Statement} as a query using the given + * {@link QueryAnalyzeMode}. + * + * @param statement the SQL statement to executed + * @param analyzeMode the {@link QueryAnalyzeMode} to use + * @return the result of the SQL statement as a {@link ResultSet} + * @throws SQLException if a database error occurs. + */ + ResultSet analyzeQuery(com.google.cloud.spanner.Statement statement, QueryAnalyzeMode analyzeMode) + throws SQLException { + return executeQuery(statement, analyzeMode); + } + /** * Executes a SQL statement on the connection of this {@link Statement} as a query. * @@ -157,11 +172,24 @@ private void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLE */ ResultSet executeQuery(com.google.cloud.spanner.Statement statement, QueryOption... options) throws SQLException { + return executeQuery(statement, null, options); + } + + private ResultSet executeQuery( + com.google.cloud.spanner.Statement statement, + QueryAnalyzeMode analyzeMode, + QueryOption... options) + throws SQLException { StatementTimeout originalTimeout = setTemporaryStatementTimeout(); try { - return JdbcResultSet.of( - this, - connection.getSpannerConnection().executeQuery(statement, getQueryOptions(options))); + 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); } finally { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 7a0e84235505..d8eeb6232eb3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -17,11 +17,17 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.Options.QueryOption; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import com.google.common.collect.ImmutableList; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; /** Implementation of {@link PreparedStatement} for Cloud Spanner. */ @@ -86,4 +92,20 @@ public JdbcParameterMetaData getParameterMetaData() throws SQLException { checkClosed(); return new JdbcParameterMetaData(this); } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + checkClosed(); + if (StatementParser.INSTANCE.isUpdateStatement(sql)) { + // Return metadata for an empty result set as DML statements do not return any results (as a + // result set). + com.google.cloud.spanner.ResultSet resultSet = + ResultSets.forRows(Type.struct(), ImmutableList.of()); + resultSet.next(); + return new JdbcResultSetMetaData(JdbcResultSet.of(resultSet), this); + } + try (ResultSet rs = analyzeQuery(createStatement(), QueryAnalyzeMode.PLAN)) { + return rs.getMetaData(); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 85334b2f74ce..5a1235f5d677 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.Statement; @@ -293,7 +294,7 @@ public void testGetResultSetMetadata() throws SQLException { .set("AMOUNT") .to(Math.PI) .build())); - when(connection.executeQuery(Statement.of(sql))).thenReturn(rs); + when(connection.analyzeQuery(Statement.of(sql), QueryAnalyzeMode.PLAN)).thenReturn(rs); try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(connection), sql)) { ResultSetMetaData metadata = ps.getMetaData(); @@ -306,4 +307,15 @@ public void testGetResultSetMetadata() throws SQLException { assertEquals(Types.DOUBLE, metadata.getColumnType(3)); } } + + @Test + public void testGetResultSetMetaDataForDml() throws SQLException { + Connection connection = mock(Connection.class); + try (JdbcPreparedStatement ps = + new JdbcPreparedStatement( + createMockConnection(connection), "UPDATE FOO SET BAR=1 WHERE TRUE")) { + ResultSetMetaData metadata = ps.getMetaData(); + assertEquals(0, metadata.getColumnCount()); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index b4e02a985a0b..2890ed9ce06d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -23,11 +24,12 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; -import com.google.api.client.util.Base64; import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.common.base.Strings; +import com.google.common.io.BaseEncoding; import java.io.File; import java.io.FileNotFoundException; import java.io.StringReader; @@ -38,6 +40,7 @@ import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; @@ -222,7 +225,7 @@ private static Long[] parseLongArray(String value) { } private static byte[] parseBytes(String value) { - return Base64.decodeBase64(value); + return BaseEncoding.base64().decode(value); } private List createSingers() { @@ -825,6 +828,53 @@ public void test08_InsertAllColumnTypes() throws SQLException { } } + @Test + public void test09_MetaData_FromQuery() throws SQLException { + assumeFalse("The emulator does not support PLAN mode", isUsingEmulator()); + try (Connection con = createConnection()) { + try (PreparedStatement ps = + con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { + ResultSetMetaData metadata = ps.getMetaData(); + assertEquals(22, metadata.getColumnCount()); + int index = 0; + assertEquals("ColInt64", metadata.getColumnLabel(++index)); + assertEquals("ColFloat64", metadata.getColumnLabel(++index)); + assertEquals("ColBool", metadata.getColumnLabel(++index)); + assertEquals("ColString", metadata.getColumnLabel(++index)); + assertEquals("ColStringMax", metadata.getColumnLabel(++index)); + assertEquals("ColBytes", metadata.getColumnLabel(++index)); + assertEquals("ColBytesMax", metadata.getColumnLabel(++index)); + assertEquals("ColDate", metadata.getColumnLabel(++index)); + assertEquals("ColTimestamp", metadata.getColumnLabel(++index)); + assertEquals("ColCommitTS", metadata.getColumnLabel(++index)); + assertEquals("ColNumeric", metadata.getColumnLabel(++index)); + assertEquals("ColInt64Array", metadata.getColumnLabel(++index)); + assertEquals("ColFloat64Array", metadata.getColumnLabel(++index)); + assertEquals("ColBoolArray", metadata.getColumnLabel(++index)); + assertEquals("ColStringArray", metadata.getColumnLabel(++index)); + assertEquals("ColStringMaxArray", metadata.getColumnLabel(++index)); + assertEquals("ColBytesArray", metadata.getColumnLabel(++index)); + assertEquals("ColBytesMaxArray", metadata.getColumnLabel(++index)); + assertEquals("ColDateArray", metadata.getColumnLabel(++index)); + assertEquals("ColTimestampArray", metadata.getColumnLabel(++index)); + assertEquals("ColNumericArray", metadata.getColumnLabel(++index)); + assertEquals("ColComputed", metadata.getColumnLabel(++index)); + } + } + } + + @Test + public void test10_MetaData_FromDML() throws SQLException { + try (Connection con = createConnection()) { + try (PreparedStatement ps = + con.prepareStatement( + "UPDATE TableWithAllColumnTypes SET ColBool=FALSE WHERE ColInt64=?")) { + ResultSetMetaData metadata = ps.getMetaData(); + assertEquals(0, metadata.getColumnCount()); + } + } + } + private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) throws SQLException { assertEquals(expectedParamCount, pmd.getParameterCount()); From da05710b344037b00a80d70d2d1fd90810b7dac6 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Mar 2021 06:32:30 +0100 Subject: [PATCH 0344/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v1.21.0 (#392) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e70c46899909..0edee3488a76 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.20.1 + 1.21.0 From 9cc6100349f8a075eeb7bd60468e3ac94f908f40 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Mar 2021 06:32:52 +0100 Subject: [PATCH 0345/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v5.1.0 (#393) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d787d0a1a79d..3900685a3df9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 5.0.0 + 5.1.0 pom import From f7dd711830a885f1c76f0e9eca75b0bc5b3910f7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Mar 2021 06:33:13 +0100 Subject: [PATCH 0346/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v19.2.0 (#395) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f77728989d1f..6890bf9eb785 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 19.1.0 + 19.2.0 pom import From ea91673008298bd6f2dbe5a6bcdb194ae4ebdc04 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 19 Mar 2021 19:04:30 +0100 Subject: [PATCH 0347/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v19.2.1 (#401) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `19.2.0` -> `19.2.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.2.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.2.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.2.1/compatibility-slim/19.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/19.2.1/confidence-slim/19.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Renovate configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6890bf9eb785..4ae551a6378f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 19.2.0 + 19.2.1 pom import From 5f7c79de95d13d78268c526e537574e36a3cf81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 22 Mar 2021 00:53:02 +0100 Subject: [PATCH 0348/1979] build: remove java7 as required check (#400) --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 6bddd18eac90..a0c0cd493824 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -34,7 +34,6 @@ branchProtectionRules: - "linkage-monitor" - "lint" - "clirr" - - "units (7)" - "units (8)" - "units (11)" - "Kokoro - Test: Integration" From 0b1a98e29bfc80c4fb8dea1eb987faf088f96c1b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 22 Mar 2021 00:53:27 +0100 Subject: [PATCH 0349/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v5.2.0 (#398) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3900685a3df9..e7504f5517a0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 5.1.0 + 5.2.0 pom import From da55e2b8f0642c4dd345762679abca1e0584b86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 22 Mar 2021 01:33:43 +0100 Subject: [PATCH 0350/1979] feat!: upgrade to Java 8 and JDBC 4.2 (#397) * feat!: upgrade to Java 8 and JDBC 4.2 Upgrade to Java 8 and implement new methods added in Java 8 for JDBC. Drops support for Java 7. Closes #396 * fix: remove Java 7 from CI * test: add additional test cases * test: add tests for batches * build: remove java7 configs --- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- java-spanner-jdbc/.kokoro/nightly/java7.cfg | 7 - java-spanner-jdbc/.kokoro/presubmit/java7.cfg | 7 - java-spanner-jdbc/pom.xml | 12 ++ .../jdbc/AbstractJdbcPreparedStatement.java | 16 ++ .../spanner/jdbc/AbstractJdbcResultSet.java | 23 ++ .../spanner/jdbc/AbstractJdbcStatement.java | 41 +++- .../spanner/jdbc/AbstractJdbcWrapper.java | 6 +- .../spanner/jdbc/JdbcDatabaseMetaData.java | 11 + .../google/cloud/spanner/jdbc/JdbcDriver.java | 7 +- .../spanner/jdbc/JdbcParameterStore.java | 11 +- .../spanner/jdbc/JdbcPreparedStatement.java | 5 + .../spanner/jdbc/JdbcSqlExceptionFactory.java | 16 ++ .../cloud/spanner/jdbc/JdbcStatement.java | 96 +++++++-- .../jdbc/AbstractJdbcResultSetTest.java | 33 ++- .../jdbc/JdbcDatabaseMetaDataTest.java | 4 + .../cloud/spanner/jdbc/JdbcDriverTest.java | 7 + .../spanner/jdbc/JdbcParameterStoreTest.java | 18 +- .../jdbc/JdbcPreparedStatementTest.java | 70 ++++--- ...PreparedStatementWithMockedServerTest.java | 197 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcStatementTest.java | 102 ++++++++- 21 files changed, 595 insertions(+), 96 deletions(-) delete mode 100644 java-spanner-jdbc/.kokoro/nightly/java7.cfg delete mode 100644 java-spanner-jdbc/.kokoro/presubmit/java7.cfg create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index def8b3a2c84d..29d933b045e4 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [7, 8, 11] + java: [8, 11] steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 diff --git a/java-spanner-jdbc/.kokoro/nightly/java7.cfg b/java-spanner-jdbc/.kokoro/nightly/java7.cfg deleted file mode 100644 index cb24f44eea3b..000000000000 --- a/java-spanner-jdbc/.kokoro/nightly/java7.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java7" -} diff --git a/java-spanner-jdbc/.kokoro/presubmit/java7.cfg b/java-spanner-jdbc/.kokoro/presubmit/java7.cfg deleted file mode 100644 index cb24f44eea3b..000000000000 --- a/java-spanner-jdbc/.kokoro/presubmit/java7.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java7" -} diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e7504f5517a0..1fcd4358573a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -197,6 +197,18 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + -Xlint:unchecked + -Xlint:deprecation + true + + org.apache.maven.plugins maven-surefire-plugin diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 09409979e5ed..0507d5d5d604 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -31,6 +31,7 @@ import java.sql.ResultSet; import java.sql.RowId; import java.sql.SQLException; +import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; @@ -321,6 +322,21 @@ public void setObject(int parameterIndex, Object value, int targetSqlType, int s parameters.setParameter(parameterIndex, value, targetSqlType, scaleOrLength); } + @Override + public void setObject(int parameterIndex, Object value, SQLType targetSqlType) + throws SQLException { + checkClosed(); + parameters.setParameter(parameterIndex, value, targetSqlType.getVendorTypeNumber()); + } + + @Override + public void setObject(int parameterIndex, Object value, SQLType targetSqlType, int scaleOrLength) + throws SQLException { + checkClosed(); + parameters.setParameter( + parameterIndex, value, targetSqlType.getVendorTypeNumber(), scaleOrLength); + } + @Override public void setAsciiStream(int parameterIndex, InputStream value, long length) throws SQLException { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java index 6016bd2c3033..74d5ccde3c30 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java @@ -29,6 +29,7 @@ import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLType; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Time; @@ -233,11 +234,22 @@ public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQ throw new SQLFeatureNotSupportedException(); } + @Override + public void updateObject(int columnIndex, Object x, SQLType type, int scaleOrLength) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + @Override public void updateObject(int columnIndex, Object x) throws SQLException { throw new SQLFeatureNotSupportedException(); } + @Override + public void updateObject(int columnIndex, Object x, SQLType type) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + @Override public void updateNull(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException(); @@ -335,6 +347,17 @@ public void updateObject(String columnLabel, Object x) throws SQLException { throw new SQLFeatureNotSupportedException(); } + @Override + public void updateObject(String columnLabel, Object x, SQLType type) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public void updateObject(String columnLabel, Object x, SQLType type, int scaleOrLength) + throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + @Override public void insertRow() throws SQLException { throw new SQLFeatureNotSupportedException(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 5217396f7e28..9863f47c0855 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -201,20 +201,32 @@ 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. + * @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}. + * 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 { - long count = connection.getSpannerConnection().executeUpdate(statement); - if (count > Integer.MAX_VALUE) { - throw JdbcSqlExceptionFactory.of( - "update count too large for executeUpdate: " + count, Code.OUT_OF_RANGE); - } - return (int) count; + return connection.getSpannerConnection().executeUpdate(statement); } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); } finally { @@ -357,11 +369,22 @@ public int getMaxRows() throws SQLException { return 0; } + @Override + public long getLargeMaxRows() throws SQLException { + checkClosed(); + return 0L; + } + @Override public void setMaxRows(int max) throws SQLException { checkClosed(); } + @Override + public void setLargeMaxRows(long max) throws SQLException { + checkClosed(); + } + @Override public void setEscapeProcessing(boolean enable) throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 655566870d1a..9f9752452e43 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -66,7 +66,8 @@ static String getSpannerTypeName(int sqlType) { if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL) return Type.numeric().getCode().name(); if (sqlType == Types.NVARCHAR) return Type.string().getCode().name(); - if (sqlType == Types.TIMESTAMP) return Type.timestamp().getCode().name(); + if (sqlType == Types.TIMESTAMP || sqlType == Types.TIMESTAMP_WITH_TIMEZONE) + return Type.timestamp().getCode().name(); if (sqlType == Types.ARRAY) return Code.ARRAY.name(); return OTHER_NAME; @@ -84,7 +85,8 @@ static String getClassName(int sqlType) { || sqlType == Types.TINYINT) return Long.class.getName(); if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL) return BigDecimal.class.getName(); if (sqlType == Types.NVARCHAR) return String.class.getName(); - if (sqlType == Types.TIMESTAMP) return Timestamp.class.getName(); + if (sqlType == Types.TIMESTAMP || sqlType == Types.TIMESTAMP_WITH_TIMEZONE) + return Timestamp.class.getName(); if (sqlType == Types.ARRAY) return Object.class.getName(); return null; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index a5d79b14e9bf..191d991ea5f9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -1630,4 +1630,15 @@ public ResultSet getPseudoColumns( public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } + + @Override + public long getMaxLogicalLobSize() throws SQLException { + // BYTES(MAX) + return 10485760L; + } + + @Override + public boolean supportsRefCursors() throws SQLException { + return false; + } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 3f4a433526bc..dbb2df5ca6bd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -106,7 +106,8 @@ */ public class JdbcDriver implements Driver { private static final String JDBC_API_CLIENT_LIB_TOKEN = "sp-jdbc"; - static final int MAJOR_VERSION = 1; + // Updated to version 2 when upgraded to Java 8 (JDBC 4.2) + static final int MAJOR_VERSION = 2; static final int MINOR_VERSION = 0; private static final String JDBC_URL_FORMAT = "jdbc:" + ConnectionOptions.Builder.SPANNER_URI_FORMAT; @@ -245,12 +246,12 @@ private String parseUriProperty(String uri, String property, String defaultValue @Override public int getMajorVersion() { - return 1; + return MAJOR_VERSION; } @Override public int getMinorVersion() { - return 0; + return MINOR_VERSION; } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 10de0f839c33..2c529c4e7d9a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -204,7 +204,9 @@ private boolean isTypeSupported(int sqlType) { case Types.LONGNVARCHAR: case Types.DATE: case Types.TIME: + case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: @@ -249,7 +251,9 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { || value instanceof URL; case Types.DATE: case Types.TIME: + case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: return value instanceof Date || value instanceof Time || value instanceof Timestamp; case Types.BINARY: case Types.VARBINARY: @@ -522,7 +526,9 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } throw JdbcSqlExceptionFactory.of(value + " is not a valid date", Code.INVALID_ARGUMENT); case Types.TIME: + case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: if (value instanceof Date) { return binder.to(JdbcTypeConverter.toGoogleTimestamp((Date) value)); } else if (value instanceof Time) { @@ -715,7 +721,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.DATE: return binder.toDateArray((Iterable) null); case Types.TIME: + case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: return binder.toTimestampArray((Iterable) null); case Types.BINARY: case Types.VARBINARY: @@ -843,8 +851,9 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) throw case Types.SQLXML: return binder.to((String) null); case Types.TIME: - return binder.to((com.google.cloud.Timestamp) null); + case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: return binder.to((com.google.cloud.Timestamp) null); case Types.TINYINT: return binder.to((Long) null); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index d8eeb6232eb3..b0032e44e15b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -74,6 +74,11 @@ public int executeUpdate() throws SQLException { return executeUpdate(createStatement()); } + public long executeLargeUpdate() throws SQLException { + checkClosed(); + return executeLargeUpdate(createStatement()); + } + @Override public boolean execute() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java index b7d1130d24cd..33d3bb4223a8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java @@ -127,6 +127,16 @@ private JdbcSqlBatchUpdateException(int[] updateCounts, SpannerBatchUpdateExcept this.code = Code.forNumber(cause.getCode()); } + private JdbcSqlBatchUpdateException(long[] updateCounts, SpannerBatchUpdateException cause) { + super( + cause.getMessage(), + cause.getErrorCode().toString(), + cause.getCode(), + updateCounts, + cause); + this.code = Code.forNumber(cause.getCode()); + } + @Override public Code getCode() { return code; @@ -315,4 +325,10 @@ static BatchUpdateException batchException( int[] updateCounts, SpannerBatchUpdateException cause) { return new JdbcSqlBatchUpdateException(updateCounts, cause); } + + /** Creates a {@link JdbcSqlException} for large batch update exceptions. */ + static BatchUpdateException batchException( + long[] updateCounts, SpannerBatchUpdateException cause) { + return new JdbcSqlBatchUpdateException(updateCounts, cause); + } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index b4eaa0d17a45..5a8f69166104 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -68,6 +68,21 @@ public ResultSet executeQuery(String sql) throws SQLException { */ @Override public int executeUpdate(String sql) throws SQLException { + long result = executeLargeUpdate(sql); + if (result > Integer.MAX_VALUE) { + throw JdbcSqlExceptionFactory.of("update count too large: " + result, Code.OUT_OF_RANGE); + } + return (int) result; + } + + /** + * @see java.sql.Statement#executeLargeUpdate(String) + *

    This method allows both DML and DDL statements to be executed. It assumes that the user + * knows what kind of statement is being executed, and the method will therefore return 0 for + * both DML statements that changed 0 rows as well as for all DDL statements. + */ + @Override + public long executeLargeUpdate(String sql) throws SQLException { checkClosed(); Statement statement = Statement.of(sql); StatementResult result = execute(statement); @@ -76,13 +91,9 @@ public int executeUpdate(String sql) throws SQLException { throw JdbcSqlExceptionFactory.of( "The statement is not an update or DDL statement", Code.INVALID_ARGUMENT); case UPDATE_COUNT: - if (result.getUpdateCount() > Integer.MAX_VALUE) { - throw JdbcSqlExceptionFactory.of( - "update count too large: " + result.getUpdateCount(), Code.OUT_OF_RANGE); - } - return result.getUpdateCount().intValue(); + return result.getUpdateCount(); case NO_RESULT: - return 0; + return 0L; default: throw JdbcSqlExceptionFactory.of( "unknown result: " + result.getResultType(), Code.FAILED_PRECONDITION); @@ -138,6 +149,18 @@ public int getUpdateCount() throws SQLException { return (int) currentUpdateCount; } + /** + * Returns the update count of the last update statement as a {@link Long}. Will return {@link + * JdbcConstants#STATEMENT_RESULT_SET} if the last statement returned a {@link ResultSet} and will + * return {@link JdbcConstants#STATEMENT_NO_RESULT} if the last statement did not have any return + * value, such as for example DDL statements. + */ + @Override + public long getLargeUpdateCount() throws SQLException { + checkClosed(); + return currentUpdateCount; + } + @Override public boolean getMoreResults() throws SQLException { checkClosed(); @@ -234,19 +257,28 @@ public void clearBatch() throws SQLException { @Override public int[] executeBatch() throws SQLException { + return convertUpdateCounts(executeBatch(false)); + } + + public long[] executeLargeBatch() throws SQLException { + return executeBatch(true); + } + + private long[] executeBatch(boolean large) throws SQLException { checkClosed(); checkConnectionHasNoActiveBatch(); try { switch (this.currentBatchType) { case DML: try { - long[] updateCounts = - getConnection().getSpannerConnection().executeBatchUpdate(batchedStatements); - int[] res = convertUpdateCounts(updateCounts); - return res; + return getConnection().getSpannerConnection().executeBatchUpdate(batchedStatements); } catch (SpannerBatchUpdateException e) { - int[] updateCounts = convertUpdateCounts(e.getUpdateCounts()); - throw JdbcSqlExceptionFactory.batchException(updateCounts, e); + if (large) { + throw JdbcSqlExceptionFactory.batchException(e.getUpdateCounts(), e); + } else { + throw JdbcSqlExceptionFactory.batchException( + convertUpdateCounts(e.getUpdateCounts()), e); + } } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); } @@ -257,20 +289,24 @@ public int[] executeBatch() throws SQLException { execute(statement); } getConnection().getSpannerConnection().runBatch(); - int[] res = new int[batchedStatements.size()]; + long[] res = new long[batchedStatements.size()]; Arrays.fill(res, java.sql.Statement.SUCCESS_NO_INFO); return res; } catch (SpannerBatchUpdateException e) { - int[] res = new int[batchedStatements.size()]; + long[] res = new long[batchedStatements.size()]; Arrays.fill(res, java.sql.Statement.EXECUTE_FAILED); convertUpdateCountsToSuccessNoInfo(e.getUpdateCounts(), res); - throw JdbcSqlExceptionFactory.batchException(res, e); + if (large) { + throw JdbcSqlExceptionFactory.batchException(res, e); + } else { + throw JdbcSqlExceptionFactory.batchException(convertUpdateCounts(res), e); + } } catch (SpannerException e) { throw JdbcSqlExceptionFactory.of(e); } case NONE: // There is no batch on this statement, this is a no-op. - return new int[0]; + return new long[0]; default: throw JdbcSqlExceptionFactory.unsupported( String.format("Unknown batch type: %s", this.currentBatchType.name())); @@ -296,16 +332,11 @@ int[] convertUpdateCounts(long[] updateCounts) throws SQLException { } @VisibleForTesting - void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, int[] res) throws SQLException { + void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, long[] res) throws SQLException { Preconditions.checkNotNull(updateCounts); Preconditions.checkNotNull(res); Preconditions.checkArgument(res.length >= 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); - } if (updateCounts[index] > 0L) { res[index] = java.sql.Statement.SUCCESS_NO_INFO; } else { @@ -349,6 +380,27 @@ public int executeUpdate(String sql, String[] columnNames) throws SQLException { return executeUpdate(sql); } + @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); + } + + @Override + public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { + checkClosed(); + return executeLargeUpdate(sql); + } + + @Override + public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { + checkClosed(); + return executeLargeUpdate(sql); + } + @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java index 960287ceea6b..2be79bf20cbb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java @@ -40,6 +40,7 @@ import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLType; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; @@ -508,14 +509,28 @@ public void run() throws SQLException { new SqlRunnable() { @Override public void run() throws SQLException { - rs.updateObject("test", new Object()); + rs.updateObject(1, new Object(), 1); } }); assertUnsupported( new SqlRunnable() { @Override public void run() throws SQLException { - rs.updateObject(1, new Object(), 1); + rs.updateObject(1, new Object(), mock(SQLType.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject(1, new Object(), mock(SQLType.class), 0); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject("test", new Object()); } }); assertUnsupported( @@ -525,6 +540,20 @@ public void run() throws SQLException { rs.updateObject("test", new Object(), 1); } }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject("test", new Object(), mock(SQLType.class)); + } + }); + assertUnsupported( + new SqlRunnable() { + @Override + public void run() throws SQLException { + rs.updateObject("test", new Object(), mock(SQLType.class), 1); + } + }); assertUnsupported( new SqlRunnable() { @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index ac8ab7bf6371..e7e634a2eb0c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -20,6 +20,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -267,6 +269,8 @@ public void testTrivialMethods() throws SQLException { }) { assertThat(meta.supportsTransactionIsolationLevel(level), is(false)); } + assertEquals(10485760L, meta.getMaxLogicalLobSize()); + assertFalse(meta.supportsRefCursors()); // trivial tests that guarantee that the function works, but the return value doesn't matter assertThat(meta.getNumericFunctions(), is(notNullValue())); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 014d9bde0ae5..c6709b348d89 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import com.google.cloud.spanner.MockSpannerServiceImpl; @@ -82,6 +83,12 @@ public void testClientLibToken() { assertThat(JdbcDriver.getClientLibToken()).isEqualTo("sp-jdbc"); } + @Test + public void testVersion() throws SQLException { + assertEquals(JdbcDriver.MAJOR_VERSION, JdbcDriver.getRegisteredDriver().getMajorVersion()); + assertEquals(JdbcDriver.MINOR_VERSION, JdbcDriver.getRegisteredDriver().getMinorVersion()); + } + @Test public void testRegister() throws SQLException { assertThat(JdbcDriver.isRegistered()).isTrue(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 502ef5457d2c..7f686013889e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -84,10 +84,18 @@ public void testSetParameterWithType() throws SQLException, IOException { verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); params.setParameter(1, new Time(0L), Types.TIME); assertEquals(new Time(0L), params.getParameter(1)); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Time(0L), Types.TIME_WITH_TIMEZONE); + assertEquals(new Time(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new Timestamp(0L), Types.TIMESTAMP); assertEquals(new Timestamp(0L), params.getParameter(1)); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + params.setParameter(1, new Timestamp(0L), Types.TIMESTAMP_WITH_TIMEZONE); + assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); params.setParameter(1, new byte[] {1, 2, 3}, Types.BINARY); @@ -184,7 +192,10 @@ public void testSetParameterWithType() throws SQLException, IOException { } // types that should lead to timestamp - for (int type : new int[] {Types.TIME, Types.TIMESTAMP}) { + for (int type : + new int[] { + Types.TIME, Types.TIME_WITH_TIMEZONE, Types.TIMESTAMP, Types.TIMESTAMP_WITH_TIMEZONE + }) { params.setParameter(1, new Date(0L), type); assertEquals(new Date(0L), params.getParameter(1)); verifyParameter( @@ -321,7 +332,10 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { } // types that should lead to timestamp - for (int type : new int[] {Types.TIME, Types.TIMESTAMP}) { + for (int type : + new int[] { + Types.TIME, Types.TIME_WITH_TIMEZONE, Types.TIMESTAMP, Types.TIMESTAMP_WITH_TIMEZONE + }) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 5a1235f5d677..b19aa54c12a8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -39,6 +39,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.sql.Date; +import java.sql.JDBCType; import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSetMetaData; @@ -101,7 +102,7 @@ private JdbcConnection createMockConnection(Connection spanner) throws SQLExcept @SuppressWarnings("deprecation") @Test public void testParameters() throws SQLException, MalformedURLException { - final int numberOfParams = 48; + final int numberOfParams = 51; String sql = generateSqlWithParameters(numberOfParams); JdbcConnection connection = createMockConnection(); @@ -151,6 +152,8 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setUnicodeStream(47, new ByteArrayInputStream("TEST".getBytes()), 4); ps.setURL(48, new URL("https://spanner.google.com")); ps.setObject(49, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e")); + ps.setObject(50, "TEST", JDBCType.NVARCHAR); + ps.setObject(51, "TEST", JDBCType.NVARCHAR, 20); testSetUnsupportedTypes(ps); @@ -204,6 +207,8 @@ public void testParameters() throws SQLException, MalformedURLException { assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(47)); assertEquals(URL.class.getName(), pmd.getParameterClassName(48)); assertEquals(UUID.class.getName(), pmd.getParameterClassName(49)); + assertEquals(String.class.getName(), pmd.getParameterClassName(50)); + assertEquals(String.class.getName(), pmd.getParameterClassName(51)); ps.clearParameters(); pmd = ps.getParameterMetaData(); @@ -237,41 +242,46 @@ private void testSetUnsupportedTypes(PreparedStatement ps) { @Test public void testSetNullValues() throws SQLException { - String sql = generateSqlWithParameters(27); + final int numberOfParameters = 27; + String sql = generateSqlWithParameters(numberOfParameters); try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(), sql)) { - ps.setNull(1, Types.BLOB); - ps.setNull(2, Types.NVARCHAR); - ps.setNull(4, Types.BINARY); - ps.setNull(5, Types.BOOLEAN); - ps.setNull(6, Types.TINYINT); - ps.setNull(7, Types.DATE); - ps.setNull(8, Types.DOUBLE); - ps.setNull(9, Types.FLOAT); - ps.setNull(10, Types.INTEGER); - ps.setNull(11, Types.BIGINT); - ps.setNull(12, Types.SMALLINT); - ps.setNull(13, Types.TIME); - ps.setNull(14, Types.TIMESTAMP); - ps.setNull(15, Types.CHAR); - ps.setNull(16, Types.CLOB); - ps.setNull(17, Types.LONGNVARCHAR); - ps.setNull(18, Types.LONGVARBINARY); - ps.setNull(19, Types.LONGVARCHAR); - ps.setNull(20, Types.NCHAR); - ps.setNull(21, Types.NCLOB); - ps.setNull(23, Types.NVARCHAR); - ps.setNull(24, Types.REAL); - ps.setNull(25, Types.BIT); - ps.setNull(26, Types.VARBINARY); - ps.setNull(27, Types.VARCHAR); + int index = 0; + ps.setNull(++index, Types.BLOB); + ps.setNull(++index, Types.NVARCHAR); + ps.setNull(++index, Types.BINARY); + ps.setNull(++index, Types.BOOLEAN); + ps.setNull(++index, Types.TINYINT); + ps.setNull(++index, Types.DATE); + ps.setNull(++index, Types.DOUBLE); + ps.setNull(++index, Types.FLOAT); + ps.setNull(++index, Types.INTEGER); + ps.setNull(++index, Types.BIGINT); + ps.setNull(++index, Types.SMALLINT); + ps.setNull(++index, Types.TIME); + ps.setNull(++index, Types.TIME_WITH_TIMEZONE); + ps.setNull(++index, Types.TIMESTAMP); + ps.setNull(++index, Types.TIMESTAMP_WITH_TIMEZONE); + ps.setNull(++index, Types.CHAR); + ps.setNull(++index, Types.CLOB); + ps.setNull(++index, Types.LONGNVARCHAR); + ps.setNull(++index, Types.LONGVARBINARY); + ps.setNull(++index, Types.LONGVARCHAR); + ps.setNull(++index, Types.NCHAR); + ps.setNull(++index, Types.NCLOB); + ps.setNull(++index, Types.NVARCHAR); + ps.setNull(++index, Types.REAL); + ps.setNull(++index, Types.BIT); + ps.setNull(++index, Types.VARBINARY); + ps.setNull(++index, Types.VARCHAR); + assertEquals(numberOfParameters, index); JdbcParameterMetaData pmd = ps.getParameterMetaData(); - assertEquals(27, pmd.getParameterCount()); - assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(14)); + assertEquals(numberOfParameters, pmd.getParameterCount()); + assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(15)); ps.clearParameters(); pmd = ps.getParameterMetaData(); - assertEquals(27, pmd.getParameterCount()); + assertEquals(numberOfParameters, pmd.getParameterCount()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java new file mode 100644 index 000000000000..3f36f0001420 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java @@ -0,0 +1,197 @@ +/* + * Copyright 2021 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 com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlBatchUpdateException; +import io.grpc.Server; +import io.grpc.Status; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collection; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +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 JdbcPreparedStatementWithMockedServerTest { + private static MockSpannerServiceImpl mockSpanner; + private static Server server; + private static InetSocketAddress address; + + @Parameter public boolean executeLarge; + + @Parameters(name = "executeLarge = {0}") + public static Collection data() { + return Arrays.asList(new Object[][] {{false}, {true}}); + } + + @BeforeClass + public static void startStaticServer() throws IOException { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void stopServer() throws Exception { + server.shutdown(); + server.awaitTermination(); + } + + @After + public void reset() { + SpannerPool.closeSpannerPool(); + mockSpanner.removeAllExecutionTimes(); + mockSpanner.reset(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + server.getPort(), "proj", "inst", "db"); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testExecuteBatch() throws SQLException { + Statement.Builder insertBuilder = + Statement.newBuilder("INSERT INTO Test (Col1, Col2) VALUES (@p1, @p2)"); + mockSpanner.putStatementResult( + StatementResult.update( + insertBuilder.bind("p1").to(1L).bind("p2").to("test 1").build(), 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + insertBuilder.bind("p1").to(2L).bind("p2").to("test 2").build(), 1L)); + try (Connection connection = createConnection()) { + try (PreparedStatement statement = + connection.prepareStatement("INSERT INTO Test (Col1, Col2) VALUES (?, ?)")) { + statement.setLong(1, 1L); + statement.setString(2, "test 1"); + statement.addBatch(); + statement.setLong(1, 2L); + statement.setString(2, "test 2"); + statement.addBatch(); + if (executeLarge) { + assertThat(statement.executeLargeBatch()).asList().containsExactly(1L, 1L); + } else { + assertThat(statement.executeBatch()).asList().containsExactly(1, 1); + } + } + } + } + + @Test + public void testExecuteBatch_withOverflow() throws SQLException { + Statement.Builder insertBuilder = + Statement.newBuilder("INSERT INTO Test (Col1, Col2) VALUES (@p1, @p2)"); + mockSpanner.putStatementResult( + StatementResult.update( + insertBuilder.bind("p1").to(1L).bind("p2").to("test 1").build(), 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + insertBuilder.bind("p1").to(2L).bind("p2").to("test 2").build(), + Integer.MAX_VALUE + 1L)); + try (Connection connection = createConnection()) { + try (PreparedStatement statement = + connection.prepareStatement("INSERT INTO Test (Col1, Col2) VALUES (?, ?)")) { + statement.setLong(1, 1L); + statement.setString(2, "test 1"); + statement.addBatch(); + statement.setLong(1, 2L); + statement.setString(2, "test 2"); + statement.addBatch(); + if (executeLarge) { + assertThat(statement.executeLargeBatch()) + .asList() + .containsExactly(1L, Integer.MAX_VALUE + 1L); + } else { + try { + statement.executeBatch(); + fail("missing expected OutOfRange exception"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + JdbcSqlException sqlException = (JdbcSqlException) e; + assertEquals( + ErrorCode.OUT_OF_RANGE.getGrpcStatusCode().value(), sqlException.getErrorCode()); + } + } + } + } + } + + @Test + public void testExecuteBatch_withException() throws SQLException { + Statement.Builder insertBuilder = + Statement.newBuilder("INSERT INTO Test (Col1, Col2) VALUES (@p1, @p2)"); + mockSpanner.putStatementResult( + StatementResult.update( + insertBuilder.bind("p1").to(1L).bind("p2").to("test 1").build(), 1L)); + mockSpanner.putStatementResult( + StatementResult.exception( + insertBuilder.bind("p1").to(2L).bind("p2").to("test 2").build(), + Status.ALREADY_EXISTS.asRuntimeException())); + try (Connection connection = createConnection()) { + try (PreparedStatement statement = + connection.prepareStatement("INSERT INTO Test (Col1, Col2) VALUES (?, ?)")) { + statement.setLong(1, 1L); + statement.setString(2, "test 1"); + statement.addBatch(); + statement.setLong(1, 2L); + statement.setString(2, "test 2"); + statement.addBatch(); + try { + if (executeLarge) { + statement.executeLargeBatch(); + } else { + statement.executeBatch(); + } + } catch (JdbcSqlBatchUpdateException e) { + if (executeLarge) { + assertThat(e.getLargeUpdateCounts()).asList().containsExactly(1L); + } else { + assertThat(e.getUpdateCounts()).asList().containsExactly(1); + } + } + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 7349bfce72de..ee21dda54f15 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -187,14 +187,15 @@ public void testExecuteWithUpdateStatement() throws SQLException { assertThat(res).isFalse(); assertThat(statement.getResultSet()).isNull(); assertThat(statement.getUpdateCount()).isEqualTo(1); + assertThat(statement.execute(LARGE_UPDATE)).isFalse(); + assertThat(statement.getResultSet()).isNull(); try { - assertThat(statement.execute(LARGE_UPDATE)).isFalse(); - assertThat(statement.getResultSet()).isNull(); statement.getUpdateCount(); fail("missing expected exception"); } catch (JdbcSqlExceptionImpl e) { assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE); } + assertThat(statement.getLargeUpdateCount()).isEqualTo(Integer.MAX_VALUE + 1L); } @Test @@ -270,6 +271,65 @@ public void testExecuteUpdate() throws SQLException { } } + @Test + public void testInternalExecuteUpdate() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + Connection spannerConnection = mock(Connection.class); + when(connection.getSpannerConnection()).thenReturn(spannerConnection); + com.google.cloud.spanner.Statement updateStatement = + 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); + try (JdbcStatement statement = new JdbcStatement(connection)) { + assertThat(statement.executeUpdate(updateStatement)).isEqualTo(1); + try { + statement.executeUpdate(largeUpdateStatement); + fail("missing expected exception"); + } catch (JdbcSqlExceptionImpl e) { + assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE); + } + } + } + + @Test + public void testInternalExecuteLargeUpdate() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + Connection spannerConnection = mock(Connection.class); + when(connection.getSpannerConnection()).thenReturn(spannerConnection); + com.google.cloud.spanner.Statement updateStatement = + 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); + try (JdbcStatement statement = new JdbcStatement(connection)) { + assertThat(statement.executeLargeUpdate(updateStatement)).isEqualTo(1); + assertThat(statement.executeLargeUpdate(largeUpdateStatement)) + .isEqualTo(Integer.MAX_VALUE + 1L); + } + } + + @Test + public void testExecuteLargeUpdate() throws SQLException { + Statement statement = createStatement(); + assertThat(statement.executeLargeUpdate(UPDATE)).isEqualTo(1L); + assertThat(statement.executeLargeUpdate(LARGE_UPDATE)).isEqualTo(Integer.MAX_VALUE + 1L); + + assertThat(statement.executeLargeUpdate(UPDATE, Statement.NO_GENERATED_KEYS)).isEqualTo(1L); + assertThat(statement.executeLargeUpdate(LARGE_UPDATE, Statement.NO_GENERATED_KEYS)) + .isEqualTo(Integer.MAX_VALUE + 1L); + + assertThat(statement.executeLargeUpdate(UPDATE, new int[0])).isEqualTo(1L); + assertThat(statement.executeLargeUpdate(LARGE_UPDATE, new int[0])) + .isEqualTo(Integer.MAX_VALUE + 1L); + + assertThat(statement.executeLargeUpdate(UPDATE, new String[0])).isEqualTo(1L); + assertThat(statement.executeLargeUpdate(LARGE_UPDATE, new String[0])) + .isEqualTo(Integer.MAX_VALUE + 1L); + } + @Test public void testExecuteUpdateWithSelectStatement() throws SQLException { Statement statement = createStatement(); @@ -364,6 +424,19 @@ public void testDmlBatch() throws SQLException { } } + @Test + public void testLargeDmlBatch() throws SQLException { + try (Statement statement = createStatement()) { + // Verify that multiple batches can be executed on the same statement. + for (int i = 0; i < 2; i++) { + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'TEST')"); + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (2, 'TEST')"); + statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (3, 'TEST')"); + assertThat(statement.executeLargeBatch()).asList().containsExactly(1L, 1L, 1L); + } + } + } + @Test public void testConvertUpdateCounts() throws SQLException { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { @@ -382,30 +455,39 @@ public void testConvertUpdateCounts() throws SQLException { @Test public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { - int[] updateCounts = new int[3]; + long[] updateCounts = new long[3]; statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 2L, 3L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO, Statement.SUCCESS_NO_INFO); + Long.valueOf(Statement.SUCCESS_NO_INFO), + Long.valueOf(Statement.SUCCESS_NO_INFO), + Long.valueOf(Statement.SUCCESS_NO_INFO)); statement.convertUpdateCountsToSuccessNoInfo(new long[] {0L, 0L, 0L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED, Statement.EXECUTE_FAILED); + Long.valueOf(Statement.EXECUTE_FAILED), + Long.valueOf(Statement.EXECUTE_FAILED), + Long.valueOf(Statement.EXECUTE_FAILED)); statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 0L, 2L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Statement.SUCCESS_NO_INFO, Statement.EXECUTE_FAILED, Statement.SUCCESS_NO_INFO); + Long.valueOf(Statement.SUCCESS_NO_INFO), + Long.valueOf(Statement.EXECUTE_FAILED), + Long.valueOf(Statement.SUCCESS_NO_INFO)); statement.convertUpdateCountsToSuccessNoInfo( - new long[] {1L, Integer.MAX_VALUE + 1L}, updateCounts); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE).matches(e)).isTrue(); + new long[] {1L, Integer.MAX_VALUE + 1L, 2L}, updateCounts); + assertThat(updateCounts) + .asList() + .containsExactly( + Long.valueOf(Statement.SUCCESS_NO_INFO), + Long.valueOf(Statement.SUCCESS_NO_INFO), + Long.valueOf(Statement.SUCCESS_NO_INFO)); } } } From cfc6aa8b6379cd2d0afedc8a215a4416d6085681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 24 Mar 2021 05:55:50 +0100 Subject: [PATCH 0351/1979] docs: add reference to jar-with-dependencies in readme (#404) Towards #399 --- java-spanner-jdbc/.readme-partials.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml index c407ffc2c4b2..3407400d2e12 100644 --- a/java-spanner-jdbc/.readme-partials.yaml +++ b/java-spanner-jdbc/.readme-partials.yaml @@ -24,6 +24,10 @@ custom_content: | } ``` + ### Jar with Dependencies + A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest + or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). + ### Creating a Shaded Jar A jar with all dependencies included is automatically generated when you execute `mvn package`. From b3e068b536201b8f6053e14297623b058707b35a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 24 Mar 2021 05:56:20 +0100 Subject: [PATCH 0352/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6 (#403) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1fcd4358573a..8c2eb74f2cea 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 5.2.0 + 6.0.0 pom import From 3781c5cde970f25d9d6b9b4a563eba702e6955ad Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 23 Mar 2021 22:14:02 -0700 Subject: [PATCH 0353/1979] chore: regenerate README (#405) This PR was generated using Autosynth. :rainbow:

    Log from Synthtool ``` 2021-03-24 04:58:13,532 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-03-24 04:58:14,418 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/ef8c06cb-a758-45ba-ae33-be84ee3c8c9d/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 210b7f7532ad..1c35e44741e3 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "b83537e08c9f453904ddbe0d1b642477a45c16ac" + "sha": "3e0fbd1706fc269cd7bfcd2258181487cc40cece" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ac8f20f12e7a4c0b0ae1c6fa415f684a25ea82b7" + "sha": "86ed43d4f56e6404d068e62e497029018879c771" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 210ee1a1ffac..bd9013fdcc7e 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -84,6 +84,10 @@ try (Connection connection = } ``` +### Jar with Dependencies +A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest +or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). + ### Creating a Shaded Jar A jar with all dependencies included is automatically generated when you execute `mvn package`. From f1fb03f05ade2819bd949136666715a04476741e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 24 Mar 2021 16:31:11 +1100 Subject: [PATCH 0354/1979] chore: release 1.21.1-SNAPSHOT (#406) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8c2eb74f2cea..15b4830f84f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.21.0 + 1.21.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3aed79761c71..55fbbbe7a8f9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.21.0 + 1.21.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d9d8cbb299d0..c6a4bb9ac886 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.21.0:1.21.0 +google-cloud-spanner-jdbc:1.21.0:1.21.1-SNAPSHOT From 9b3d33179becc3b4c1bb22e3811578024ad339ea Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 24 Mar 2021 17:30:23 +1100 Subject: [PATCH 0355/1979] chore: release 2.0.0 (#407) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 28 ++++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index aed0b022585c..c935f736df4a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [2.0.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.21.0...v2.0.0) (2021-03-24) + + +### ⚠ BREAKING CHANGES + +* upgrade to Java 8 and JDBC 4.2 (#397) + +### Features + +* upgrade to Java 8 and JDBC 4.2 ([#397](https://www.github.com/googleapis/java-spanner-jdbc/issues/397)) ([7eedfbc](https://www.github.com/googleapis/java-spanner-jdbc/commit/7eedfbc78dad15e598d4b678027094ce1467e7f1)) + + +### Performance Improvements + +* use PLAN mode to get result metadata ([#388](https://www.github.com/googleapis/java-spanner-jdbc/issues/388)) ([8c7b665](https://www.github.com/googleapis/java-spanner-jdbc/commit/8c7b665c0c16dbec65da5040da038a320efa0a4a)) + + +### Documentation + +* add reference to jar-with-dependencies in readme ([#404](https://www.github.com/googleapis/java-spanner-jdbc/issues/404)) ([12c3235](https://www.github.com/googleapis/java-spanner-jdbc/commit/12c3235f4799cd2e74d523d1149c55573437c7ad)), closes [#399](https://www.github.com/googleapis/java-spanner-jdbc/issues/399) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v5.1.0 ([#393](https://www.github.com/googleapis/java-spanner-jdbc/issues/393)) ([9b36a54](https://www.github.com/googleapis/java-spanner-jdbc/commit/9b36a546963b044fc9eaf60667ab013afca6bc54)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v5.2.0 ([#398](https://www.github.com/googleapis/java-spanner-jdbc/issues/398)) ([8482652](https://www.github.com/googleapis/java-spanner-jdbc/commit/8482652e6d8933903ab8ccaece8bbe3224d080b5)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6 ([#403](https://www.github.com/googleapis/java-spanner-jdbc/issues/403)) ([3e0fbd1](https://www.github.com/googleapis/java-spanner-jdbc/commit/3e0fbd1706fc269cd7bfcd2258181487cc40cece)) + ## [1.21.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.20.1...v1.21.0) (2021-03-10) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 15b4830f84f0..cd3d5c568b66 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 - 1.21.1-SNAPSHOT + 2.0.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 55fbbbe7a8f9..cf69402502e3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.21.1-SNAPSHOT + 2.0.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c6a4bb9ac886..3d2f03ceb974 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:1.21.0:1.21.1-SNAPSHOT +google-cloud-spanner-jdbc:2.0.0:2.0.0 From ccb0d98045ff20837bc7d168592eb697bccd871a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 24 Mar 2021 06:48:02 +0000 Subject: [PATCH 0356/1979] chore: release 2.0.1-SNAPSHOT (#408) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cd3d5c568b66..dc8c473fa935 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.0 + 2.0.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index cf69402502e3..98a19e9a03b2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.0 + 2.0.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3d2f03ceb974..e817f33bd7f5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.0:2.0.0 +google-cloud-spanner-jdbc:2.0.0:2.0.1-SNAPSHOT From b0f945e07d645b2ac078e0cd00b12db1a33e9611 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 25 Mar 2021 02:50:06 +0100 Subject: [PATCH 0357/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2 (#409) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0edee3488a76..7e5e8b791d2d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 1.21.0 + 2.0.0 From a2df4f3efc348719c1d589cd6997241cb91096d8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 24 Mar 2021 19:08:02 -0700 Subject: [PATCH 0358/1979] chore: regenerate README (#412) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-03-25 01:52:12,889 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-03-25 01:52:14,048 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/308f86e5-3e08-4174-95a6-ede4c9611bfd/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 1c35e44741e3..a65fe82d3467 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3e0fbd1706fc269cd7bfcd2258181487cc40cece" + "sha": "f0cd180f7a34c28460ff88699614cf1173205002" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "86ed43d4f56e6404d068e62e497029018879c771" + "sha": "bb854b6c048619e3be4e8b8ce8ed10aa74ea78ef" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index bd9013fdcc7e..8250edaa457c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 1.21.0 + 2.0.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:1.21.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "1.21.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.0" ``` ## Authentication From 3d095961ed55f2d7750308dcccac7e76d8c29bb0 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Mon, 29 Mar 2021 10:42:53 +1100 Subject: [PATCH 0359/1979] chore: sets the min version of the repo as Java 8 (#411) This is used by autosynth to generate files such as the README. --- java-spanner-jdbc/.repo-metadata.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index 524b2f3f22c9..e787150b31a9 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -5,8 +5,10 @@ "client_documentation": "https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html", "release_level": "ga", "language": "java", + "min_java_version": 8, "repo": "googleapis/java-spanner-jdbc", "repo_short": "java-spanner-jdbc", "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc", "codeowner_team": "@googleapis/api-spanner-java" } + From 1e7a436cadbe05bd7964af26a99fdbfd8fa2c370 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Mon, 29 Mar 2021 10:43:17 +1100 Subject: [PATCH 0360/1979] chore: marks the branch 1.21.x as stable (#413) Updates the github configuration to mark the branch 1.21.x as stable. --- java-spanner-jdbc/.github/release-please.yml | 7 ++++- .../.github/sync-repo-settings.yaml | 31 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index dce2c8450921..127277a02466 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -1,2 +1,7 @@ releaseType: java-yoshi -bumpMinorPreMajor: true \ No newline at end of file +bumpMinorPreMajor: true +branches: +- branch: 1.21.x + releaseType: java-yoshi + bumpMinorPreMajor: true + diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index a0c0cd493824..7defd84ae437 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -38,6 +38,35 @@ branchProtectionRules: - "units (11)" - "Kokoro - Test: Integration" - "cla/google" + +# Rules for master branch protection +branchProtectionRules: +# Identifies the protection rule pattern. Name of the branch to be protected. +# Defaults to `master` +- pattern: 1.21.x + # Can admins overwrite branch protection. + # Defaults to `true` + isAdminEnforced: true + # Number of approving reviews required to update matching branches. + # Defaults to `1` + requiredApprovingReviewCount: 1 + # Are reviews from code owners required to update matching branches. + # Defaults to `false` + requiresCodeOwnerReviews: true + # Require up to date branches + requiresStrictStatusChecks: false + # List of required status check contexts that must pass for commits to be accepted to matching branches. + requiredStatusCheckContexts: + - "dependencies (8)" + - "dependencies (11)" + - "linkage-monitor" + - "lint" + - "clirr" + - "units (8)" + - "units (11)" + - "Kokoro - Test: Integration" + - "cla/google" + # List of explicit permissions to add (additive only) permissionRules: - team: yoshi-admins @@ -45,4 +74,4 @@ permissionRules: - team: yoshi-java-admins permission: admin - team: yoshi-java - permission: push \ No newline at end of file + permission: push From 710ed5b3b1ab9d89eec56bcdc05ac3ccea7d9ffa Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 28 Mar 2021 17:00:06 -0700 Subject: [PATCH 0361/1979] chore: regenerate README (#414) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-03-28 23:45:07,520 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-03-28 23:45:08,722 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/91579ce3-d49c-4399-bfda-3caaae494359/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index a65fe82d3467..668ae410d893 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "f0cd180f7a34c28460ff88699614cf1173205002" + "sha": "032f2c63dc95d4fc2bc4d05738031c1d1d880b4f" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "bb854b6c048619e3be4e8b8ce8ed10aa74ea78ef" + "sha": "60fc32cc950c20cfdd774b846a4a7dc5d1e4d0ef" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8250edaa457c..03bdbcc9a87f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -108,7 +108,7 @@ To get help, follow the instructions in the [shared Troubleshooting document][tr ## Java Versions -Java 7 or above is required for using this client. +Java 8 or above is required for using this client. ## Versioning @@ -135,7 +135,6 @@ Apache 2.0 - See [LICENSE][license] for more information. Java Version | Status ------------ | ------ -Java 7 | [![Kokoro CI][kokoro-badge-image-1]][kokoro-badge-link-1] Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2] Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] From 26409be66bffaf9417360a60073771de44d41b64 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 6 Apr 2021 20:05:15 -0700 Subject: [PATCH 0362/1979] chore: Re-generated to pick up changes from synthtool (#417) * changes without context autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. * chore(java): detect sample-secrets in build.sh Fixes #904 Source-Author: Neenu Shaji Source-Date: Wed Mar 24 15:50:02 2021 -0400 Source-Repo: googleapis/synthtool Source-Sha: bb854b6c048619e3be4e8b8ce8ed10aa74ea78ef Source-Link: https://github.com/googleapis/synthtool/commit/bb854b6c048619e3be4e8b8ce8ed10aa74ea78ef * chore: remove staging bucket v2 not needed since we removed v2 solution - https://github.com/googleapis/synthtool/pull/964 Source-Author: Emily Ball Source-Date: Mon Mar 29 14:47:37 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 572ef8f70edd9041f5bcfa71511aed6aecfc2098 Source-Link: https://github.com/googleapis/synthtool/commit/572ef8f70edd9041f5bcfa71511aed6aecfc2098 --- java-spanner-jdbc/.github/release-please.yml | 7 +------ java-spanner-jdbc/.kokoro/build.sh | 5 +++++ java-spanner-jdbc/.kokoro/nightly/java7.cfg | 7 +++++++ java-spanner-jdbc/.kokoro/presubmit/java7.cfg | 7 +++++++ java-spanner-jdbc/.kokoro/release/publish_javadoc.sh | 5 ----- java-spanner-jdbc/synth.metadata | 4 ++-- 6 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/nightly/java7.cfg create mode 100644 java-spanner-jdbc/.kokoro/presubmit/java7.cfg diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index 127277a02466..dce2c8450921 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -1,7 +1,2 @@ releaseType: java-yoshi -bumpMinorPreMajor: true -branches: -- branch: 1.21.x - releaseType: java-yoshi - bumpMinorPreMajor: true - +bumpMinorPreMajor: true \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 5566bac3f5c8..e4ddb5b737ac 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -79,6 +79,11 @@ samples) if [[ -f ${SAMPLES_DIR}/pom.xml ]] then + for FILE in ${KOKORO_GFILE_DIR}/secret_manager/*-samples-secrets; do + [[ -f "$FILE" ]] || continue + source "$FILE" + done + pushd ${SAMPLES_DIR} mvn -B \ -Penable-samples \ diff --git a/java-spanner-jdbc/.kokoro/nightly/java7.cfg b/java-spanner-jdbc/.kokoro/nightly/java7.cfg new file mode 100644 index 000000000000..cb24f44eea3b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/java7.cfg b/java-spanner-jdbc/.kokoro/presubmit/java7.cfg new file mode 100644 index 000000000000..cb24f44eea3b --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/java7.cfg @@ -0,0 +1,7 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java7" +} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 0773cfe82fe2..caa7dddfb5f5 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -24,11 +24,6 @@ if [[ -z "${STAGING_BUCKET}" ]]; then exit 1 fi -if [[ -z "${STAGING_BUCKET_V2}" ]]; then - echo "Need to set STAGING_BUCKET_V2 environment variable" - exit 1 -fi - # work from the git root directory pushd $(dirname "$0")/../../ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index ac98e78ee5c9..d862197c3f9f 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "b32e7aebd4c8d24d052e4616b5dd7735878e01c3" + "sha": "46fd8aad1018962d73c5752d37b89f26290a449c" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "0b064d767537e0675fc053e53fca473c5c701fb8" + "sha": "572ef8f70edd9041f5bcfa71511aed6aecfc2098" } } ], From 8a97461266cf81d0d57547b9cb306ac6a954feb8 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 7 Apr 2021 05:56:44 +0200 Subject: [PATCH 0363/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.22 (#422) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7e5e8b791d2d..ac8d45977bb9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.21 + 1.0.22 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 13432e5e892c..08d34f32f3c4 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.21 + 1.0.22 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 98a19e9a03b2..2c774fa9df4f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.21 + 1.0.22 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 4ae551a6378f..602836becd3d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.21 + 1.0.22 From 5fd565a0c014dfa98577f1df51c33a2ebc1c713b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 13 Apr 2021 06:08:53 +0200 Subject: [PATCH 0364/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.0 (#420) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dc8c473fa935..d43b9721b265 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.0.0 + 6.2.0 pom import From 46b5494269893b73893c67609fd488c13431c1ef Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 13 Apr 2021 06:09:10 +0200 Subject: [PATCH 0365/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.0 (#423) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d43b9721b265..35fa8e8b1657 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.20.1 + 0.21.0 pom import From bc9a43ffff504c6aa9025a5685e4cf66237bbb05 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 12 Apr 2021 21:09:38 -0700 Subject: [PATCH 0366/1979] build(java): skip javadoc tests during dependencies test (#424) Source-Author: Jeff Ching Source-Date: Fri Apr 9 09:18:54 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 5b0e1592dd7d70b485e157ea4b3eb1704ecbd015 Source-Link: https://github.com/googleapis/synthtool/commit/5b0e1592dd7d70b485e157ea4b3eb1704ecbd015 --- java-spanner-jdbc/.kokoro/dependencies.sh | 1 + java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 0fb8c8436ccc..59d2aafc790f 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -33,6 +33,7 @@ export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" retry_with_backoff 3 10 \ mvn install -B -V -ntp \ -DskipTests=true \ + -Dmaven.javadoc.skip=true \ -Dclirr.skip=true mvn -B dependency:analyze -DfailOnWarning=true diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index d862197c3f9f..8221195764bf 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "46fd8aad1018962d73c5752d37b89f26290a449c" + "sha": "aa52dbff8e007c902111eb64aee79f8548c94a1a" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "572ef8f70edd9041f5bcfa71511aed6aecfc2098" + "sha": "5b0e1592dd7d70b485e157ea4b3eb1704ecbd015" } } ], From abb4fbdfc7033a02fcbadd2026e0b98cf8ad262c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 13 Apr 2021 06:09:58 +0200 Subject: [PATCH 0367/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20 (#425) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 602836becd3d..bd61461981ca 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 19.2.1 + 20.0.0 pom import From 30dfd2d8257040be1e0c0a9b16986aaad6715c09 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 14:37:06 +1000 Subject: [PATCH 0368/1979] chore: release 2.0.1 (#426) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c935f736df4a..817bb15277a5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### [2.0.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.0...v2.0.1) (2021-04-13) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.0 ([#423](https://www.github.com/googleapis/java-spanner-jdbc/issues/423)) ([e0cf14a](https://www.github.com/googleapis/java-spanner-jdbc/commit/e0cf14a4dd087532924f49bb8e0431e1d681c7e8)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.0 ([#420](https://www.github.com/googleapis/java-spanner-jdbc/issues/420)) ([fdd8809](https://www.github.com/googleapis/java-spanner-jdbc/commit/fdd880943394e4760c26eadc3a87d5a298591eb1)) + ## [2.0.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v1.21.0...v2.0.0) (2021-03-24) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 35fa8e8b1657..3c197a7039ff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.1-SNAPSHOT + 2.0.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2c774fa9df4f..4d7c6e1a625c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.1-SNAPSHOT + 2.0.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e817f33bd7f5..d778cc6f2799 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.0:2.0.1-SNAPSHOT +google-cloud-spanner-jdbc:2.0.1:2.0.1 From ea3d3ed87c985dbc60540e639b3730e70a11413b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 12 Apr 2021 21:58:17 -0700 Subject: [PATCH 0369/1979] chore: autosynth (#416) Co-authored-by: Thiago Nunes --- java-spanner-jdbc/synth.metadata | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 8221195764bf..274898131661 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "aa52dbff8e007c902111eb64aee79f8548c94a1a" + "sha": "46fd8aad1018962d73c5752d37b89f26290a449c" } }, { From 7ae728ea11ff421558d23d4784fe145d99857810 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 15:47:29 +1000 Subject: [PATCH 0370/1979] chore: release 2.0.2-SNAPSHOT (#427) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3c197a7039ff..a7b0523b173b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.1 + 2.0.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4d7c6e1a625c..104da4da3cd5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.1 + 2.0.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d778cc6f2799..942735f6a750 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.1:2.0.1 +google-cloud-spanner-jdbc:2.0.1:2.0.2-SNAPSHOT From d2dd17cb93f8b43a34be48cc9b9798f3932d0c6d Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 13 Apr 2021 19:36:02 -0700 Subject: [PATCH 0371/1979] chore: regenerate README (#428) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 668ae410d893..36432895f847 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "032f2c63dc95d4fc2bc4d05738031c1d1d880b4f" + "sha": "da5084160a5c89552b57cf32e6af1e70e0d6b807" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "60fc32cc950c20cfdd774b846a4a7dc5d1e4d0ef" + "sha": "082e1ca0863b13ada8594fe91845380765da5b70" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 03bdbcc9a87f..1fbd770a5ab7 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.0.0 + 2.0.1 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.1" ``` ## Authentication From 6b74d1680f24cacc33e11267d87f231f978b2827 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 13 Apr 2021 19:37:56 -0700 Subject: [PATCH 0372/1979] fix: typo (#431) @Neenu1995 Source-Author: Elliotte Rusty Harold Source-Date: Tue Apr 13 00:00:05 2021 +0000 Source-Repo: googleapis/synthtool Source-Sha: 082e1ca0863b13ada8594fe91845380765da5b70 Source-Link: https://github.com/googleapis/synthtool/commit/082e1ca0863b13ada8594fe91845380765da5b70 --- java-spanner-jdbc/.kokoro/build.sh | 2 +- java-spanner-jdbc/synth.metadata | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index e4ddb5b737ac..9eaeef4f20a6 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -37,7 +37,7 @@ retry_with_backoff 3 10 \ -Dgcloud.download.skip=true \ -T 1C -# if GOOGLE_APPLICATION_CREDIENTIALS is specified as a relative path prepend Kokoro root directory onto it +# if GOOGLE_APPLICATION_CREDENTIALS is specified as a relative path, prepend Kokoro root directory onto it if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTIALS}" != /* ]]; then export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_GFILE_DIR}/${GOOGLE_APPLICATION_CREDENTIALS}) fi diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 274898131661..4bcb3feb26ba 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "46fd8aad1018962d73c5752d37b89f26290a449c" + "sha": "da5084160a5c89552b57cf32e6af1e70e0d6b807" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5b0e1592dd7d70b485e157ea4b3eb1704ecbd015" + "sha": "082e1ca0863b13ada8594fe91845380765da5b70" } } ], @@ -26,6 +26,7 @@ ".github/readme/synth.py", ".github/release-please.yml", ".github/snippet-bot.yml", + ".github/sync-repo-settings.yaml", ".github/trusted-contribution.yml", ".github/workflows/approve-readme.yaml", ".github/workflows/auto-release.yaml", From fa384d42430158b5afe5be2be435136d5f7b4445 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 14 Apr 2021 04:54:06 +0200 Subject: [PATCH 0373/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.0.1 (#429) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ac8d45977bb9..e5e5c85701ca 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.0 + 2.0.1 From 0157bcbcbed8c47917b4006c3c8a2c07a6187c04 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 14 Apr 2021 04:54:17 +0200 Subject: [PATCH 0374/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.1 (#430) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a7b0523b173b..8303e0c91e24 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.2.0 + 6.2.1 pom import From 41c85a21256375664ce837d3531131f02806bd99 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 15 Apr 2021 16:45:26 -0700 Subject: [PATCH 0375/1979] fix: release scripts from issuing overlapping phases (#434) `mvn deploy` will run `mvn install` so specifying `mvn install deploy` is redundant at best. At worst, it will cause plugins like maven-shade-plugin to be executed twice re-shading itself Source-Author: Igor Bernstein Source-Date: Wed Apr 14 13:16:03 2021 -0400 Source-Repo: googleapis/synthtool Source-Sha: 8285c2b4cdbc3771d031ad91e1c4ec9e55fff45d Source-Link: https://github.com/googleapis/synthtool/commit/8285c2b4cdbc3771d031ad91e1c4ec9e55fff45d --- java-spanner-jdbc/.kokoro/release/snapshot.sh | 2 +- java-spanner-jdbc/.kokoro/release/stage.sh | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/snapshot.sh b/java-spanner-jdbc/.kokoro/release/snapshot.sh index 098168a7373c..1f55b77024d8 100755 --- a/java-spanner-jdbc/.kokoro/release/snapshot.sh +++ b/java-spanner-jdbc/.kokoro/release/snapshot.sh @@ -25,7 +25,7 @@ grep SNAPSHOT versions.txt setup_environment_secrets create_settings_xml_file "settings.xml" -mvn clean install deploy -B \ +mvn clean deploy -B \ --settings ${MAVEN_SETTINGS_FILE} \ -DperformRelease=true \ -Dgpg.executable=gpg \ diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 16126d2eb53f..8a1033843cb1 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -29,7 +29,7 @@ create_settings_xml_file "settings.xml" # attempt to stage 3 times with exponential backoff (starting with 10 seconds) retry_with_backoff 3 10 \ - mvn clean install deploy -B \ + mvn clean deploy -B \ --settings ${MAVEN_SETTINGS_FILE} \ -DskipTests=true \ -DperformRelease=true \ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 4bcb3feb26ba..203fa091c833 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "da5084160a5c89552b57cf32e6af1e70e0d6b807" + "sha": "212d9d05c4f28ade71ab5484792188b11a5bcd8b" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "082e1ca0863b13ada8594fe91845380765da5b70" + "sha": "8285c2b4cdbc3771d031ad91e1c4ec9e55fff45d" } } ], From e7e93ec531f5d1390be19dd1986aba3b4898455d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 16 Apr 2021 01:45:46 +0200 Subject: [PATCH 0376/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.1.0 (#436) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index bd61461981ca..cb66073c1606 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.0.0 + 20.1.0 pom import From 69e78a02562b44ef74bb207d6f1553eab6634097 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Fri, 16 Apr 2021 11:19:12 +1000 Subject: [PATCH 0377/1979] chore: marks branch 1.21.x as stable (#437) * chore: adds branch 1.21.x as stable Adds branch 1.21.x in release please configuration * chore: fixes sync repo settings yml file Removes duplicated line * chore: adds units(7) ci to 1.21.x stable branch Makes unit tests on java 7 necessary for 1.21.x stable branch * chore: synth ignores release please and sync repo Ignores release please configuration and sync repo settings configuration in the synth tool. This is necessary to mark the branch 1.21.x as stable. --- java-spanner-jdbc/.github/release-please.yml | 7 ++++++- java-spanner-jdbc/.github/sync-repo-settings.yaml | 3 +-- java-spanner-jdbc/synth.py | 5 ++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index dce2c8450921..127277a02466 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -1,2 +1,7 @@ releaseType: java-yoshi -bumpMinorPreMajor: true \ No newline at end of file +bumpMinorPreMajor: true +branches: +- branch: 1.21.x + releaseType: java-yoshi + bumpMinorPreMajor: true + diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 7defd84ae437..26d3273bb356 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -39,8 +39,6 @@ branchProtectionRules: - "Kokoro - Test: Integration" - "cla/google" -# Rules for master branch protection -branchProtectionRules: # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `master` - pattern: 1.21.x @@ -62,6 +60,7 @@ branchProtectionRules: - "linkage-monitor" - "lint" - "clirr" + - "units (7)" - "units (8)" - "units (11)" - "Kokoro - Test: Integration" diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/synth.py index ab9fa625d1a9..85c630e3317a 100644 --- a/java-spanner-jdbc/synth.py +++ b/java-spanner-jdbc/synth.py @@ -19,5 +19,8 @@ AUTOSYNTH_MULTIPLE_COMMITS = True java.common_templates(excludes=[ - 'README.md' + 'README.md', + + '.github/release-please.yml', + '.github/sync-repo-settings.yaml', ]) From 3e13f7a4fbada6f56b645c51c5a10d9ca52df2f9 Mon Sep 17 00:00:00 2001 From: Zoe Date: Fri, 16 Apr 2021 13:59:33 +1000 Subject: [PATCH 0378/1979] chore: add default assignee for issues (#435) --- java-spanner-jdbc/.github/blunderbuss.yml | 4 +++- java-spanner-jdbc/synth.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml index 1a23ea42b141..f3e67a049132 100644 --- a/java-spanner-jdbc/.github/blunderbuss.yml +++ b/java-spanner-jdbc/.github/blunderbuss.yml @@ -1,7 +1,9 @@ # Configuration for the Blunderbuss GitHub app. For more info see # https://github.com/googleapis/repo-automation-bots/tree/master/packages/blunderbuss +assign_issues: + - thiagotnunes assign_prs_by: - labels: - samples to: - - googleapis/java-samples-reviewers \ No newline at end of file + - googleapis/java-samples-reviewers diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/synth.py index 85c630e3317a..de866777b818 100644 --- a/java-spanner-jdbc/synth.py +++ b/java-spanner-jdbc/synth.py @@ -20,7 +20,8 @@ java.common_templates(excludes=[ 'README.md', - + '.github/release-please.yml', '.github/sync-repo-settings.yaml', + '.github/blunderbuss.yml', ]) From 774c35d08cec196aebb3333cbf20132108766b23 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 26 Apr 2021 19:06:05 +0200 Subject: [PATCH 0379/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.11.2 (#373) [![WhiteSource 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) | `0.10.0` -> `0.11.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.11.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.11.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.11.2/compatibility-slim/0.10.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.11.2/confidence-slim/0.10.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.11.2`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​0112-httpswwwgithubcomgoogleapisjava-shared-configcomparev0111v0112-2021-04-22) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.11.1...v0.11.2) ### [`v0.11.1`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​0111-httpswwwgithubcomgoogleapisjava-shared-configcomparev0110v0111-2021-04-14) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.11.0...v0.11.1) ### [`v0.11.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​0110-httpswwwgithubcomgoogleapisjava-shared-configcomparev0100v0110-2021-02-25) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.10.0...v0.11.0) ##### Features - migrate releases to the new Google Sonatype endpoint to address Sonatype errors. ([#​230](https://www.github.com/googleapis/java-shared-config/issues/230)) ([ff6a95f](https://www.github.com/googleapis/java-shared-config/commit/ff6a95f7b0d24a1c37c38ba8ac6c6624ee97cc15)) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v8.40 ([#​221](https://www.github.com/googleapis/java-shared-config/issues/221)) ([d9b2d4a](https://www.github.com/googleapis/java-shared-config/commit/d9b2d4aab9a9bba1c2df6fcb52ac96ee8b001ad6)) - update dependency org.apache.maven.plugins:maven-checkstyle-plugin to v3.1.2 ([#​219](https://www.github.com/googleapis/java-shared-config/issues/219)) ([f7c3f79](https://www.github.com/googleapis/java-shared-config/commit/f7c3f798ef8ad1bc59ae673c84fbdd9f93ee2413))
    --- ### Configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8303e0c91e24..36a81488641d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.10.0 + 0.11.2 From 48e3d05e3a83af63334f3e935984991b6d3fa0a7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 26 Apr 2021 19:26:02 +0200 Subject: [PATCH 0380/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.1 (#438) [![WhiteSource 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/java-shared-dependencies) | `0.21.0` -> `0.21.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.21.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.21.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.21.1/compatibility-slim/0.21.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/0.21.1/confidence-slim/0.21.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v0.21.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​0211-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0210v0211-2021-04-19) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.21.0...v0.21.1)
    --- ### Configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 36a81488641d..cfadf48fc214 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.21.0 + 0.21.1 pom import From 9bbad0cee0cb5e44892b6cef9d5bd5b36c829361 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 26 Apr 2021 19:42:05 +0200 Subject: [PATCH 0381/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1 (#441) [![WhiteSource 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/java-shared-dependencies) | `0.21.1` -> `1.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.0.0/compatibility-slim/0.21.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.0.0/confidence-slim/0.21.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v1.0.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​100-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare0211v100-2021-04-23) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v0.21.1...v1.0.0) ##### Features - promote to 1.0.0 ([#​341](https://www.github.com/googleapis/java-shared-dependencies/issues/341)) ([eddce7b](https://www.github.com/googleapis/java-shared-dependencies/commit/eddce7bda196d757c0bb93a05574cc742e3d7ff6)) ##### Dependencies - update dependency com.google.api:api-common to v1.10.3 ([#​340](https://www.github.com/googleapis/java-shared-dependencies/issues/340)) ([6a7fc33](https://www.github.com/googleapis/java-shared-dependencies/commit/6a7fc33548c199d5f310b3ee5024907882d22726)) - update dependency com.google.auth:google-auth-library-bom to v0.25.4 ([#​334](https://www.github.com/googleapis/java-shared-dependencies/issues/334)) ([e5c747d](https://www.github.com/googleapis/java-shared-dependencies/commit/e5c747d245194effc258ae706e7764153010cd53)) - update dependency com.google.auth:google-auth-library-bom to v0.25.5 ([#​338](https://www.github.com/googleapis/java-shared-dependencies/issues/338)) ([ffa1df5](https://www.github.com/googleapis/java-shared-dependencies/commit/ffa1df5497b5365f520b665a202b8caf6521fc9d)) - update dependency org.threeten:threetenbp to v1.5.1 ([#​335](https://www.github.com/googleapis/java-shared-dependencies/issues/335)) ([c8c6df4](https://www.github.com/googleapis/java-shared-dependencies/commit/c8c6df48e7f80944544939e502f4f08543af2631)) - update google.core.version to v1.94.8 ([#​342](https://www.github.com/googleapis/java-shared-dependencies/issues/342)) ([d946dd2](https://www.github.com/googleapis/java-shared-dependencies/commit/d946dd2299aac32f969a2226a1391e1e73f00e62)) ##### [0.21.1](https://www.github.com/googleapis/java-shared-dependencies/compare/0.21.0...v0.21.1) (2021-04-19) ##### Bug Fixes - release scripts from issuing overlapping phases ([#​332](https://www.github.com/googleapis/java-shared-dependencies/issues/332)) ([e289825](https://www.github.com/googleapis/java-shared-dependencies/commit/e289825a3bc45b4796db7ce4347f8d9d9251a410)) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.12.3 ([#​329](https://www.github.com/googleapis/java-shared-dependencies/issues/329)) ([a77b4fc](https://www.github.com/googleapis/java-shared-dependencies/commit/a77b4fcc2ea5caf366c76a4698bac6d4c9abc92e)) - update dependency com.google.api-client:google-api-client-bom to v1.31.4 ([#​326](https://www.github.com/googleapis/java-shared-dependencies/issues/326)) ([409d24f](https://www.github.com/googleapis/java-shared-dependencies/commit/409d24f8a0cac30e41ca45eb2711aecb335d70dd)) - update dependency com.google.auth:google-auth-library-bom to v0.25.3 ([#​328](https://www.github.com/googleapis/java-shared-dependencies/issues/328)) ([88cfc08](https://www.github.com/googleapis/java-shared-dependencies/commit/88cfc08952881200e23ed95cfa2eebad85ec7ab3)) - update google.core.version to v1.94.7 ([#​324](https://www.github.com/googleapis/java-shared-dependencies/issues/324)) ([0412c88](https://www.github.com/googleapis/java-shared-dependencies/commit/0412c88468940c1182bc0761bfe269a6688fe7b7)) - update iam.version to v1.0.12 ([#​327](https://www.github.com/googleapis/java-shared-dependencies/issues/327)) ([548d5f5](https://www.github.com/googleapis/java-shared-dependencies/commit/548d5f53c4f264f1cbb9ca72fdfe4608ab16b480))
    --- ### Configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cfadf48fc214..130fd0c72fcd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 0.21.1 + 1.0.0 pom import From 13c37836d9adaa4596e41609cf4e54da371d6eea Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 26 Apr 2021 19:58:08 +0200 Subject: [PATCH 0382/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.3.3 (#439) [![WhiteSource 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.2.1` -> `6.3.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.3.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.3.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.3.3/compatibility-slim/6.2.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.3.3/confidence-slim/6.2.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.3.3`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​633-httpswwwgithubcomgoogleapisjava-spannercomparev632v633-2021-04-24) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.3.2...v6.3.3) ### [`v6.3.2`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​632-httpswwwgithubcomgoogleapisjava-spannercomparev631v632-2021-04-20) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.3.1...v6.3.2) ### [`v6.3.1`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​631-httpswwwgithubcomgoogleapisjava-spannercomparev630v631-2021-04-20) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.3.0...v6.3.1) ### [`v6.3.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​630-httpswwwgithubcomgoogleapisjava-spannercomparev621v630-2021-04-19) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.2.1...v6.3.0) ##### Features - async work as functional interface ([#​1068](https://www.github.com/googleapis/java-spanner/issues/1068)) ([734fb60](https://www.github.com/googleapis/java-spanner/commit/734fb6095819bde94ea482b02a8e77983f2a5449)) - **spanner:** add `progress` field to `UpdateDatabaseDdlMetadata` ([#​1063](https://www.github.com/googleapis/java-spanner/issues/1063)) ([7992342](https://www.github.com/googleapis/java-spanner/commit/7992342bffc273ad8249e7564ae9ef51764bf83c)) - transaction callable as functional interface ([#​1066](https://www.github.com/googleapis/java-spanner/issues/1066)) ([b036a77](https://www.github.com/googleapis/java-spanner/commit/b036a77196886f16d2738e70f676ccc99a52874c)) ##### Bug Fixes - release scripts from issuing overlapping phases ([#​1064](https://www.github.com/googleapis/java-spanner/issues/1064)) ([2f6fe5e](https://www.github.com/googleapis/java-spanner/commit/2f6fe5e87cc4c9ae26a6f2867411004a8c2b39fe)) ##### Dependencies - update dependency org.openjdk.jmh:jmh-generator-annprocess to v1.29 ([#​1014](https://www.github.com/googleapis/java-spanner/issues/1014)) ([81ee9b0](https://www.github.com/googleapis/java-spanner/commit/81ee9b02d5846f6569f588d3b17da4faf2f2dae9)) ##### [6.2.1](https://www.github.com/googleapis/java-spanner/compare/v6.2.0...v6.2.1) (2021-04-13) ##### Dependencies - update dependency com.google.cloud:google-cloud-monitoring to v2.2.0 ([#​1054](https://www.github.com/googleapis/java-spanner/issues/1054)) ([0b59b94](https://www.github.com/googleapis/java-spanner/commit/0b59b946b31c4b5ca95a2c279bdc835f23f1a923)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.0 ([#​1045](https://www.github.com/googleapis/java-spanner/issues/1045)) ([94dcb46](https://www.github.com/googleapis/java-spanner/commit/94dcb468e807516f07777fc62faff345441ccdf6)) - update dependency com.google.cloud:google-cloud-trace to v1.3.1 ([#​1050](https://www.github.com/googleapis/java-spanner/issues/1050)) ([cbb1038](https://www.github.com/googleapis/java-spanner/commit/cbb103846e33210c914f51f64e1e47f32ff775da))
    --- ### Configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 130fd0c72fcd..56a0976a8c3d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.2.1 + 6.3.3 pom import From 34b70a93f885ad64978e8780c6dc446637424722 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 26 Apr 2021 19:36:04 +0000 Subject: [PATCH 0383/1979] chore: release 2.0.2 (#432) :robot: I have created a release \*beep\* \*boop\* --- ### [2.0.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.1...v2.0.2) (2021-04-26) ### Bug Fixes * release scripts from issuing overlapping phases ([#434](https://www.github.com/googleapis/java-spanner-jdbc/issues/434)) ([41c85a2](https://www.github.com/googleapis/java-spanner-jdbc/commit/41c85a21256375664ce837d3531131f02806bd99)) * typo ([#431](https://www.github.com/googleapis/java-spanner-jdbc/issues/431)) ([6b74d16](https://www.github.com/googleapis/java-spanner-jdbc/commit/6b74d1680f24cacc33e11267d87f231f978b2827)) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.1 ([#438](https://www.github.com/googleapis/java-spanner-jdbc/issues/438)) ([48e3d05](https://www.github.com/googleapis/java-spanner-jdbc/commit/48e3d05e3a83af63334f3e935984991b6d3fa0a7)) * update dependency com.google.cloud:google-cloud-shared-dependencies to v1 ([#441](https://www.github.com/googleapis/java-spanner-jdbc/issues/441)) ([9bbad0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/9bbad0cee0cb5e44892b6cef9d5bd5b36c829361)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.1 ([#430](https://www.github.com/googleapis/java-spanner-jdbc/issues/430)) ([0157bcb](https://www.github.com/googleapis/java-spanner-jdbc/commit/0157bcbcbed8c47917b4006c3c8a2c07a6187c04)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.3.3 ([#439](https://www.github.com/googleapis/java-spanner-jdbc/issues/439)) ([13c3783](https://www.github.com/googleapis/java-spanner-jdbc/commit/13c37836d9adaa4596e41609cf4e54da371d6eea)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 817bb15277a5..1acc5b01e3ad 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +### [2.0.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.1...v2.0.2) (2021-04-26) + + +### Bug Fixes + +* release scripts from issuing overlapping phases ([#434](https://www.github.com/googleapis/java-spanner-jdbc/issues/434)) ([b2eec0f](https://www.github.com/googleapis/java-spanner-jdbc/commit/b2eec0f079e64f5c21b89bbc0b02e3e981d6469a)) +* typo ([#431](https://www.github.com/googleapis/java-spanner-jdbc/issues/431)) ([a0b158b](https://www.github.com/googleapis/java-spanner-jdbc/commit/a0b158bf9931d610779dec51ca61107078e9398e)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.1 ([#438](https://www.github.com/googleapis/java-spanner-jdbc/issues/438)) ([aa56b5c](https://www.github.com/googleapis/java-spanner-jdbc/commit/aa56b5c1d5e3b1ccdaa0d5b877deccbda5aa0061)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v1 ([#441](https://www.github.com/googleapis/java-spanner-jdbc/issues/441)) ([df7f0e7](https://www.github.com/googleapis/java-spanner-jdbc/commit/df7f0e796c03f9607e57b4b6ba999c92ea14c58d)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.1 ([#430](https://www.github.com/googleapis/java-spanner-jdbc/issues/430)) ([212d9d0](https://www.github.com/googleapis/java-spanner-jdbc/commit/212d9d05c4f28ade71ab5484792188b11a5bcd8b)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.3.3 ([#439](https://www.github.com/googleapis/java-spanner-jdbc/issues/439)) ([a128c4c](https://www.github.com/googleapis/java-spanner-jdbc/commit/a128c4cbe0e6b66f9276b71f7733a46645186e88)) + ### [2.0.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.0...v2.0.1) (2021-04-13) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 56a0976a8c3d..a64cd171e91b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.2-SNAPSHOT + 2.0.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 104da4da3cd5..30d747066b0e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.2-SNAPSHOT + 2.0.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 942735f6a750..7710d28ba4db 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.1:2.0.2-SNAPSHOT +google-cloud-spanner-jdbc:2.0.2:2.0.2 From 93dd183ec4d567736ff55ffc25ca5f83ba467fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 28 Apr 2021 08:12:38 +0200 Subject: [PATCH 0384/1979] fix: NPE was thrown when getting an array of structs from a ResultSet (#445) A NullPointerException was thrown if a ResultSet contained an array of Structs and the getArray() method was called on the column. Fixes #444 --- .../cloud/spanner/jdbc/JdbcDataType.java | 27 ++++++++++++ .../cloud/spanner/jdbc/JdbcArrayTest.java | 25 ++++++----- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 42 +++++++++++++++++++ 3 files changed, 84 insertions(+), 10 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 1dc5f0e49e6b..6e6c3bf82142 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; import java.math.BigDecimal; @@ -253,6 +254,32 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.timestamp(); } + }, + STRUCT { + @Override + public int getSqlType() { + return Types.STRUCT; + } + + @Override + public Class getJavaClass() { + return Struct.class; + } + + @Override + public Code getCode() { + return Code.STRUCT; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getStructList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.struct(); + } }; public abstract int getSqlType(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 24e3e57362e6..f8cacd99c328 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -18,15 +18,19 @@ import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlDate; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import java.math.BigDecimal; import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.sql.Timestamp; import java.sql.Types; import org.junit.Test; @@ -174,16 +178,17 @@ public void testCreateArrayOfArray() { } @Test - public void testCreateArrayOfStruct() { - try { - JdbcArray.createArray("STRUCT", new Object[] {}); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat((Exception) e).isInstanceOf(JdbcSqlException.class); - JdbcSqlException jse = (JdbcSqlException) e; - assertThat(jse.getErrorCode()) - .isEqualTo(ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()); - } + public void testCreateArrayOfStruct() throws SQLException { + JdbcArray array = + JdbcArray.createArray( + "STRUCT", + new Struct[] {Struct.newBuilder().set("f1").to("v1").set("f2").to(1L).build(), null}); + assertEquals(Types.STRUCT, array.getBaseType()); + assertThat((Struct[]) array.getArray()) + .asList() + .containsExactly(Struct.newBuilder().set("f1").to("v1").set("f2").to(1L).build(), null) + .inOrder(); + assertThrows(SQLFeatureNotSupportedException.class, () -> array.getResultSet()); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index 15f25b919ed7..fcb3b0e44073 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -17,14 +17,22 @@ package com.google.cloud.spanner.jdbc.it; import static com.google.common.truth.Truth.assertThat; +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 com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import java.sql.Array; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.sql.Statement; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -149,4 +157,38 @@ public void testAddBatchWhenAlreadyInBatch() { "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection."); } } + + @Test + public void testSelectArrayOfStructs() throws SQLException { + String sql = + "WITH points AS\n" + + " (SELECT [1, 5] as point\n" + + " UNION ALL SELECT [2, 8] as point\n" + + " UNION ALL SELECT [3, 7] as point\n" + + " UNION ALL SELECT [4, 1] as point\n" + + " UNION ALL SELECT [5, 7] as point)\n" + + "SELECT ARRAY(\n" + + " SELECT STRUCT(point)\n" + + " FROM points)\n" + + " AS coordinates"; + try (Connection connection = createConnection()) { + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + assertTrue(resultSet.next()); + assertEquals(resultSet.getMetaData().getColumnCount(), 1); + Array array = resultSet.getArray(1); + assertThat((Struct[]) array.getArray()) + .asList() + .containsExactly( + Struct.newBuilder().set("point").to(Value.int64Array(new long[] {1L, 5L})).build(), + Struct.newBuilder().set("point").to(Value.int64Array(new long[] {2L, 8L})).build(), + Struct.newBuilder().set("point").to(Value.int64Array(new long[] {3L, 7L})).build(), + Struct.newBuilder().set("point").to(Value.int64Array(new long[] {4L, 1L})).build(), + Struct.newBuilder().set("point").to(Value.int64Array(new long[] {5L, 7L})).build()); + // Getting a result set from an array of structs is not supported, as structs are not + // supported as a valid column type in a result set. + assertThrows(SQLFeatureNotSupportedException.class, () -> array.getResultSet()); + assertFalse(resultSet.next()); + } + } + } } From c43a1a16fd2991cd3eb4d4d67bd252f8186189d0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 29 Apr 2021 07:21:43 +0200 Subject: [PATCH 0385/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.0.2 (#443) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e5e5c85701ca..e6a32e36e2e9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.1 + 2.0.2 From e5804d0ccfab3398ae4bca8cc10e18a637d8c1ee Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 28 Apr 2021 22:39:54 -0700 Subject: [PATCH 0386/1979] chore: regenerate README (#450) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 36432895f847..080e198ec846 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "da5084160a5c89552b57cf32e6af1e70e0d6b807" + "sha": "16b9802d53e640060de608e27aede6dc40310267" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "082e1ca0863b13ada8594fe91845380765da5b70" + "sha": "06a8cd0ff7e81b05e6c503eab510ec622384caa7" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 1fbd770a5ab7..2e88e52b811e 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.0.1 + 2.0.2 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.1' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.2' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.2" ``` ## Authentication From 17ae37b6279363d2508bfe206a25686904f1d9e3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 29 Apr 2021 19:50:06 +0200 Subject: [PATCH 0387/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.2.0 (#448) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.1.0` -> `20.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/compatibility-slim/20.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/confidence-slim/20.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index cb66073c1606..2d909936cfe3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.1.0 + 20.2.0 pom import From 7a90d8b255b0239ae83770b1f5ca9d342dd25e5f Mon Sep 17 00:00:00 2001 From: "google-cloud-policy-bot[bot]" <80869356+google-cloud-policy-bot[bot]@users.noreply.github.com> Date: Fri, 30 Apr 2021 18:22:15 +0000 Subject: [PATCH 0388/1979] chore: add SECURITY.md (#446) chore: add SECURITY.md --- java-spanner-jdbc/SECURITY.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 java-spanner-jdbc/SECURITY.md diff --git a/java-spanner-jdbc/SECURITY.md b/java-spanner-jdbc/SECURITY.md new file mode 100644 index 000000000000..8b58ae9c01ae --- /dev/null +++ b/java-spanner-jdbc/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). + +The Google Security Team will respond within 5 working days of your report on g.co/vulnz. + +We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. From c9df35d49065f552ff782a1169388b1ad4dd122c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 4 May 2021 10:30:05 +0200 Subject: [PATCH 0389/1979] feat: allow get/set Spanner Value instances (#454) Adds support for getting a value from a `java.sql.ResultSet` as a `com.google.cloud.spanner.Value` instance, and for setting a parameter on a `java.sql.PreparedStatement` using a `com.google.cloud.spanner.Value` instance. Fixes #452 --- .../jdbc/AbstractJdbcPreparedStatement.java | 2 +- .../spanner/jdbc/JdbcParameterStore.java | 72 +++++++++-- .../spanner/jdbc/JdbcPreparedStatement.java | 4 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 61 +++++++++- .../spanner/jdbc/JdbcParameterStoreTest.java | 88 +++++++++++--- .../jdbc/JdbcPreparedStatementTest.java | 39 ++++++ .../cloud/spanner/jdbc/JdbcResultSetTest.java | 112 +++++++++++++++++- .../jdbc/it/ITJdbcPreparedStatementTest.java | 108 +++++++++++++++++ 8 files changed, 454 insertions(+), 32 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 0507d5d5d604..2a905660b1c1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -198,7 +198,7 @@ public void setObject(int parameterIndex, Object value, int targetSqlType) throw @Override public void setObject(int parameterIndex, Object value) throws SQLException { checkClosed(); - parameters.setParameter(parameterIndex, value, null); + parameters.setParameter(parameterIndex, value, (SQLType) null); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 2c529c4e7d9a..75f16cd8e18c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -19,6 +19,7 @@ import com.google.cloud.ByteArray; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Statement.Builder; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.common.io.CharStreams; @@ -39,6 +40,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLType; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -129,7 +131,8 @@ void setColumn(int parameterIndex, String column) throws SQLException { getParameter(parameterIndex), getType(parameterIndex), getScaleOrLength(parameterIndex), - column); + column, + null); } void setType(int parameterIndex, Integer type) throws SQLException { @@ -138,26 +141,71 @@ void setType(int parameterIndex, Integer type) throws SQLException { getParameter(parameterIndex), type, getScaleOrLength(parameterIndex), - getColumn(parameterIndex)); + getColumn(parameterIndex), + null); } + /** Sets a parameter value. The type will be determined based on the type of the value. */ + void setParameter(int parameterIndex, Object value) throws SQLException { + setParameter(parameterIndex, value, null, null, null, null); + } + + /** Sets a parameter value as the specified vendor-specific {@link SQLType}. */ + void setParameter(int parameterIndex, Object value, SQLType sqlType) throws SQLException { + setParameter(parameterIndex, value, null, null, null, sqlType); + } + + /** + * Sets a parameter value as the specified vendor-specific {@link SQLType} with the specified + * scale or length. This method is only here to support the {@link + * PreparedStatement#setObject(int, Object, SQLType, int)} method. + */ + void setParameter(int parameterIndex, Object value, SQLType sqlType, Integer scaleOrLength) + throws SQLException { + setParameter(parameterIndex, value, null, scaleOrLength, null, sqlType); + } + + /** + * Sets a parameter value as the specified sql type. The type can be one of the constants in + * {@link Types} or a vendor specific type code supplied by a vendor specific {@link SQLType}. + */ void setParameter(int parameterIndex, Object value, Integer sqlType) throws SQLException { setParameter(parameterIndex, value, sqlType, null); } + /** + * Sets a parameter value as the specified sql type with the specified scale or length. The type + * can be one of the constants in {@link Types} or a vendor specific type code supplied by a + * vendor specific {@link SQLType}. + */ void setParameter(int parameterIndex, Object value, Integer sqlType, Integer scaleOrLength) throws SQLException { - setParameter(parameterIndex, value, sqlType, scaleOrLength, null); + setParameter(parameterIndex, value, sqlType, scaleOrLength, null, null); } + /** + * Sets a parameter value as the specified sql type with the specified scale or length. Any {@link + * SQLType} instance will take precedence over sqlType. The type can be one of the constants in + * {@link Types} or a vendor specific type code supplied by a vendor specific {@link SQLType}. + */ void setParameter( - int parameterIndex, Object value, Integer sqlType, Integer scaleOrLength, String column) + int parameterIndex, + Object value, + Integer sqlType, + Integer scaleOrLength, + String column, + SQLType sqlTypeObject) throws SQLException { - // check that only valid type/value combinations are entered - if (sqlType != null) { - checkTypeAndValueSupported(value, sqlType); - } - // set the parameter + // Ignore the sql type if the application has created a Spanner Value object. + if (!(value instanceof Value)) { + // check that only valid type/value combinations are entered + if (sqlTypeObject != null && sqlType == null) { + sqlType = sqlTypeObject.getVendorTypeNumber(); + } + if (sqlType != null) { + checkTypeAndValueSupported(value, sqlType); + } + } // set the parameter highestIndex = Math.max(parameterIndex, highestIndex); int arrayIndex = parameterIndex - 1; if (arrayIndex >= parametersList.size() || parametersList.get(arrayIndex) == null) { @@ -416,7 +464,11 @@ Builder bindParameterValue(ValueBinder binder, int index) throws SQLExc /** Set a value from a JDBC parameter on a Spanner {@link Statement}. */ Builder setValue(ValueBinder binder, Object value, Integer sqlType) throws SQLException { Builder res; - if (sqlType != null && sqlType == Types.ARRAY) { + if (value instanceof Value) { + // If a Value has been constructed, then that should override any sqlType that might have been + // supplied. + res = binder.to((Value) value); + } else if (sqlType != null && sqlType == Types.ARRAY) { if (value instanceof Array) { Array array = (Array) value; value = array.getArray(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index b0032e44e15b..919aad302cc9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -24,6 +24,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -48,7 +49,8 @@ ParametersInfo getParametersInfo() throws SQLException { return parameters; } - private Statement createStatement() throws SQLException { + @VisibleForTesting + Statement createStatement() throws SQLException { ParametersInfo paramInfo = getParametersInfo(); Statement.Builder builder = Statement.newBuilder(paramInfo.sqlWithNamedParameters); for (int index = 1; index <= getParameters().getHighestIndex(); index++) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index c1f4b929d1bf..6aa9b48a6949 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -21,6 +21,7 @@ import com.google.cloud.Timestamp; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; +import com.google.cloud.spanner.Value; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; @@ -28,6 +29,7 @@ import java.sql.SQLException; import java.sql.Time; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.concurrent.TimeUnit; @@ -59,8 +61,13 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx JdbcPreconditions.checkArgument(targetType != null, "targetType may not be null"); checkValidTypeAndValueForConvert(type, value); - if (value == null) return null; + if (value == null) { + return null; + } try { + if (targetType.equals(Value.class)) { + return convertToSpannerValue(value, type); + } if (targetType.equals(String.class)) { if (type.getCode() == Code.BYTES) return new String((byte[]) value, UTF8); if (type.getCode() == Code.TIMESTAMP) { @@ -155,6 +162,58 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx com.google.rpc.Code.INVALID_ARGUMENT); } + private static Value convertToSpannerValue(Object value, Type type) throws SQLException { + switch (type.getCode()) { + case ARRAY: + switch (type.getArrayElementType().getCode()) { + case BOOL: + return Value.boolArray(Arrays.asList((Boolean[]) ((java.sql.Array) value).getArray())); + case BYTES: + return Value.bytesArray(toGoogleBytes((byte[][]) ((java.sql.Array) value).getArray())); + case DATE: + return Value.dateArray( + toGoogleDates((java.sql.Date[]) ((java.sql.Array) value).getArray())); + case FLOAT64: + return Value.float64Array( + Arrays.asList((Double[]) ((java.sql.Array) value).getArray())); + case INT64: + return Value.int64Array(Arrays.asList((Long[]) ((java.sql.Array) value).getArray())); + case NUMERIC: + return Value.numericArray( + Arrays.asList((BigDecimal[]) ((java.sql.Array) value).getArray())); + case STRING: + return Value.stringArray(Arrays.asList((String[]) ((java.sql.Array) value).getArray())); + case TIMESTAMP: + return Value.timestampArray( + toGoogleTimestamps((java.sql.Timestamp[]) ((java.sql.Array) value).getArray())); + case STRUCT: + default: + throw JdbcSqlExceptionFactory.of( + "invalid argument: " + value, com.google.rpc.Code.INVALID_ARGUMENT); + } + case BOOL: + return Value.bool((Boolean) value); + case BYTES: + return Value.bytes(ByteArray.copyFrom((byte[]) value)); + case DATE: + return Value.date(toGoogleDate((java.sql.Date) value)); + case FLOAT64: + return Value.float64((Double) value); + case INT64: + return Value.int64((Long) value); + case NUMERIC: + return Value.numeric((BigDecimal) value); + case STRING: + return Value.string((String) value); + case TIMESTAMP: + return Value.timestamp(toGoogleTimestamp((java.sql.Timestamp) value)); + case STRUCT: + default: + throw JdbcSqlExceptionFactory.of( + "invalid argument: " + value, com.google.rpc.Code.INVALID_ARGUMENT); + } + } + private static void checkValidTypeAndValueForConvert(Type type, Object value) throws SQLException { if (value == null) return; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 7f686013889e..0515188dad82 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -44,6 +44,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Arrays; +import java.util.Collections; import java.util.UUID; import org.junit.Test; import org.junit.runner.RunWith; @@ -52,6 +53,61 @@ @RunWith(JUnit4.class) public class JdbcParameterStoreTest { + /** + * Tests setting a {@link Value} as a parameter value. + * + * @throws SQLException + */ + @Test + public void testSetValueAsParameter() throws SQLException { + JdbcParameterStore params = new JdbcParameterStore(); + params.setParameter(1, Value.bool(true)); + verifyParameter(params, Value.bool(true)); + params.setParameter(1, Value.bytes(ByteArray.copyFrom("test"))); + verifyParameter(params, Value.bytes(ByteArray.copyFrom("test"))); + params.setParameter(1, Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3))); + verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3))); + params.setParameter(1, Value.float64(3.14d)); + verifyParameter(params, Value.float64(3.14d)); + params.setParameter(1, Value.int64(1L)); + verifyParameter(params, Value.int64(1L)); + params.setParameter(1, Value.numeric(BigDecimal.TEN)); + verifyParameter(params, Value.numeric(BigDecimal.TEN)); + params.setParameter(1, Value.string("test")); + verifyParameter(params, Value.string("test")); + params.setParameter( + 1, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(9999L, 101))); + verifyParameter( + params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(9999L, 101))); + + params.setParameter(1, Value.boolArray(new boolean[] {true, false})); + verifyParameter(params, Value.boolArray(new boolean[] {true, false})); + params.setParameter(1, Value.bytesArray(Collections.singleton(ByteArray.copyFrom("test")))); + verifyParameter(params, Value.bytesArray(Collections.singleton(ByteArray.copyFrom("test")))); + params.setParameter( + 1, + Value.dateArray(Collections.singleton(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3)))); + verifyParameter( + params, + Value.dateArray(Collections.singleton(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3)))); + params.setParameter(1, Value.float64Array(Collections.singleton(3.14d))); + verifyParameter(params, Value.float64Array(Collections.singleton(3.14d))); + params.setParameter(1, Value.int64Array(Collections.singleton(1L))); + verifyParameter(params, Value.int64Array(Collections.singleton(1L))); + params.setParameter(1, Value.numericArray(Collections.singleton(BigDecimal.TEN))); + verifyParameter(params, Value.numericArray(Collections.singleton(BigDecimal.TEN))); + params.setParameter(1, Value.stringArray(Collections.singleton("test"))); + verifyParameter(params, Value.stringArray(Collections.singleton("test"))); + params.setParameter( + 1, + Value.timestampArray( + Collections.singleton(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(9999L, 101)))); + verifyParameter( + params, + Value.timestampArray( + Collections.singleton(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(9999L, 101)))); + } + /** Tests setting a parameter value together with a sql type */ @SuppressWarnings("deprecation") @Test @@ -422,55 +478,55 @@ private void assertInvalidParameter(JdbcParameterStore params, Object value, int @Test public void testSetParameterWithoutType() throws SQLException { JdbcParameterStore params = new JdbcParameterStore(); - params.setParameter(1, (byte) 1, null); + params.setParameter(1, (byte) 1, (Integer) null); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); - params.setParameter(1, (short) 1, null); + params.setParameter(1, (short) 1, (Integer) null); assertEquals(1, ((Short) params.getParameter(1)).shortValue()); verifyParameter(params, Value.int64(1)); - params.setParameter(1, 1, null); + params.setParameter(1, 1, (Integer) null); assertEquals(1, ((Integer) params.getParameter(1)).intValue()); verifyParameter(params, Value.int64(1)); - params.setParameter(1, 1L, null); + params.setParameter(1, 1L, (Integer) null); assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); - params.setParameter(1, (float) 1, null); + params.setParameter(1, (float) 1, (Integer) null); assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); verifyParameter(params, Value.float64(1)); - params.setParameter(1, (double) 1, null); + params.setParameter(1, (double) 1, (Integer) null); assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); verifyParameter(params, Value.float64(1)); - params.setParameter(1, new Date(1970 - 1900, 0, 1), null); + params.setParameter(1, new Date(1970 - 1900, 0, 1), (Integer) null); assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); verifyParameter(params, Value.date(com.google.cloud.Date.fromYearMonthDay(1970, 1, 1))); - params.setParameter(1, new Time(0L), null); + params.setParameter(1, new Time(0L), (Integer) null); assertEquals(new Time(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); - params.setParameter(1, new Timestamp(0L), null); + params.setParameter(1, new Timestamp(0L), (Integer) null); assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); - params.setParameter(1, new byte[] {1, 2, 3}, null); + params.setParameter(1, new byte[] {1, 2, 3}, (Integer) null); assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); - params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), null); + params.setParameter(1, new JdbcBlob(new byte[] {1, 2, 3}), (Integer) null); assertEquals(new JdbcBlob(new byte[] {1, 2, 3}), params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); - params.setParameter(1, new JdbcClob("test"), null); + params.setParameter(1, new JdbcClob("test"), (Integer) null); assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); - params.setParameter(1, true, null); + params.setParameter(1, true, (Integer) null); assertTrue((Boolean) params.getParameter(1)); verifyParameter(params, Value.bool(true)); - params.setParameter(1, "test", null); + params.setParameter(1, "test", (Integer) null); assertEquals("test", params.getParameter(1)); verifyParameter(params, Value.string("test")); - params.setParameter(1, new JdbcClob("test"), null); + params.setParameter(1, new JdbcClob("test"), (Integer) null); assertEquals(new JdbcClob("test"), params.getParameter(1)); verifyParameter(params, Value.string("test")); - params.setParameter(1, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), null); + params.setParameter(1, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), (Integer) null); assertEquals(UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), params.getParameter(1)); verifyParameter(params, Value.string("83b988cf-1f4e-428a-be3d-cc712621942e")); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index b19aa54c12a8..40ad1ad011cf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.ByteArray; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.ResultSets; @@ -32,10 +33,12 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.Connection; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.StringReader; +import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Date; @@ -51,6 +54,7 @@ import java.sql.Types; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.TimeZone; import java.util.UUID; import org.junit.Test; @@ -99,6 +103,41 @@ private JdbcConnection createMockConnection(Connection spanner) throws SQLExcept return connection; } + @Test + public void testValueAsParameter() throws SQLException { + String sql = generateSqlWithParameters(1); + JdbcConnection connection = createMockConnection(); + for (Value value : + new Value[] { + Value.bool(true), + Value.bool(false), + Value.bytes(ByteArray.copyFrom("foo")), + Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 17)), + Value.float64(6.626d), + Value.int64(13L), + Value.numeric(new BigDecimal("3.14")), + Value.string("bar"), + Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(999L, 99)), + Value.boolArray(Collections.singleton(true)), + Value.bytesArray(Collections.singleton(ByteArray.copyFrom("foo"))), + Value.dateArray( + Collections.singleton(com.google.cloud.Date.fromYearMonthDay(2021, 5, 17))), + Value.float64Array(Collections.singleton(6.626d)), + Value.int64Array(Collections.singleton(13L)), + Value.numericArray(Collections.singleton(new BigDecimal("3.14"))), + Value.stringArray(Collections.singleton("bar")), + Value.timestampArray( + Collections.singleton(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(999L, 99))), + }) { + + try (JdbcPreparedStatement ps = new JdbcPreparedStatement(connection, sql)) { + ps.setObject(1, value); + Statement statement = ps.createStatement(); + assertEquals(statement.getParameters().get("p1"), value); + } + } + } + @SuppressWarnings("deprecation") @Test public void testParameters() throws SQLException, MalformedURLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 2ad4a6d4831c..9fa5f3e9c9c7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -35,6 +35,7 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.rpc.Code; import java.io.IOException; @@ -52,6 +53,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.TimeZone; import org.junit.Test; @@ -125,6 +127,28 @@ public class JdbcResultSetTest { private static final String STRING_COL_TIME = "STRING_COL_TIME"; private static final int STRING_COLINDEX_TIME = 24; private static final String STRING_TIME_VALUE = "10:31:15"; + private static final String NUMERIC_COL_NULL = "NUMERIC_COL_NULL"; + private static final String NUMERIC_COL_NOT_NULL = "NUMERIC_COL_NOT_NULL"; + private static final BigDecimal NUMERIC_VALUE = new BigDecimal("3.14"); + private static final int NUMERIC_COLINDEX_NULL = 25; + private static final int NUMERIC_COLINDEX_NOTNULL = 26; + + private static final String BOOL_ARRAY_COL = "BOOL_ARRAY"; + private static final List BOOL_ARRAY_VALUE = Arrays.asList(true, null, false); + private static final String BYTES_ARRAY_COL = "BYTES_ARRAY"; + private static final List BYTES_ARRAY_VALUE = Arrays.asList(BYTES_VALUE, null); + private static final String DATE_ARRAY_COL = "DATE_ARRAY"; + private static final List DATE_ARRAY_VALUE = Arrays.asList(DATE_VALUE, null); + private static final String FLOAT64_ARRAY_COL = "FLOAT64_ARRAY"; + private static final List FLOAT64_ARRAY_VALUE = Arrays.asList(DOUBLE_VALUE, null); + private static final String INT64_ARRAY_COL = "INT64_ARRAY"; + private static final List INT64_ARRAY_VALUE = Arrays.asList(LONG_VALUE, null); + private static final String NUMERIC_ARRAY_COL = "NUMERIC_ARRAY"; + private static final List NUMERIC_ARRAY_VALUE = Arrays.asList(NUMERIC_VALUE, null); + private static final String STRING_ARRAY_COL = "STRING_ARRAY"; + private static final List STRING_ARRAY_VALUE = Arrays.asList(STRING_VALUE, null); + private static final String TIMESTAMP_ARRAY_COL = "TIMESTAMP_ARRAY"; + private static final List TIMESTAMP_ARRAY_VALUE = Arrays.asList(TIMESTAMP_VALUE, null); private JdbcResultSet subject; @@ -154,7 +178,17 @@ static ResultSet getMockResultSet() { StructField.of(STRING_COL_NUMBER, Type.string()), StructField.of(STRING_COL_DATE, Type.string()), StructField.of(STRING_COL_TIMESTAMP, Type.string()), - StructField.of(STRING_COL_TIME, Type.string())), + StructField.of(STRING_COL_TIME, Type.string()), + StructField.of(NUMERIC_COL_NULL, Type.numeric()), + StructField.of(NUMERIC_COL_NOT_NULL, Type.numeric()), + StructField.of(BOOL_ARRAY_COL, Type.array(Type.bool())), + StructField.of(BYTES_ARRAY_COL, Type.array(Type.bytes())), + StructField.of(DATE_ARRAY_COL, Type.array(Type.date())), + StructField.of(FLOAT64_ARRAY_COL, Type.array(Type.float64())), + StructField.of(INT64_ARRAY_COL, Type.array(Type.int64())), + StructField.of(NUMERIC_ARRAY_COL, Type.array(Type.numeric())), + StructField.of(STRING_ARRAY_COL, Type.array(Type.string())), + StructField.of(TIMESTAMP_ARRAY_COL, Type.array(Type.timestamp()))), Arrays.asList( Struct.newBuilder() .set(STRING_COL_NULL) @@ -205,6 +239,26 @@ static ResultSet getMockResultSet() { .to(STRING_TIMESTAMP_VALUE) .set(STRING_COL_TIME) .to(STRING_TIME_VALUE) + .set(NUMERIC_COL_NULL) + .to((BigDecimal) null) + .set(NUMERIC_COL_NOT_NULL) + .to(NUMERIC_VALUE) + .set(BOOL_ARRAY_COL) + .toBoolArray(BOOL_ARRAY_VALUE) + .set(BYTES_ARRAY_COL) + .toBytesArray(BYTES_ARRAY_VALUE) + .set(DATE_ARRAY_COL) + .toDateArray(DATE_ARRAY_VALUE) + .set(FLOAT64_ARRAY_COL) + .toFloat64Array(FLOAT64_ARRAY_VALUE) + .set(INT64_ARRAY_COL) + .toInt64Array(INT64_ARRAY_VALUE) + .set(NUMERIC_ARRAY_COL) + .toNumericArray(NUMERIC_ARRAY_VALUE) + .set(STRING_ARRAY_COL) + .toStringArray(STRING_ARRAY_VALUE) + .set(TIMESTAMP_ARRAY_COL) + .toTimestampArray(TIMESTAMP_ARRAY_VALUE) .build())); } @@ -835,7 +889,7 @@ public void testFindColumn() throws SQLException { } @Test - public void testGetBigDecimalIndex() throws SQLException { + public void testGetBigDecimalFromDouble_usingIndex() throws SQLException { assertNotNull(subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL)); assertEquals(BigDecimal.valueOf(DOUBLE_VALUE), subject.getBigDecimal(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); @@ -844,7 +898,7 @@ public void testGetBigDecimalIndex() throws SQLException { } @Test - public void testGetBigDecimalLabel() throws SQLException { + public void testGetBigDecimalFromDouble_usingLabel() throws SQLException { assertNotNull(subject.getBigDecimal(DOUBLE_COL_NOT_NULL)); assertEquals(BigDecimal.valueOf(DOUBLE_VALUE), subject.getBigDecimal(DOUBLE_COL_NOT_NULL)); assertFalse(subject.wasNull()); @@ -852,6 +906,24 @@ public void testGetBigDecimalLabel() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetBigDecimalIndex() throws SQLException { + assertNotNull(subject.getBigDecimal(NUMERIC_COLINDEX_NOTNULL)); + assertEquals(NUMERIC_VALUE, subject.getBigDecimal(NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBigDecimalLabel() throws SQLException { + assertNotNull(subject.getBigDecimal(NUMERIC_COL_NOT_NULL)); + assertEquals(NUMERIC_VALUE, subject.getBigDecimal(NUMERIC_COL_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBigDecimal(NUMERIC_COL_NULL)); + assertTrue(subject.wasNull()); + } + @Test public void testGetStatement() throws SQLException { assertNotNull(subject.getStatement()); @@ -1618,4 +1690,38 @@ public void testGetRowAndIsFirst() throws SQLException { public void testGetHoldability() throws SQLException { assertEquals(java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT, subject.getHoldability()); } + + @Test + public void testGetObjectAsValue() throws SQLException { + assertEquals( + Value.bool(BOOLEAN_VALUE), subject.getObject(BOOLEAN_COLINDEX_NOTNULL, Value.class)); + assertEquals(Value.bytes(BYTES_VALUE), subject.getObject(BYTES_COLINDEX_NOTNULL, Value.class)); + assertEquals(Value.date(DATE_VALUE), subject.getObject(DATE_COLINDEX_NOTNULL, Value.class)); + assertEquals( + Value.float64(DOUBLE_VALUE), subject.getObject(DOUBLE_COLINDEX_NOTNULL, Value.class)); + assertEquals(Value.int64(LONG_VALUE), subject.getObject(LONG_COLINDEX_NOTNULL, Value.class)); + assertEquals( + Value.numeric(NUMERIC_VALUE), subject.getObject(NUMERIC_COLINDEX_NOTNULL, Value.class)); + assertEquals( + Value.string(STRING_VALUE), subject.getObject(STRING_COLINDEX_NOTNULL, Value.class)); + assertEquals( + Value.timestamp(TIMESTAMP_VALUE), + subject.getObject(TIMESTAMP_COLINDEX_NOTNULL, Value.class)); + + assertEquals(Value.boolArray(BOOL_ARRAY_VALUE), subject.getObject(BOOL_ARRAY_COL, Value.class)); + assertEquals( + Value.bytesArray(BYTES_ARRAY_VALUE), subject.getObject(BYTES_ARRAY_COL, Value.class)); + assertEquals(Value.dateArray(DATE_ARRAY_VALUE), subject.getObject(DATE_ARRAY_COL, Value.class)); + assertEquals( + Value.float64Array(FLOAT64_ARRAY_VALUE), subject.getObject(FLOAT64_ARRAY_COL, Value.class)); + assertEquals( + Value.int64Array(INT64_ARRAY_VALUE), subject.getObject(INT64_ARRAY_COL, Value.class)); + assertEquals( + Value.numericArray(NUMERIC_ARRAY_VALUE), subject.getObject(NUMERIC_ARRAY_COL, Value.class)); + assertEquals( + Value.stringArray(STRING_ARRAY_VALUE), subject.getObject(STRING_ARRAY_COL, Value.class)); + assertEquals( + Value.timestampArray(TIMESTAMP_ARRAY_VALUE), + subject.getObject(TIMESTAMP_ARRAY_COL, Value.class)); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 2890ed9ce06d..d52e56025369 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -26,7 +26,9 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; +import com.google.cloud.ByteArray; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; @@ -46,6 +48,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Scanner; @@ -875,6 +878,111 @@ public void test10_MetaData_FromDML() throws SQLException { } } + @Test + public void test11_InsertDataUsingSpannerValue() throws SQLException { + try (Connection con = createConnection()) { + try (PreparedStatement ps = + con.prepareStatement( + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + ps.setObject(1, Value.int64(2L)); + ps.setObject(2, Value.float64(2D)); + ps.setObject(3, Value.bool(true)); + ps.setObject(4, Value.string("testvalues")); + ps.setObject(5, Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967")); + ps.setObject(6, Value.bytes(ByteArray.copyFrom("test".getBytes()))); + ps.setObject(7, Value.bytes(ByteArray.copyFrom("testtest".getBytes()))); + ps.setObject(8, Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3))); + ps.setObject( + 9, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99))); + ps.setObject(10, Value.numeric(BigDecimal.TEN)); + ps.setObject(11, Value.int64Array(new long[] {1L, 2L, 3L})); + ps.setObject(12, Value.float64Array(new double[] {1.1D, 2.2D, 3.3D})); + ps.setObject(13, Value.boolArray(Arrays.asList(Boolean.TRUE, null, Boolean.FALSE))); + ps.setObject(14, Value.stringArray(Arrays.asList("1", "2", "3"))); + ps.setObject(15, Value.stringArray(Arrays.asList("3", "2", "1"))); + ps.setObject( + 16, + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("1"), ByteArray.copyFrom("2"), ByteArray.copyFrom("3")))); + ps.setObject( + 17, + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("333"), + ByteArray.copyFrom("222"), + ByteArray.copyFrom("111")))); + ps.setObject( + 18, + Value.dateArray( + Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3), null))); + ps.setObject( + 19, + Value.timestampArray( + Arrays.asList(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99), null))); + ps.setObject(20, Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN))); + assertEquals(1, ps.executeUpdate()); + } + try (ResultSet rs = + con.createStatement() + .executeQuery("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=2")) { + assertTrue(rs.next()); + assertEquals(Value.int64(2L), rs.getObject(1, Value.class)); + assertEquals(Value.float64(2d), rs.getObject(2, Value.class)); + assertEquals(Value.bool(true), rs.getObject(3, Value.class)); + assertEquals(Value.string("testvalues"), rs.getObject(4, Value.class)); + assertEquals( + Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967"), rs.getObject(5, Value.class)); + assertEquals(Value.bytes(ByteArray.copyFrom("test")), rs.getObject(6, Value.class)); + assertEquals(Value.bytes(ByteArray.copyFrom("testtest")), rs.getObject(7, Value.class)); + assertEquals( + Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3)), + rs.getObject(8, Value.class)); + assertEquals( + Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99)), + rs.getObject(9, Value.class)); + assertNotNull(rs.getObject(10, Value.class)); // Commit timestamp + assertEquals(Value.numeric(BigDecimal.TEN), rs.getObject(11, Value.class)); + assertEquals(Value.int64Array(new long[] {1L, 2L, 3L}), rs.getObject(12, Value.class)); + assertEquals( + Value.float64Array(new double[] {1.1D, 2.2D, 3.3D}), rs.getObject(13, Value.class)); + assertEquals( + Value.boolArray(Arrays.asList(true, null, false)), rs.getObject(14, Value.class)); + assertEquals( + Value.stringArray(Arrays.asList("1", "2", "3")), rs.getObject(15, Value.class)); + assertEquals( + Value.stringArray(Arrays.asList("3", "2", "1")), rs.getObject(16, Value.class)); + assertEquals( + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("1"), ByteArray.copyFrom("2"), ByteArray.copyFrom("3"))), + rs.getObject(17, Value.class)); + assertEquals( + Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("333"), + ByteArray.copyFrom("222"), + ByteArray.copyFrom("111"))), + rs.getObject(18, Value.class)); + assertEquals( + Value.dateArray( + Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3), null)), + rs.getObject(19, Value.class)); + assertEquals( + Value.timestampArray( + Arrays.asList(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99), null)), + rs.getObject(20, Value.class)); + assertEquals( + Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN)), + rs.getObject(21, Value.class)); + assertFalse(rs.next()); + } + } + } + private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) throws SQLException { assertEquals(expectedParamCount, pmd.getParameterCount()); From 0e098c68d5b3c3e6164ea7fd3c827ebd03ceb0f5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 May 2021 00:59:01 +0200 Subject: [PATCH 0390/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.1.2 (#451) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a64cd171e91b..b6ced97a22fc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -370,7 +370,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.1.1 + 3.1.2 From d8f0408d3bfdbda84380991dc4d8682df93c7a48 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 May 2021 00:59:25 +0200 Subject: [PATCH 0391/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 (#453) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b6ced97a22fc..00537dfc06f1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.3.3 + 6.4.0 pom import From 8b902626525a7668edde95b28fac2bc16298d565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 7 May 2021 00:59:57 +0200 Subject: [PATCH 0392/1979] chore: remove unused statements file (#458) The ClientSideStatements.json file has been moved to the Connection API in the client library and is not needed in the JDBC driver. --- .../spanner/jdbc/ClientSideStatements.json | 268 ------------------ 1 file changed, 268 deletions(-) delete mode 100644 java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json deleted file mode 100644 index 8d8cca207dc9..000000000000 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/ClientSideStatements.json +++ /dev/null @@ -1,268 +0,0 @@ -{ -"statements": - [ - { - "name": "SHOW VARIABLE AUTOCOMMIT", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+autocommit\\s*\\z", - "method": "statementShowAutocommit", - "exampleStatements": ["show variable autocommit"] - }, - { - "name": "SHOW VARIABLE READONLY", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+readonly\\s*\\z", - "method": "statementShowReadOnly", - "exampleStatements": ["show variable readonly"] - }, - { - "name": "SHOW VARIABLE RETRY_ABORTS_INTERNALLY", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+retry_aborts_internally\\s*\\z", - "method": "statementShowRetryAbortsInternally", - "exampleStatements": ["show variable retry_aborts_internally"], - "examplePrerequisiteStatements": ["set readonly=false", "set autocommit=false"] - }, - { - "name": "SHOW VARIABLE AUTOCOMMIT_DML_MODE", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+autocommit_dml_mode\\s*\\z", - "method": "statementShowAutocommitDmlMode", - "exampleStatements": ["show variable autocommit_dml_mode"] - }, - { - "name": "SHOW VARIABLE STATEMENT_TIMEOUT", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+statement_timeout\\s*\\z", - "method": "statementShowStatementTimeout", - "exampleStatements": ["show variable statement_timeout"] - }, - { - "name": "SHOW VARIABLE READ_TIMESTAMP", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+read_timestamp\\s*\\z", - "method": "statementShowReadTimestamp", - "exampleStatements": ["show variable read_timestamp"], - "examplePrerequisiteStatements": ["set readonly = true", "SELECT 1 AS TEST"] - }, - { - "name": "SHOW VARIABLE COMMIT_TIMESTAMP", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+commit_timestamp\\s*\\z", - "method": "statementShowCommitTimestamp", - "exampleStatements": ["show variable commit_timestamp"], - "examplePrerequisiteStatements": ["update foo set bar=1"] - }, - { - "name": "SHOW VARIABLE READ_ONLY_STALENESS", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+read_only_staleness\\s*\\z", - "method": "statementShowReadOnlyStaleness", - "exampleStatements": ["show variable read_only_staleness"] - }, - { - "name": "SHOW VARIABLE OPTIMIZER_VERSION", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "RESULT_SET", - "regex": "(?is)\\A\\s*show\\s+variable\\s+optimizer_version\\s*\\z", - "method": "statementShowOptimizerVersion", - "exampleStatements": ["show variable optimizer_version"] - }, - { - "name": "BEGIN TRANSACTION", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:begin|start)(?:\\s+transaction)?\\s*\\z", - "method": "statementBeginTransaction", - "exampleStatements": ["begin", "start", "begin transaction", "start transaction"] - }, - { - "name": "COMMIT TRANSACTION", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:commit)(?:\\s+transaction)?\\s*\\z", - "method": "statementCommit", - "exampleStatements": ["commit", "commit transaction"], - "examplePrerequisiteStatements": ["begin transaction"] - }, - { - "name": "ROLLBACK TRANSACTION", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:rollback)(?:\\s+transaction)?\\s*\\z", - "method": "statementRollback", - "exampleStatements": ["rollback", "rollback transaction"], - "examplePrerequisiteStatements": ["begin transaction"] - }, - { - "name": "START BATCH DDL", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:start)(?:\\s+batch)(?:\\s+ddl)\\s*\\z", - "method": "statementStartBatchDdl", - "exampleStatements": ["start batch ddl"] - }, - { - "name": "START BATCH DML", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:start)(?:\\s+batch)(?:\\s+dml)\\s*\\z", - "method": "statementStartBatchDml", - "exampleStatements": ["start batch dml"] - }, - { - "name": "RUN BATCH", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:run)(?:\\s+batch)\\s*\\z", - "method": "statementRunBatch", - "exampleStatements": ["run batch"], - "examplePrerequisiteStatements": ["start batch ddl"] - }, - { - "name": "ABORT BATCH", - "executorName": "ClientSideStatementNoParamExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*(?:abort)(?:\\s+batch)\\s*\\z", - "method": "statementAbortBatch", - "exampleStatements": ["abort batch"], - "examplePrerequisiteStatements": ["start batch ddl"] - }, - { - "name": "SET AUTOCOMMIT = TRUE|FALSE", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+autocommit\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetAutocommit", - "exampleStatements": ["set autocommit = true", "set autocommit = false"], - "setStatement": { - "propertyName": "AUTOCOMMIT", - "separator": "=", - "allowedValues": "(TRUE|FALSE)", - "converterName": "ClientSideStatementValueConverters$BooleanConverter" - } - }, - { - "name": "SET READONLY = TRUE|FALSE", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+readonly\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetReadOnly", - "exampleStatements": ["set readonly = true", "set readonly = false"], - "setStatement": { - "propertyName": "READONLY", - "separator": "=", - "allowedValues": "(TRUE|FALSE)", - "converterName": "ClientSideStatementValueConverters$BooleanConverter" - } - }, - { - "name": "SET RETRY_ABORTS_INTERNALLY = TRUE|FALSE", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+retry_aborts_internally\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetRetryAbortsInternally", - "exampleStatements": ["set retry_aborts_internally = true", "set retry_aborts_internally = false"], - "examplePrerequisiteStatements": ["set readonly = false", "set autocommit = false"], - "setStatement": { - "propertyName": "RETRY_ABORTS_INTERNALLY", - "separator": "=", - "allowedValues": "(TRUE|FALSE)", - "converterName": "ClientSideStatementValueConverters$BooleanConverter" - } - }, - { - "name": "SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+autocommit_dml_mode\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetAutocommitDmlMode", - "exampleStatements": ["set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'", "set autocommit_dml_mode='TRANSACTIONAL'"], - "setStatement": { - "propertyName": "AUTOCOMMIT_DML_MODE", - "separator": "=", - "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL)'", - "converterName": "ClientSideStatementValueConverters$AutocommitDmlModeConverter" - } - }, - { - "name": "SET STATEMENT_TIMEOUT = ''|NULL", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+statement_timeout\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetStatementTimeout", - "exampleStatements": ["set statement_timeout=null", "set statement_timeout='1s'", "set statement_timeout='100ms'", "set statement_timeout='10000us'", "set statement_timeout='9223372036854775807ns'"], - "setStatement": { - "propertyName": "STATEMENT_TIMEOUT", - "separator": "=", - "allowedValues": "('(\\d{1,19})(s|ms|us|ns)'|NULL)", - "converterName": "ClientSideStatementValueConverters$DurationConverter" - } - }, - { - "name": "SET TRANSACTION READ ONLY|READ WRITE", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+transaction\\s*(?:\\s+)\\s*(.*)\\z", - "method": "statementSetTransactionMode", - "exampleStatements": ["set transaction read only", "set transaction read write"], - "examplePrerequisiteStatements": ["set autocommit = false"], - "setStatement": { - "propertyName": "TRANSACTION", - "separator": "\\s+", - "allowedValues": "(READ\\s+ONLY|READ\\s+WRITE)", - "converterName": "ClientSideStatementValueConverters$TransactionModeConverter" - } - }, - { - "name": "SET READ_ONLY_STALENESS = 'STRONG' | 'MIN_READ_TIMESTAMP ' | 'READ_TIMESTAMP ' | 'MAX_STALENESS s|ms|us|ns' | 'EXACT_STALENESS (s|ms|us|ns)'", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+read_only_staleness\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetReadOnlyStaleness", - "exampleStatements": ["set read_only_staleness='STRONG'", - "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123-08:00'", - "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123Z'", - "set read_only_staleness='MIN_READ_TIMESTAMP 2018-01-02T03:04:05.123+07:45'", - "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321-07:00'", - "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321Z'", - "set read_only_staleness='READ_TIMESTAMP 2018-01-02T03:04:05.54321+05:30'", - "set read_only_staleness='MAX_STALENESS 12s'", - "set read_only_staleness='MAX_STALENESS 100ms'", - "set read_only_staleness='MAX_STALENESS 99999us'", - "set read_only_staleness='MAX_STALENESS 10ns'", - "set read_only_staleness='EXACT_STALENESS 15s'", - "set read_only_staleness='EXACT_STALENESS 1500ms'", - "set read_only_staleness='EXACT_STALENESS 15000000us'", - "set read_only_staleness='EXACT_STALENESS 9999ns'"], - "setStatement": { - "propertyName": "READ_ONLY_STALENESS", - "separator": "=", - "allowedValues": "'((STRONG)|(MIN_READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(READ_TIMESTAMP)[\\t ]+((\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)([Zz]|([+-])(\\d{2}):(\\d{2})))|(MAX_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns))|(EXACT_STALENESS)[\\t ]+((\\d{1,19})(s|ms|us|ns)))'", - "converterName": "ClientSideStatementValueConverters$ReadOnlyStalenessConverter" - } - }, - { - "name": "SET OPTIMIZER_VERSION = ''|'LATEST'|''", - "executorName": "ClientSideStatementSetExecutor", - "resultType": "NO_RESULT", - "regex": "(?is)\\A\\s*set\\s+optimizer_version\\s*(?:=)\\s*(.*)\\z", - "method": "statementSetOptimizerVersion", - "exampleStatements": ["set optimizer_version='1'", "set optimizer_version='200'", "set optimizer_version='LATEST'", "set optimizer_version=''"], - "setStatement": { - "propertyName": "OPTIMIZER_VERSION", - "separator": "=", - "allowedValues": "'((\\d{1,20})|(LATEST)|())'", - "converterName": "ClientSideStatementValueConverters$StringValueConverter" - } - } - ] -} \ No newline at end of file From b3c2d73784bf848de52c0405cdb8b800863edafd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 07:00:18 +0200 Subject: [PATCH 0393/1979] chore: release 2.0.3-SNAPSHOT (#442) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 00537dfc06f1..b78a835a237a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.2 + 2.0.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 30d747066b0e..613c0a6b2290 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.2 + 2.0.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7710d28ba4db..68a245afb5db 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.2:2.0.2 +google-cloud-spanner-jdbc:2.0.2:2.0.3-SNAPSHOT From f6134fc269f8b76af9d75017c537ce5a1cfce776 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 7 May 2021 09:08:47 -0700 Subject: [PATCH 0394/1979] chore: adding cloud-rad java xrefs (#461) Source-Author: Emily Ball Source-Date: Thu May 6 11:48:47 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 046994f491c02806aea60118e214a9edd67f5ab7 Source-Link: https://github.com/googleapis/synthtool/commit/046994f491c02806aea60118e214a9edd67f5ab7 --- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 7 +++++++ java-spanner-jdbc/synth.metadata | 7 ++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 164c473614ba..26d1f17d7647 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -49,6 +49,13 @@ pushd target/docfx-yml python3 -m docuploader create-metadata \ --name ${NAME} \ --version ${VERSION} \ + --xrefs devsite://java/gax \ + --xrefs devsite://java/google-cloud-core \ + --xrefs devsite://java/api-common \ + --xrefs devsite://java/proto-google-common-protos \ + --xrefs devsite://java/google-api-client \ + --xrefs devsite://java/google-http-client \ + --xrefs devsite://java/protobuf \ --language java # upload yml to production bucket diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 203fa091c833..b83354b3006c 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "212d9d05c4f28ade71ab5484792188b11a5bcd8b" + "sha": "a657035b74e24e9fdfa12f91e5edf3c3e9b215ff" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8285c2b4cdbc3771d031ad91e1c4ec9e55fff45d" + "sha": "046994f491c02806aea60118e214a9edd67f5ab7" } } ], @@ -21,12 +21,9 @@ ".github/ISSUE_TEMPLATE/feature_request.md", ".github/ISSUE_TEMPLATE/support_request.md", ".github/PULL_REQUEST_TEMPLATE.md", - ".github/blunderbuss.yml", ".github/generated-files-bot.yml", ".github/readme/synth.py", - ".github/release-please.yml", ".github/snippet-bot.yml", - ".github/sync-repo-settings.yaml", ".github/trusted-contribution.yml", ".github/workflows/approve-readme.yaml", ".github/workflows/auto-release.yaml", From 4df44bce220796915205b912b620961caee6ecbd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 11 May 2021 03:22:15 +0200 Subject: [PATCH 0395/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 (#463) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `1.0.0` -> `1.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/compatibility-slim/1.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/confidence-slim/1.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v1.1.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​110-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare100v110-2021-05-10) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.0.0...v1.1.0) ##### Dependencies - update dependency com.google.protobuf:protobuf-bom to v3.16.0 ([#​348](https://www.github.com/googleapis/java-shared-dependencies/issues/348)) ([0aacfde](https://www.github.com/googleapis/java-shared-dependencies/commit/0aacfdeec70e30803734db8287c47e4fad5481ef)) - update gax.version to v1.64.0 ([#​345](https://www.github.com/googleapis/java-shared-dependencies/issues/345)) ([478bd35](https://www.github.com/googleapis/java-shared-dependencies/commit/478bd35296293e81c7e70157f50bfbebdc1bb54d)) - update iam.version to v1.0.13 ([#​343](https://www.github.com/googleapis/java-shared-dependencies/issues/343)) ([3637923](https://www.github.com/googleapis/java-shared-dependencies/commit/363792392b71deff5cc5731104b631122fba5e61))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b78a835a237a..c7aba4e4ef52 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 1.0.0 + 1.1.0 pom import From fd78d3665e6467c28dde528877f3a797c6ca6a51 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 13 May 2021 15:56:34 +0200 Subject: [PATCH 0396/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.3.0 (#462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.2.0` -> `20.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/compatibility-slim/20.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/confidence-slim/20.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2d909936cfe3..cfcdaccb55cc 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.2.0 + 20.3.0 pom import From 660ea5d49f3fc2595df80c918c26c0941adac852 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 13 May 2021 16:38:04 -0700 Subject: [PATCH 0397/1979] build(java): remove codecov action (#465) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/8e8c0070-26ea-4d86-b07a-e4dcc9e5b8b1/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/4f4b1b9b8d8b52f1e9e4a76165896debce5ab7f1 --- java-spanner-jdbc/.github/workflows/ci.yaml | 6 +----- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 29d933b045e4..65ae6ecdda77 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -19,10 +19,6 @@ jobs: - run: .kokoro/build.sh env: JOB_TYPE: test - - name: coverage - uses: codecov/codecov-action@v1 - with: - name: actions ${{matrix.java}} windows: runs-on: windows-latest steps: @@ -80,4 +76,4 @@ jobs: - run: java -version - run: .kokoro/build.sh env: - JOB_TYPE: clirr \ No newline at end of file + JOB_TYPE: clirr diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index b83354b3006c..2305e47001aa 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a657035b74e24e9fdfa12f91e5edf3c3e9b215ff" + "sha": "7fbd143dbcd7507a4e5b0e397646b89cf033d1af" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "046994f491c02806aea60118e214a9edd67f5ab7" + "sha": "4f4b1b9b8d8b52f1e9e4a76165896debce5ab7f1" } } ], From d16e126717a2e0af2670695301d3e2190f0331bf Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 17 May 2021 03:46:22 +0200 Subject: [PATCH 0398/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.4.0 (#466) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.3.0` -> `20.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/compatibility-slim/20.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/confidence-slim/20.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index cfcdaccb55cc..505f9cbd7e84 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.3.0 + 20.4.0 pom import From 4d18149c6baa37fb3a1c5034dff65c41b68364bf Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 17 May 2021 15:20:12 -0700 Subject: [PATCH 0399/1979] chore: add changelog to cloud-rad (#467) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/41862329-45d0-4225-9ed2-ad5a75997ae8/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/c86c7a60985644eab557949363a38301d40d78d2 --- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 2 ++ java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 26d1f17d7647..38ee2e5c8ec8 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -42,6 +42,8 @@ mvn clean site -B -q -P docFX # copy README to docfx-yml dir and rename index.md cp README.md target/docfx-yml/index.md +# copy CHANGELOG to docfx-yml dir and rename history.md +cp CHANGELOG.md target/docfx-yml/history.md pushd target/docfx-yml diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 2305e47001aa..b398ba938087 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "7fbd143dbcd7507a4e5b0e397646b89cf033d1af" + "sha": "c42f7f7014cc24c32012aca8d2aa324c7cbc6e37" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "4f4b1b9b8d8b52f1e9e4a76165896debce5ab7f1" + "sha": "c86c7a60985644eab557949363a38301d40d78d2" } } ], From 6362ff4a5e59bfe301d8ba7bdf364e274afd13eb Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Tue, 18 May 2021 11:37:52 +1000 Subject: [PATCH 0400/1979] tests: fixes jdbc query options test (#468) * tests: fixes jdbc query options test This test was failing, because we were no longer recreating the jdbc connection from scratch. One of the tests, set an environment variable specifying the optimizer version, which was permanently applied, since the connection was not re-created. Here we make sure to start / stop the static server before each test. * chore: fixes linting errors --- .../cloud/spanner/jdbc/JdbcQueryOptionsTest.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index f628e17ee150..d26aba592811 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -26,12 +26,19 @@ import com.google.spanner.v1.ExecuteSqlRequest; import java.sql.DriverManager; import java.sql.SQLException; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JdbcQueryOptionsTest extends AbstractMockServerTest { + @Before + public void setup() throws Exception { + stopServer(); + startStaticServer(); + } + @Test public void testDefaultOptimizerVersion() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { @@ -151,13 +158,7 @@ public void testUseOptimizerVersionFromConnectionUrl() throws SQLException { @Test public void testUseOptimizerVersionFromEnvironment() throws SQLException { try { - SpannerOptions.useEnvironment( - new SpannerOptions.SpannerEnvironment() { - @Override - public String getOptimizerVersion() { - return "20"; - } - }); + SpannerOptions.useEnvironment(() -> "20"); try (java.sql.Connection connection = DriverManager.getConnection(String.format("jdbc:%s", getBaseUrl()))) { // Do a query and verify that the version from the environment is used. From 0f749febadc263f85cf3df81fe4aa802d1799fd2 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Tue, 18 May 2021 14:10:04 +1000 Subject: [PATCH 0401/1979] tests: fixes sql script test (#469) In version 6.4.4 of spanner we have change the verifyStatementsInFile method to wrap any SQLExceptions into SpannerExceptions. In the failing tests we were catching SQLExceptions and ignoring them, since they were expected. We have changed the tests to also ignore the respective SpannerExceptions. --- .../cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index 8fc331bb5300..5133fc4d38d2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -23,6 +23,7 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; @@ -93,6 +94,11 @@ public void test02_InsertTestData() throws Exception { // Ignore, this is expected as errors during a read/write transaction are sticky on the // emulator. } + } catch (SpannerException e) { + if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) { + // Ignore, this is expected as errors during a read/write transaction are sticky on the + // emulator. + } } } @@ -114,6 +120,11 @@ public void test04_TestGetCommitTimestamp() throws Exception { && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()) { // Ignore as errors during read/write transactions are sticky on the emulator. } + } catch (SpannerException e) { + if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) { + // Ignore, this is expected as errors during a read/write transaction are sticky on the + // emulator. + } } } From b64fbaa814f745e9a91a53e17b2af42f0dd44a7c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 May 2021 06:26:10 +0200 Subject: [PATCH 0402/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 (#464) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c7aba4e4ef52..35bac01e7156 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.4.0 + 6.4.4 pom import From bbf2ea1141e1abdbe7d9fe0ac5e619c42c1014cd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 18 May 2021 15:24:07 +0000 Subject: [PATCH 0403/1979] chore: release 2.1.0 (#460) :robot: I have created a release \*beep\* \*boop\* --- ## [2.1.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.2...v2.1.0) (2021-05-18) ### Features * allow get/set Spanner Value instances ([#454](https://www.github.com/googleapis/java-spanner-jdbc/issues/454)) ([c9df35d](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9df35d49065f552ff782a1169388b1ad4dd122c)), closes [#452](https://www.github.com/googleapis/java-spanner-jdbc/issues/452) ### Bug Fixes * NPE was thrown when getting an array of structs from a ResultSet ([#445](https://www.github.com/googleapis/java-spanner-jdbc/issues/445)) ([93dd183](https://www.github.com/googleapis/java-spanner-jdbc/commit/93dd183ec4d567736ff55ffc25ca5f83ba467fb3)), closes [#444](https://www.github.com/googleapis/java-spanner-jdbc/issues/444) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 ([#463](https://www.github.com/googleapis/java-spanner-jdbc/issues/463)) ([4df44bc](https://www.github.com/googleapis/java-spanner-jdbc/commit/4df44bce220796915205b912b620961caee6ecbd)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 ([#453](https://www.github.com/googleapis/java-spanner-jdbc/issues/453)) ([d8f0408](https://www.github.com/googleapis/java-spanner-jdbc/commit/d8f0408d3bfdbda84380991dc4d8682df93c7a48)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 ([#464](https://www.github.com/googleapis/java-spanner-jdbc/issues/464)) ([b64fbaa](https://www.github.com/googleapis/java-spanner-jdbc/commit/b64fbaa814f745e9a91a53e17b2af42f0dd44a7c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 19 +++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1acc5b01e3ad..1f79ceedd6ab 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [2.1.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.2...v2.1.0) (2021-05-18) + + +### Features + +* allow get/set Spanner Value instances ([#454](https://www.github.com/googleapis/java-spanner-jdbc/issues/454)) ([d6935b8](https://www.github.com/googleapis/java-spanner-jdbc/commit/d6935b863349c58cfdd44d6ce20dba6f5dbc1472)), closes [#452](https://www.github.com/googleapis/java-spanner-jdbc/issues/452) + + +### Bug Fixes + +* NPE was thrown when getting an array of structs from a ResultSet ([#445](https://www.github.com/googleapis/java-spanner-jdbc/issues/445)) ([1dfb37b](https://www.github.com/googleapis/java-spanner-jdbc/commit/1dfb37b27ee661718fe80be0bf260c40f4b15582)), closes [#444](https://www.github.com/googleapis/java-spanner-jdbc/issues/444) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 ([#463](https://www.github.com/googleapis/java-spanner-jdbc/issues/463)) ([f148c71](https://www.github.com/googleapis/java-spanner-jdbc/commit/f148c71bef2b762d7b4475ba7f28443c7938c394)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 ([#453](https://www.github.com/googleapis/java-spanner-jdbc/issues/453)) ([7dac8b3](https://www.github.com/googleapis/java-spanner-jdbc/commit/7dac8b3e43625aa28be214bd735fc3386770de04)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 ([#464](https://www.github.com/googleapis/java-spanner-jdbc/issues/464)) ([eeb31c0](https://www.github.com/googleapis/java-spanner-jdbc/commit/eeb31c050fda116203d9da5c4a80c7f1c6a6cac4)) + ### [2.0.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.1...v2.0.2) (2021-04-26) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 35bac01e7156..7644e1f9f6b8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0.3-SNAPSHOT + 2.1.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 613c0a6b2290..159d4c9a85bb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.3-SNAPSHOT + 2.1.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 68a245afb5db..cde0aa334999 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.0.2:2.0.3-SNAPSHOT +google-cloud-spanner-jdbc:2.1.0:2.1.0 From 7b9bf2a24eb08169afb99bee49f2e28ffb39d6b8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 18 May 2021 19:32:08 +0000 Subject: [PATCH 0404/1979] chore: release 2.1.1-SNAPSHOT (#470) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7644e1f9f6b8..a30617503ed1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.1.0 + 2.1.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 159d4c9a85bb..08ed0eaedb3c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index cde0aa334999..a41b9cd6c29b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.1.0:2.1.0 +google-cloud-spanner-jdbc:2.1.0:2.1.1-SNAPSHOT From 3be64022d78f2db0afae5392967cba6ee196b0e7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 May 2021 21:46:07 +0200 Subject: [PATCH 0405/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.1.0 (#471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.0.2` -> `2.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/compatibility-slim/2.0.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/confidence-slim/2.0.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.1.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​210-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev202v210-2021-05-18) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.0.2...v2.1.0) ##### Features - allow get/set Spanner Value instances ([#​454](https://www.github.com/googleapis/java-spanner-jdbc/issues/454)) ([c9df35d](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9df35d49065f552ff782a1169388b1ad4dd122c)), closes [#​452](https://www.github.com/googleapis/java-spanner-jdbc/issues/452) ##### Bug Fixes - NPE was thrown when getting an array of structs from a ResultSet ([#​445](https://www.github.com/googleapis/java-spanner-jdbc/issues/445)) ([93dd183](https://www.github.com/googleapis/java-spanner-jdbc/commit/93dd183ec4d567736ff55ffc25ca5f83ba467fb3)), closes [#​444](https://www.github.com/googleapis/java-spanner-jdbc/issues/444) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 ([#​463](https://www.github.com/googleapis/java-spanner-jdbc/issues/463)) ([4df44bc](https://www.github.com/googleapis/java-spanner-jdbc/commit/4df44bce220796915205b912b620961caee6ecbd)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 ([#​453](https://www.github.com/googleapis/java-spanner-jdbc/issues/453)) ([d8f0408](https://www.github.com/googleapis/java-spanner-jdbc/commit/d8f0408d3bfdbda84380991dc4d8682df93c7a48)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 ([#​464](https://www.github.com/googleapis/java-spanner-jdbc/issues/464)) ([b64fbaa](https://www.github.com/googleapis/java-spanner-jdbc/commit/b64fbaa814f745e9a91a53e17b2af42f0dd44a7c)) ##### [2.0.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.1...v2.0.2) (2021-04-26) ##### Bug Fixes - release scripts from issuing overlapping phases ([#​434](https://www.github.com/googleapis/java-spanner-jdbc/issues/434)) ([41c85a2](https://www.github.com/googleapis/java-spanner-jdbc/commit/41c85a21256375664ce837d3531131f02806bd99)) - typo ([#​431](https://www.github.com/googleapis/java-spanner-jdbc/issues/431)) ([6b74d16](https://www.github.com/googleapis/java-spanner-jdbc/commit/6b74d1680f24cacc33e11267d87f231f978b2827)) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.1 ([#​438](https://www.github.com/googleapis/java-spanner-jdbc/issues/438)) ([48e3d05](https://www.github.com/googleapis/java-spanner-jdbc/commit/48e3d05e3a83af63334f3e935984991b6d3fa0a7)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v1 ([#​441](https://www.github.com/googleapis/java-spanner-jdbc/issues/441)) ([9bbad0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/9bbad0cee0cb5e44892b6cef9d5bd5b36c829361)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.1 ([#​430](https://www.github.com/googleapis/java-spanner-jdbc/issues/430)) ([0157bcb](https://www.github.com/googleapis/java-spanner-jdbc/commit/0157bcbcbed8c47917b4006c3c8a2c07a6187c04)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.3.3 ([#​439](https://www.github.com/googleapis/java-spanner-jdbc/issues/439)) ([13c3783](https://www.github.com/googleapis/java-spanner-jdbc/commit/13c37836d9adaa4596e41609cf4e54da371d6eea)) ##### [2.0.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.0...v2.0.1) (2021-04-13) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.0 ([#​423](https://www.github.com/googleapis/java-spanner-jdbc/issues/423)) ([46b5494](https://www.github.com/googleapis/java-spanner-jdbc/commit/46b5494269893b73893c67609fd488c13431c1ef)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.0 ([#​420](https://www.github.com/googleapis/java-spanner-jdbc/issues/420)) ([5fd565a](https://www.github.com/googleapis/java-spanner-jdbc/commit/5fd565a0c014dfa98577f1df51c33a2ebc1c713b))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e6a32e36e2e9..e19a884b2759 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.0.2 + 2.1.0 From 5f9ed96272c818f07d9eb384f283f7e9c032a6ca Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 19 May 2021 07:18:03 -0700 Subject: [PATCH 0406/1979] feat: add `gcf-owl-bot[bot]` to `ignoreAuthors` (#474) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/35db7954-f063-42f8-9ff3-5d189e94e5d3/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/7332178a11ddddc91188dc0f25bca1ccadcaa6c6 --- java-spanner-jdbc/.github/generated-files-bot.yml | 1 + java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/generated-files-bot.yml b/java-spanner-jdbc/.github/generated-files-bot.yml index 47c2ba132e01..c644a24e1129 100644 --- a/java-spanner-jdbc/.github/generated-files-bot.yml +++ b/java-spanner-jdbc/.github/generated-files-bot.yml @@ -9,3 +9,4 @@ ignoreAuthors: - 'renovate-bot' - 'yoshi-automation' - 'release-please[bot]' +- 'gcf-owl-bot[bot]' diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index b398ba938087..fbc55284bfc4 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "c42f7f7014cc24c32012aca8d2aa324c7cbc6e37" + "sha": "8a6a8529e0f832b21c07ec40adb448bd77c5b02c" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c86c7a60985644eab557949363a38301d40d78d2" + "sha": "7332178a11ddddc91188dc0f25bca1ccadcaa6c6" } } ], From 2d3097a65237eb0425ba3d2b52f594335190975c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 19 May 2021 17:14:05 +0200 Subject: [PATCH 0407/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 (#473) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `1.1.0` -> `1.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/compatibility-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/confidence-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v1.2.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​120-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare110v120-2021-05-18) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.1.0...v1.2.0) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.31.5 ([#​353](https://www.github.com/googleapis/java-shared-dependencies/issues/353)) ([8d72ab0](https://www.github.com/googleapis/java-shared-dependencies/commit/8d72ab003e08c864aedc17fc190ba26f393bf0c7)) - update dependency com.google.errorprone:error_prone_annotations to v2.7.1 ([#​360](https://www.github.com/googleapis/java-shared-dependencies/issues/360)) ([8f952d0](https://www.github.com/googleapis/java-shared-dependencies/commit/8f952d05745358fc426a1a2dcb688da5d5010239)) - update dependency com.google.protobuf:protobuf-bom to v3.17.0 ([#​355](https://www.github.com/googleapis/java-shared-dependencies/issues/355)) ([09858fb](https://www.github.com/googleapis/java-shared-dependencies/commit/09858fb4f1b78a77e828501597d20df4db0ebfcf)) - update dependency io.grpc:grpc-bom to v1.37.1 ([#​359](https://www.github.com/googleapis/java-shared-dependencies/issues/359)) ([bc9869e](https://www.github.com/googleapis/java-shared-dependencies/commit/bc9869e914314f951afd69f2acae95c414398f43)) - update google.common-protos.version to v2.2.1 ([#​358](https://www.github.com/googleapis/java-shared-dependencies/issues/358)) ([a3ed764](https://www.github.com/googleapis/java-shared-dependencies/commit/a3ed764a0e5143ee323d4b69c9747b8265d349e2)) - update iam.version to v1.0.14 ([#​352](https://www.github.com/googleapis/java-shared-dependencies/issues/352)) ([bea9a01](https://www.github.com/googleapis/java-shared-dependencies/commit/bea9a01788ac1332a4bc7e06574ef5701700fe90))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a30617503ed1..57adb5279621 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 1.1.0 + 1.2.0 pom import From f25504bf27fe10dd707b6d4a69f3897b2a4da84b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 19 May 2021 09:42:10 -0700 Subject: [PATCH 0408/1979] chore: regenerate README (#472) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-05-18 19:34:16,960 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-05-18 19:34:18,292 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/572b047a-da68-49ed-98fa-b98e7f88514a/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 080e198ec846..3e392b94ef09 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "16b9802d53e640060de608e27aede6dc40310267" + "sha": "ff677e73838f811c0fa9ed1b4ddbc8331dceec74" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "06a8cd0ff7e81b05e6c503eab510ec622384caa7" + "sha": "c86c7a60985644eab557949363a38301d40d78d2" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 2e88e52b811e..0cf417a1c620 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.0.2 + 2.1.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.0.2' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.1.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.0.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.1.0" ``` ## Authentication From 4a7ac821f6cb30d511f495256be4dde7bc61dd88 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 19 May 2021 23:02:18 +0200 Subject: [PATCH 0409/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.12.0 (#476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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) | `0.11.2` -> `0.12.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/compatibility-slim/0.11.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/confidence-slim/0.11.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 57adb5279621..c53d6ce5252a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.11.2 + 0.12.0 From 93cfd5289bdf5c8ba2c593a60990f31312d87894 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 20 May 2021 15:32:32 -0700 Subject: [PATCH 0410/1979] chore: dump maven version along with java (#477) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/9ea9dfcf-fef7-472c-9ebc-755e62e086c4/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/8eae0234a16b26c2ff616d305dbd9786c8b10a47 --- java-spanner-jdbc/.kokoro/build.sh | 4 ++-- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 9eaeef4f20a6..163c8526dd4e 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -23,8 +23,8 @@ cd ${scriptDir}/.. # include common functions source ${scriptDir}/common.sh -# Print out Java version -java -version +# Print out Maven & Java version +mvn -version echo ${JOB_TYPE} # attempt to install 3 times with exponential backoff (starting with 10 seconds) diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index fbc55284bfc4..5186fb26131c 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "8a6a8529e0f832b21c07ec40adb448bd77c5b02c" + "sha": "b7218e5b4408685b3d291c0010a24d7a048b3b0e" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "7332178a11ddddc91188dc0f25bca1ccadcaa6c6" + "sha": "8eae0234a16b26c2ff616d305dbd9786c8b10a47" } } ], From f5bca0cd589b1839f569497f2e7efddef9934174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 24 May 2021 07:35:20 +0200 Subject: [PATCH 0411/1979] docs: document connection properties in README (#478) Adds documentation for the supported connection properties to the README file. Fixes #456 --- java-spanner-jdbc/.readme-partials.yaml | 22 +++++++++++++++ .../google/cloud/spanner/jdbc/JdbcDriver.java | 28 +++++++++++-------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml index 3407400d2e12..6fcc2f61ae2b 100644 --- a/java-spanner-jdbc/.readme-partials.yaml +++ b/java-spanner-jdbc/.readme-partials.yaml @@ -24,6 +24,28 @@ custom_content: | } ``` + ### Connection URL Properties + + The Cloud Spanner JDBC driver supports the following connection URL properties. Note that all of + these can also be supplied in a Properties instance that is passed to the + `DriverManager#getConnection(String url, Properties properties)` method. + + #### Commonly Used Properties + - credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json` + - autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. + - readonly (boolean): Sets the initial readonly mode for the connection. Default is false. + - autoConfigEmulator (boolean): Automatically configure the connection to try to connect to the Cloud Spanner emulator. You do not need to specify any host or port in the connection string as long as the emulator is running on the default host/port (localhost:9010). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. This means that you do not need to execute any `gcloud` commands on the emulator to create the instance and database before you can connect to it. Example: `jdbc:cloudspanner:/projects/test-project/instances/test-instance/databases/test-db;autoConfigEmulator=true` + - usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to a (local) server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. Example: `jdbc:cloudspanner://localhost:9010/projects/test-project/instances/test-instance/databases/test-db;usePlainText=true` + - optimizerVersion (String): Sets the default query optimizer version to use for this connection. See also https://cloud.google.com/spanner/docs/query-optimizer/query-optimizer-versions. + + #### Advanced Properties + - minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. + - maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. + - numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. + - retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. + - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. + - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. + ### Jar with Dependencies A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index dbb2df5ca6bd..08dd5fafe9bf 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -76,14 +76,29 @@ *
  • credentials (String): URL for the credentials file to use for the connection. If you do not * specify any credentials at all, the default credentials of the environment as returned by * {@link GoogleCredentials#getApplicationDefault()} is used. + *
  • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. + *
  • readonly (boolean): Sets the initial readonly mode for the connection. Default is false. + *
  • autoConfigEmulator (boolean): Automatically configure the connection to try to connect to + * the Cloud Spanner emulator. You do not need to specify any host or port in the connection + * string as long as the emulator is running on the default host/port (localhost:9010). The + * instance and database in the connection string will automatically be created if these do + * not yet exist on the emulator. This means that you do not need to execute any `gcloud` + * commands on the emulator to create the instance and database before you can connect to it. + *
  • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted + * connection to the server. This option can only be used when connecting to a local emulator + * that does not require an encrypted connection, and that does not require authentication. + *
  • optimizerVersion (string): The query optimizer version to use for the connection. The value + * must be either a valid version number or LATEST. If no value is specified, the + * query optimizer version specified in the environment variable + * SPANNER_OPTIMIZER_VERSION is used. If no query optimizer version is specified in the + * connection URL or in the environment variable, the default query optimizer version of Cloud + * Spanner is used. *
  • oauthtoken (String): A valid OAuth2 token to use for the JDBC connection. The token must * have been obtained with one or both of the scopes * 'https://www.googleapis.com/auth/spanner.admin' and/or * 'https://www.googleapis.com/auth/spanner.data'. If you specify both a credentials file and * an OAuth token, the JDBC driver will throw an exception when you try to obtain a * connection. - *
  • autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. - *
  • readonly (boolean): Sets the initial readonly mode for the connection. Default is false. *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the * connection. Default is true. @see {@link * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} @@ -93,15 +108,6 @@ *
  • maxSessions (int): Sets the maximum number of sessions in the backing session pool. * Defaults to 400. *
  • numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - *
  • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted - * connection to the server. This option can only be used when connecting to a local emulator - * that does not require an encrypted connection, and that does not require authentication. - *
  • optimizerVersion (string): The query optimizer version to use for the connection. The value - * must be either a valid version number or LATEST. If no value is specified, the - * query optimizer version specified in the environment variable - * SPANNER_OPTIMIZER_VERSION is used. If no query optimizer version is specified in the - * connection URL or in the environment variable, the default query optimizer version of Cloud - * Spanner is used. * */ public class JdbcDriver implements Driver { From 10b4bcf95da3765515447cdcf894052a2bc03b30 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 23 May 2021 22:54:02 -0700 Subject: [PATCH 0412/1979] chore: regenerate README (#481) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-05-24 05:37:24,863 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-05-24 05:37:26,075 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/5da15a47-718f-4374-b505-dead2c234c76/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 3e392b94ef09..49ff805af5d7 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ff677e73838f811c0fa9ed1b4ddbc8331dceec74" + "sha": "3ccc5433bec261b18d2536b04590e7645e47ed9b" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c86c7a60985644eab557949363a38301d40d78d2" + "sha": "bb5ef5a99df6d439c63fddf0f7b6fe58e0679b10" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0cf417a1c620..c5b404ebdc7f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -84,6 +84,28 @@ try (Connection connection = } ``` +### Connection URL Properties + +The Cloud Spanner JDBC driver supports the following connection URL properties. Note that all of +these can also be supplied in a Properties instance that is passed to the +`DriverManager#getConnection(String url, Properties properties)` method. + +#### Commonly Used Properties +- credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json` +- autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. +- readonly (boolean): Sets the initial readonly mode for the connection. Default is false. +- autoConfigEmulator (boolean): Automatically configure the connection to try to connect to the Cloud Spanner emulator. You do not need to specify any host or port in the connection string as long as the emulator is running on the default host/port (localhost:9010). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. This means that you do not need to execute any `gcloud` commands on the emulator to create the instance and database before you can connect to it. Example: `jdbc:cloudspanner:/projects/test-project/instances/test-instance/databases/test-db;autoConfigEmulator=true` +- usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to a (local) server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. Example: `jdbc:cloudspanner://localhost:9010/projects/test-project/instances/test-instance/databases/test-db;usePlainText=true` +- optimizerVersion (String): Sets the default query optimizer version to use for this connection. See also https://cloud.google.com/spanner/docs/query-optimizer/query-optimizer-versions. + +#### Advanced Properties +- minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. +- maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. +- numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. +- retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. +- oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. +- lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. + ### Jar with Dependencies A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). From 41a6fa78a13b52ffc2bf39f69fa51631629b4234 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 25 May 2021 05:04:46 +0200 Subject: [PATCH 0413/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.3.0 (#480) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c53d6ce5252a..d622aace0324 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -397,7 +397,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.3.0 html From 78966887cb391e7ac5eff8758d7de7237d99a742 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 25 May 2021 05:05:06 +0200 Subject: [PATCH 0414/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.5.0 (#482) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 505f9cbd7e84..3eea4b01e7b6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.4.0 + 20.5.0 pom import From af87ed0d50d6c8650c08d5f6f605882dcd8cfbab Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 26 May 2021 05:28:40 +0200 Subject: [PATCH 0415/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 (#483) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d622aace0324..dd89f395ec66 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.4.4 + 6.5.0 pom import From 7cc16d9a8c5bb1a2a66892ca91515cafce30b3f0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 26 May 2021 05:29:02 +0200 Subject: [PATCH 0416/1979] test(deps): update dependency com.google.truth:truth to v1.1.3 (#484) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dd89f395ec66..a47b81a81311 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ 4.13.2 3.0.2 1.4.4 - 1.1.2 + 1.1.3 1.10.19 2.2 From 240c7600266f7b4343dddb4fc47459eadd7a2a6f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 26 May 2021 22:58:06 +0200 Subject: [PATCH 0417/1979] test(deps): update dependency com.google.truth:truth to v1.1.3 (#485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.truth:truth | `1.1.2` -> `1.1.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/compatibility-slim/1.1.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/confidence-slim/1.1.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e19a884b2759..ba86078360ae 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1.2 + 1.1.3 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 08ed0eaedb3c..8c8646f1b739 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1.2 + 1.1.3 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 3eea4b01e7b6..d29022a683f7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.1.2 + 1.1.3 test From 5b4bb7906b3dd6c1cbb96f69cf3fe48ae2e77235 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 21:38:11 +0000 Subject: [PATCH 0418/1979] chore: release 2.2.0 (#475) :robot: I have created a release \*beep\* \*boop\* --- ## [2.2.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.1.0...v2.2.0) (2021-05-26) ### Features * add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#474](https://www.github.com/googleapis/java-spanner-jdbc/issues/474)) ([5f9ed96](https://www.github.com/googleapis/java-spanner-jdbc/commit/5f9ed96272c818f07d9eb384f283f7e9c032a6ca)) ### Documentation * document connection properties in README ([#478](https://www.github.com/googleapis/java-spanner-jdbc/issues/478)) ([f5bca0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/f5bca0cd589b1839f569497f2e7efddef9934174)), closes [#456](https://www.github.com/googleapis/java-spanner-jdbc/issues/456) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 ([#473](https://www.github.com/googleapis/java-spanner-jdbc/issues/473)) ([2d3097a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2d3097a65237eb0425ba3d2b52f594335190975c)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 ([#483](https://www.github.com/googleapis/java-spanner-jdbc/issues/483)) ([af87ed0](https://www.github.com/googleapis/java-spanner-jdbc/commit/af87ed0d50d6c8650c08d5f6f605882dcd8cfbab)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1f79ceedd6ab..0db055e37907 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.2.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.1.0...v2.2.0) (2021-05-26) + + +### Features + +* add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#474](https://www.github.com/googleapis/java-spanner-jdbc/issues/474)) ([c14f17b](https://www.github.com/googleapis/java-spanner-jdbc/commit/c14f17b411b15e778a68ce998de04732b159d7ac)) + + +### Documentation + +* document connection properties in README ([#478](https://www.github.com/googleapis/java-spanner-jdbc/issues/478)) ([3ccc543](https://www.github.com/googleapis/java-spanner-jdbc/commit/3ccc5433bec261b18d2536b04590e7645e47ed9b)), closes [#456](https://www.github.com/googleapis/java-spanner-jdbc/issues/456) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 ([#473](https://www.github.com/googleapis/java-spanner-jdbc/issues/473)) ([a6cc069](https://www.github.com/googleapis/java-spanner-jdbc/commit/a6cc0697ed5916c665f007a1bf16660b8b91f9f9)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 ([#483](https://www.github.com/googleapis/java-spanner-jdbc/issues/483)) ([e7fec30](https://www.github.com/googleapis/java-spanner-jdbc/commit/e7fec30f2f2c5518821d5348d448f102301d65c3)) + ## [2.1.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.0.2...v2.1.0) (2021-05-18) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a47b81a81311..d8601ee391cf 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.1.1-SNAPSHOT + 2.2.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8c8646f1b739..49d4e027bf12 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.1.1-SNAPSHOT + 2.2.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a41b9cd6c29b..7bca310323d2 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.1.0:2.1.1-SNAPSHOT +google-cloud-spanner-jdbc:2.2.0:2.2.0 From 463baad7263c5491a4e0a1fee73e0a12927f44b9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 21:56:12 +0000 Subject: [PATCH 0419/1979] chore: release 2.2.1-SNAPSHOT (#487) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d8601ee391cf..f0a735be2638 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.0 + 2.2.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 49d4e027bf12..5a9403332c08 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.0 + 2.2.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7bca310323d2..58f95a2014f5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.0:2.2.0 +google-cloud-spanner-jdbc:2.2.0:2.2.1-SNAPSHOT From 8448b94a99635f0499fd182c80fee8ac95f86c2c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 2 Jun 2021 22:26:05 +0200 Subject: [PATCH 0420/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.0 (#488) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.1.0` -> `2.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/compatibility-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/confidence-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.2.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​220-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev210v220-2021-05-26) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.1.0...v2.2.0) ##### Features - add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#​474](https://www.github.com/googleapis/java-spanner-jdbc/issues/474)) ([5f9ed96](https://www.github.com/googleapis/java-spanner-jdbc/commit/5f9ed96272c818f07d9eb384f283f7e9c032a6ca)) ##### Documentation - document connection properties in README ([#​478](https://www.github.com/googleapis/java-spanner-jdbc/issues/478)) ([f5bca0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/f5bca0cd589b1839f569497f2e7efddef9934174)), closes [#​456](https://www.github.com/googleapis/java-spanner-jdbc/issues/456) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 ([#​473](https://www.github.com/googleapis/java-spanner-jdbc/issues/473)) ([2d3097a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2d3097a65237eb0425ba3d2b52f594335190975c)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 ([#​483](https://www.github.com/googleapis/java-spanner-jdbc/issues/483)) ([af87ed0](https://www.github.com/googleapis/java-spanner-jdbc/commit/af87ed0d50d6c8650c08d5f6f605882dcd8cfbab))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ba86078360ae..e1d154cefbdc 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.1.0 + 2.2.0 From b6a968ca634af25e12ea7919302d69cb366ca212 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 2 Jun 2021 13:44:14 -0700 Subject: [PATCH 0421/1979] chore: regenerate README (#489) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-02 20:28:22,584 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-02 20:28:23,968 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/f9c652de-b905-42d2-8dff-d97f0e0d5476/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 49ff805af5d7..55f35bca4ee8 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "3ccc5433bec261b18d2536b04590e7645e47ed9b" + "sha": "4d7ad154135b066eb0cf4f9563933c978f4e6943" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "bb5ef5a99df6d439c63fddf0f7b6fe58e0679b10" + "sha": "c3e41da0fa256ad7f6b4bc76b9d069dedecdfef4" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c5b404ebdc7f..79fbfd8ef097 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.1.0 + 2.2.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.1.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.1.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.0" ``` ## Authentication From f4f05b9ce05476deb43a7601aa6ccdf053ca5ec1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 4 Jun 2021 17:10:29 +0200 Subject: [PATCH 0422/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.3.0 (#490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `1.2.0` -> `1.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/compatibility-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/confidence-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v1.3.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​130-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare120v130-2021-06-03) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.2.0...v1.3.0) ##### Features - add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#​365](https://www.github.com/googleapis/java-shared-dependencies/issues/365)) ([7e8309b](https://www.github.com/googleapis/java-shared-dependencies/commit/7e8309bf67ade0fe2b09f792848136cd88b4d2e4)) ##### Dependencies - update dependency com.google.auth:google-auth-library-bom to v0.26.0 ([#​368](https://www.github.com/googleapis/java-shared-dependencies/issues/368)) ([38256a8](https://www.github.com/googleapis/java-shared-dependencies/commit/38256a82cb6896c3f5e5ea6ca5d8d671c412bf84)) - update dependency com.google.cloud:google-cloud-core-bom to v1.95.0 ([#​377](https://www.github.com/googleapis/java-shared-dependencies/issues/377)) ([297ea62](https://www.github.com/googleapis/java-shared-dependencies/commit/297ea621e02f8c0679c8b07ed399d11eaacecc14)) - update dependency com.google.code.gson:gson to v2.8.7 ([#​370](https://www.github.com/googleapis/java-shared-dependencies/issues/370)) ([cdc1b8e](https://www.github.com/googleapis/java-shared-dependencies/commit/cdc1b8ea1c93f97b712081ca8dc8ea57f342b69e)) - update dependency com.google.protobuf:protobuf-bom to v3.17.1 ([#​369](https://www.github.com/googleapis/java-shared-dependencies/issues/369)) ([5a19574](https://www.github.com/googleapis/java-shared-dependencies/commit/5a19574bc626bb3c6b573ed1d177e8907188dec1)) - update dependency com.google.protobuf:protobuf-bom to v3.17.2 ([#​374](https://www.github.com/googleapis/java-shared-dependencies/issues/374)) ([83516e6](https://www.github.com/googleapis/java-shared-dependencies/commit/83516e691b99e5e5d22d27e561781a5ade5fb514)) - update dependency io.grpc:grpc-bom to v1.38.0 ([#​364](https://www.github.com/googleapis/java-shared-dependencies/issues/364)) ([00db570](https://www.github.com/googleapis/java-shared-dependencies/commit/00db5701c3b0aa609f3778c06911a9a0248ca342)) - update gax.version to v1.65.0 ([#​376](https://www.github.com/googleapis/java-shared-dependencies/issues/376)) ([b793a0d](https://www.github.com/googleapis/java-shared-dependencies/commit/b793a0d7744ff1b0f8ae5d3d13ec4776ae8d3089)) - update google.common-protos.version to v2.3.1 ([#​366](https://www.github.com/googleapis/java-shared-dependencies/issues/366)) ([7d6a7fa](https://www.github.com/googleapis/java-shared-dependencies/commit/7d6a7fa7a2cad2b3f2ecf45e42d2ed5db0b60a43)) - update google.common-protos.version to v2.3.2 ([#​375](https://www.github.com/googleapis/java-shared-dependencies/issues/375)) ([68a47ad](https://www.github.com/googleapis/java-shared-dependencies/commit/68a47ad3243f3e980db74c9c8505a1b3063c131b))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f0a735be2638..aa83de5b63d4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 1.2.0 + 1.3.0 pom import From 309cb0b8c4cfd4f188fdd628943d3ebf2ed65e91 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 15:32:08 +0000 Subject: [PATCH 0423/1979] chore: release 2.2.1 (#491) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.0...v2.2.1) (2021-06-04) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.3.0 ([#490](https://www.github.com/googleapis/java-spanner-jdbc/issues/490)) ([f4f05b9](https://www.github.com/googleapis/java-spanner-jdbc/commit/f4f05b9ce05476deb43a7601aa6ccdf053ca5ec1)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 0db055e37907..fe5632e1b071 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.2.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.0...v2.2.1) (2021-06-04) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v1.3.0 ([#490](https://www.github.com/googleapis/java-spanner-jdbc/issues/490)) ([bf0c9d6](https://www.github.com/googleapis/java-spanner-jdbc/commit/bf0c9d6bf612b50a59ea2d530430ccace79aaf35)) + ## [2.2.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.1.0...v2.2.0) (2021-05-26) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index aa83de5b63d4..63386911a2fe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.1-SNAPSHOT + 2.2.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5a9403332c08..9a1c8deb9696 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.1-SNAPSHOT + 2.2.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 58f95a2014f5..89b98cc5188e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.0:2.2.1-SNAPSHOT +google-cloud-spanner-jdbc:2.2.1:2.2.1 From 762886221dde51931661d9d8a2648bbe60c5d709 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 15:48:08 +0000 Subject: [PATCH 0424/1979] chore: release 2.2.2-SNAPSHOT (#492) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 63386911a2fe..2ab9e3259acf 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.1 + 2.2.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9a1c8deb9696..af73bc325851 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.1 + 2.2.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 89b98cc5188e..9debde31d7e6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.1:2.2.1 +google-cloud-spanner-jdbc:2.2.1:2.2.2-SNAPSHOT From 7cd3bb8167d180fe68de90772b314ff4cd0774bd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 5 Jun 2021 11:50:18 +0200 Subject: [PATCH 0425/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.1 (#493) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e1d154cefbdc..79f600b32f3a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.0 + 2.2.1 From 55a9f83d1622858a4e3f0036c8934055d279d5b4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 5 Jun 2021 11:50:38 +0200 Subject: [PATCH 0426/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.23 (#494) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 79f600b32f3a..534229914546 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.22 + 1.0.23 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 08d34f32f3c4..b50770aaecc9 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.22 + 1.0.23 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index af73bc325851..3e2a541e0683 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.22 + 1.0.23 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d29022a683f7..87e63b006034 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.22 + 1.0.23 From f8f904c1c9062e5f3b931e59b745acc0281f3ad7 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sat, 5 Jun 2021 03:08:06 -0700 Subject: [PATCH 0427/1979] chore: regenerate README (#495) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-05 09:53:24,030 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-05 09:53:25,229 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/2c57a5bd-142d-430b-9931-a1a1a7e59a30/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 55f35bca4ee8..720b019d5e7b 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "4d7ad154135b066eb0cf4f9563933c978f4e6943" + "sha": "554ff0508453712bb8f54394be9bf774d7cdf9b4" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "c3e41da0fa256ad7f6b4bc76b9d069dedecdfef4" + "sha": "8da7927493739fa36130360019ca21258242f73a" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 79fbfd8ef097..92c748d85b5c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.0 + 2.2.1 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.0' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.1" ``` ## Authentication From 4c2ef9759db2fa38e51697cdf095e89cb6e2c12b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 7 Jun 2021 21:00:18 +0200 Subject: [PATCH 0428/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.6.0 (#496) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.5.0` -> `20.6.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/compatibility-slim/20.5.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/confidence-slim/20.5.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 87e63b006034..321b143cb13a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.5.0 + 20.6.0 pom import From 412adf57e2b092074499d500071ca9968e0e9094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 10 Jun 2021 02:54:52 +0200 Subject: [PATCH 0429/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 (#498) * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 Updates to Spanner client 6.6.0 and adds tests for optimizer stats package. Replaces #497 * test: implement missing method for integration test --- java-spanner-jdbc/pom.xml | 2 +- .../spanner/jdbc/JdbcQueryOptionsTest.java | 110 ++++++++++++++---- .../jdbc/it/ITJdbcQueryOptionsTest.java | 40 +++++-- 3 files changed, 117 insertions(+), 35 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2ab9e3259acf..056534bbb0ff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.5.0 + 6.6.0 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index d26aba592811..d1aeeb92d4ee 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -20,6 +20,7 @@ import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.SpannerOptions.SpannerEnvironment; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.common.base.MoreObjects; @@ -40,7 +41,7 @@ public void setup() throws Exception { } @Test - public void testDefaultOptimizerVersion() throws SQLException { + public void testDefaultOptions() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { try (java.sql.ResultSet rs = connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { @@ -48,25 +49,39 @@ public void testDefaultOptimizerVersion() throws SQLException { assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); assertThat(rs.next()).isFalse(); } + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo(""); + assertThat(rs.next()).isFalse(); + } } } @Test - public void testOptimizerVersionInConnectionUrl() throws SQLException { + public void testOptionsInConnectionUrl() throws SQLException { try (java.sql.Connection connection = DriverManager.getConnection( - String.format("jdbc:%s;optimizerVersion=%s", getBaseUrl(), "100"))) { + String.format( + "jdbc:%s;optimizerVersion=%s;optimizerStatisticsPackage=%s", + getBaseUrl(), "100", "url_package"))) { try (java.sql.ResultSet rs = connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { assertThat(rs.next()).isTrue(); assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo("100"); assertThat(rs.next()).isFalse(); } + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo("url_package"); + assertThat(rs.next()).isFalse(); + } } } @Test - public void testSetOptimizerVersion() throws SQLException { + public void testSetOptions() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { connection.createStatement().execute("SET OPTIMIZER_VERSION='20'"); try (java.sql.ResultSet rs = @@ -89,41 +104,64 @@ public void testSetOptimizerVersion() throws SQLException { assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(""); assertThat(rs.next()).isFalse(); } + + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='20210609'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo("20210609"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='latest'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo("latest"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE=''"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo(""); + assertThat(rs.next()).isFalse(); + } } } @Test - public void testSetAndUseOptimizerVersion() throws SQLException { + public void testSetAndUseOptions() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { connection.createStatement().execute("SET OPTIMIZER_VERSION='20'"); + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='20210609'"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); assertThat(rs.next()).isFalse(); - // Verify that the last ExecuteSqlRequest that the server received specified optimizer - // version 20. + // Verify that the last ExecuteSqlRequest that the server received used the options that + // were set. ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()).isEqualTo("20210609"); } - // Do another query, but now with optimizer version 'latest'. connection.createStatement().execute("SET OPTIMIZER_VERSION='latest'"); + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='latest'"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); assertThat(rs.next()).isFalse(); - // Verify that the last ExecuteSqlRequest that the server received specified optimizer - // version 'latest'. ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("latest"); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()).isEqualTo("latest"); } - // Set the optimizer version to ''. This will do a fallback to the default, meaning that it - // will be read from the environment variable SPANNER_OPTIMIZER_VERSION as we have nothing set - // on the connection URL. + // Set the options to ''. This will do a fallback to the default, meaning that it will be read + // from the environment variables as we have nothing set on the connection URL. connection.createStatement().execute("SET OPTIMIZER_VERSION=''"); + connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE=''"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); @@ -134,31 +172,49 @@ public void testSetAndUseOptimizerVersion() throws SQLException { ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()) .isEqualTo(MoreObjects.firstNonNull(System.getenv("SPANNER_OPTIMIZER_VERSION"), "")); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) + .isEqualTo(MoreObjects.firstNonNull(System.getenv("OPTIMIZER_STATISTICS_PACKAGE"), "")); } } } @Test - public void testUseOptimizerVersionFromConnectionUrl() throws SQLException { + public void testUseOptionsFromConnectionUrl() throws SQLException { try (java.sql.Connection connection = - DriverManager.getConnection(String.format("jdbc:%s;optimizerVersion=10", getBaseUrl()))) { + DriverManager.getConnection( + String.format( + "jdbc:%s;optimizerVersion=10;optimizerStatisticsPackage=20210609_10_00_00", + getBaseUrl()))) { // Do a query and verify that the version from the connection URL is used. try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); assertThat(rs.next()).isFalse(); - // The optimizer version used should be '10' from the connection URL. + // The options should come from the connection URL. ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("10"); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) + .isEqualTo("20210609_10_00_00"); } } } @Test - public void testUseOptimizerVersionFromEnvironment() throws SQLException { + public void testUseOptionsFromEnvironment() throws SQLException { try { - SpannerOptions.useEnvironment(() -> "20"); + SpannerOptions.useEnvironment( + new SpannerEnvironment() { + @Override + public String getOptimizerVersion() { + return "20"; + } + + @Override + public String getOptimizerStatisticsPackage() { + return "env_package"; + } + }); try (java.sql.Connection connection = DriverManager.getConnection(String.format("jdbc:%s", getBaseUrl()))) { // Do a query and verify that the version from the environment is used. @@ -170,6 +226,8 @@ public void testUseOptimizerVersionFromEnvironment() throws SQLException { // Verify query options from the environment. ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) + .isEqualTo("env_package"); } // Now set one of the query options on the connection. That option should be used in // combination with the other option from the environment. @@ -183,6 +241,9 @@ public void testUseOptimizerVersionFromEnvironment() throws SQLException { ExecuteSqlRequest request = getLastExecuteSqlRequest(); // Optimizer version should come from the connection. assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("30"); + // Optimizer statistics package should come from the environment. + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) + .isEqualTo("env_package"); } } } finally { @@ -195,7 +256,9 @@ public void testUseQueryHint() throws SQLException { mockSpanner.putStatementResult( StatementResult.query( Statement.of( - String.format("@{optimizer_version=1} %s", SELECT_COUNT_STATEMENT.getSql())), + String.format( + "@{optimizer_version=1, optimizer_statistics_package=hint_package} %s", + SELECT_COUNT_STATEMENT.getSql())), SELECT_COUNT_RESULTSET_BEFORE_INSERT)); try (java.sql.Connection connection = DriverManager.getConnection(String.format("jdbc:%s", getBaseUrl()))) { @@ -203,14 +266,17 @@ public void testUseQueryHint() throws SQLException { connection .createStatement() .executeQuery( - String.format("@{optimizer_version=1} %s", SELECT_COUNT_STATEMENT.getSql()))) { + String.format( + "@{optimizer_version=1, optimizer_statistics_package=hint_package} %s", + SELECT_COUNT_STATEMENT.getSql()))) { assertThat(rs.next()).isTrue(); assertThat(rs.getLong(1)).isEqualTo(COUNT_BEFORE_INSERT); assertThat(rs.next()).isFalse(); - // The optimizer version used in the ExecuteSqlRequest should be empty as the query hint is - // parsed by the backend. + // The options used in the ExecuteSqlRequest should be empty as the query hint is parsed by + // the backend. ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo(""); + assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()).isEqualTo(""); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 7ca650dfc173..ac90687c8217 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -17,6 +17,9 @@ package com.google.cloud.spanner.jdbc.it; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; @@ -25,6 +28,7 @@ import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlException; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.rpc.Code; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.sql.Connection; @@ -96,7 +100,8 @@ public void connectionUrl() throws SQLException { @Test public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { - assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); + assumeFalse( + "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); this.connectionUriSuffix = ";optimizerVersion=9999999"; try (Connection connection = createConnection()) { try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { @@ -139,7 +144,8 @@ public void setLatestOptimizerVersion() throws SQLException { @Test public void setInvalidOptimizerVersion() throws SQLException { - assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); + assumeFalse( + "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection()) { connection.createStatement().execute("SET OPTIMIZER_VERSION='9999999'"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { @@ -156,7 +162,7 @@ public void setInvalidOptimizerVersion() throws SQLException { public void optimizerVersionInQueryHint() throws SQLException { assumeFalse( "optimizer version in query hint is not supported on emulator", - env.getTestHelper().isEmulator()); + EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection()) { verifyOptimizerVersion(connection, ""); try (ResultSet rs = @@ -175,8 +181,9 @@ public void optimizerVersionInQueryHint() throws SQLException { } @Test - public void optimizerVersionInEnvironment() throws SQLException { - assumeFalse("optimizer version is ignored on emulator", env.getTestHelper().isEmulator()); + public void testOptionsInEnvironment() throws SQLException { + assumeFalse( + "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); try { SpannerOptions.useEnvironment( new SpannerOptions.SpannerEnvironment() { @@ -184,6 +191,11 @@ public void optimizerVersionInEnvironment() throws SQLException { public String getOptimizerVersion() { return "1"; } + + @Override + public String getOptimizerStatisticsPackage() { + return "latest"; + } }); try (Connection connection = createConnection()) { // Environment query options are not visible to the connection. @@ -204,15 +216,19 @@ public String getOptimizerVersion() { public String getOptimizerVersion() { return "9999999"; } + + @Override + public String getOptimizerStatisticsPackage() { + return "latest"; + } }); try (Connection connection = createConnection()) { - try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { - fail("missing expected exception"); - } catch (SQLException e) { - assertThat((Throwable) e).isInstanceOf(JdbcSqlException.class); - JdbcSqlException je = (JdbcSqlException) e; - assertThat(je.getCode()).isEqualTo(Code.INVALID_ARGUMENT); - } + SQLException e = + assertThrows( + SQLException.class, () -> connection.createStatement().executeQuery("SELECT 1")); + assertTrue(e instanceof JdbcSqlException); + JdbcSqlException je = (JdbcSqlException) e; + assertEquals(Code.INVALID_ARGUMENT, je.getCode()); } } finally { SpannerOptions.useDefaultEnvironment(); From 94323d48fccd9f556c1bab1a9072f37d0b7eff36 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 10 Jun 2021 01:14:05 +0000 Subject: [PATCH 0430/1979] chore: release 2.2.2 (#499) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.1...v2.2.2) (2021-06-10) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 ([#498](https://www.github.com/googleapis/java-spanner-jdbc/issues/498)) ([412adf5](https://www.github.com/googleapis/java-spanner-jdbc/commit/412adf57e2b092074499d500071ca9968e0e9094)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index fe5632e1b071..1f2efa91ca15 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.2.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.1...v2.2.2) (2021-06-10) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 ([#498](https://www.github.com/googleapis/java-spanner-jdbc/issues/498)) ([5849a97](https://www.github.com/googleapis/java-spanner-jdbc/commit/5849a970087d3fa1d1b42092b4568602563a1dbd)) + ### [2.2.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.0...v2.2.1) (2021-06-04) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 056534bbb0ff..767f5337dc36 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.2-SNAPSHOT + 2.2.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3e2a541e0683..27ed2fe56b2f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.2-SNAPSHOT + 2.2.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9debde31d7e6..2031781d9b29 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.1:2.2.2-SNAPSHOT +google-cloud-spanner-jdbc:2.2.2:2.2.2 From 22169a37bfebbd61e14407a322d9f0e37e57aee7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 10 Jun 2021 01:30:05 +0000 Subject: [PATCH 0431/1979] chore: release 2.2.3-SNAPSHOT (#500) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 767f5337dc36..2a88a4324180 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.2 + 2.2.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 27ed2fe56b2f..f463553a9eee 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.2 + 2.2.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2031781d9b29..5fd766f61e6b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.2:2.2.2 +google-cloud-spanner-jdbc:2.2.2:2.2.3-SNAPSHOT From 731d0e4229b8dd97648f4319fdc03268aabc3ace Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Jun 2021 23:12:38 +0200 Subject: [PATCH 0432/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.1 (#502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.6.0` -> `6.6.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/compatibility-slim/6.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/confidence-slim/6.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.6.1`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​661-httpswwwgithubcomgoogleapisjava-spannercomparev660v661-2021-06-10) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.6.0...v6.6.1)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2a88a4324180..3ca45fdf4924 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.6.0 + 6.6.1 pom import From 55eec9c35fea270ae58d90e1e73e47e43c96c486 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 15 Jun 2021 21:32:08 +0000 Subject: [PATCH 0433/1979] chore: release 2.2.3 (#504) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.2...v2.2.3) (2021-06-15) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.1 ([#502](https://www.github.com/googleapis/java-spanner-jdbc/issues/502)) ([731d0e4](https://www.github.com/googleapis/java-spanner-jdbc/commit/731d0e4229b8dd97648f4319fdc03268aabc3ace)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1f2efa91ca15..e01978820f3f 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.2.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.2...v2.2.3) (2021-06-15) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.1 ([#502](https://www.github.com/googleapis/java-spanner-jdbc/issues/502)) ([41a9cd4](https://www.github.com/googleapis/java-spanner-jdbc/commit/41a9cd49fed468f410ad226555f7b9ba46d857b3)) + ### [2.2.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.1...v2.2.2) (2021-06-10) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ca45fdf4924..123a5c592b12 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.3-SNAPSHOT + 2.2.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f463553a9eee..b2f6193f12a5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.3-SNAPSHOT + 2.2.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5fd766f61e6b..2527fc276823 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.2:2.2.3-SNAPSHOT +google-cloud-spanner-jdbc:2.2.3:2.2.3 From 839eebdd6104039749567ae2a31ee295227c4de8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 15 Jun 2021 14:32:10 -0700 Subject: [PATCH 0434/1979] chore: regenerate README (#505) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-15 21:17:11,110 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-15 21:17:12,273 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/0bc6fb82-3b4e-44b2-978c-65fa57b88268/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 720b019d5e7b..e9f671faa1d1 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "554ff0508453712bb8f54394be9bf774d7cdf9b4" + "sha": "41a9cd49fed468f410ad226555f7b9ba46d857b3" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8da7927493739fa36130360019ca21258242f73a" + "sha": "8f76a885deaaf2fe234daeba4a8cc4d1b3de8086" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 92c748d85b5c..ec3dd0a1859a 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.1 + 2.2.2 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.1' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.2' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.2" ``` ## Authentication From 4a2ce48c9af07382bf5a5c4c7bdc06df03499199 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 15 Jun 2021 21:48:08 +0000 Subject: [PATCH 0435/1979] chore: release 2.2.4-SNAPSHOT (#507) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 123a5c592b12..49e128dd900b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.3 + 2.2.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b2f6193f12a5..6d4c8162b9c5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.3 + 2.2.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2527fc276823..659bd1f9d229 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.3:2.2.3 +google-cloud-spanner-jdbc:2.2.3:2.2.4-SNAPSHOT From 3b7159618eb47306c2f5e0628d494e603d92f51e Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 15 Jun 2021 15:04:08 -0700 Subject: [PATCH 0436/1979] fix: Update dependencies.sh to not break on mac (#506) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/f853e0b6-9a6b-4346-9a07-ff7c7ec6f858/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/8f76a885deaaf2fe234daeba4a8cc4d1b3de8086 --- java-spanner-jdbc/.kokoro/dependencies.sh | 4 ++-- java-spanner-jdbc/synth.metadata | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 59d2aafc790f..a7e999d33bfb 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -46,7 +46,7 @@ function completenessCheck() { # This is stripped from the output as it is not present in the flattened pom. # Only dependencies with 'compile' or 'runtime' scope are included from original dependency list. msg "Generating dependency list using original pom..." - mvn dependency:list -f pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e s/\\s--\\smodule.*// >.org-list.txt + mvn dependency:list -f pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e 's/ --.*//' >.org-list.txt # Output dep list generated using the flattened pom (only 'compile' and 'runtime' scopes) msg "Generating dependency list using flattened pom..." @@ -70,7 +70,7 @@ function completenessCheck() { set +e error_count=0 -for path in $(find -name ".flattened-pom.xml") +for path in **/.flattened-pom.xml do # Check flattened pom in each dir that contains it for completeness dir=$(dirname "$path") diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 5186fb26131c..bf237ce168b6 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "b7218e5b4408685b3d291c0010a24d7a048b3b0e" + "sha": "41a9cd49fed468f410ad226555f7b9ba46d857b3" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8eae0234a16b26c2ff616d305dbd9786c8b10a47" + "sha": "8f76a885deaaf2fe234daeba4a8cc4d1b3de8086" } } ], @@ -79,6 +79,7 @@ "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "LICENSE", + "SECURITY.md", "codecov.yaml", "java.header", "license-checks.xml", From d1dbd5e4c7716145787e4c1e1480461e075a7a51 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 16 Jun 2021 01:09:21 +0200 Subject: [PATCH 0437/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.2 (#501) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 534229914546..6b8351848f3a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.1 + 2.2.2 From b440a22e6201a6035326aec63aaecc0f1523c268 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 15 Jun 2021 16:26:10 -0700 Subject: [PATCH 0438/1979] chore: regenerate README (#510) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-15 23:11:37,759 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-15 23:11:38,999 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/61cfb5e0-68cd-47b3-89b4-af4a25c2c4b6/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 2 +- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index e9f671faa1d1..a9f3e4274a41 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "41a9cd49fed468f410ad226555f7b9ba46d857b3" + "sha": "ce3d0cdb5aa63753a26f55c524a6faa482884052" } }, { diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ec3dd0a1859a..afafb1da45b6 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.2 + 2.2.3 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.2' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.3' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.3" ``` ## Authentication From 98d72146a1b21cd8adf7c89b0a698c63737813ad Mon Sep 17 00:00:00 2001 From: Yunus Durmus Date: Wed, 16 Jun 2021 13:32:02 +0200 Subject: [PATCH 0439/1979] fix: prevent relocating urls that start with com like /computeMetadata/ (#511) Fixes #503 In addition to original problem I have added an exception for all the Netty libraries since I have got errors on service provider which claims that netty libraries are not a subtype. --- java-spanner-jdbc/pom.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 49e128dd900b..76bf954dfff1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -333,26 +333,26 @@ - com - com.google.cloud.spanner.jdbc.shaded.com + com. + com.google.cloud.spanner.jdbc.shaded.com. com.google.cloud.spanner.** - android - com.google.cloud.spanner.jdbc.shaded.android + android. + com.google.cloud.spanner.jdbc.shaded.android. - io - com.google.cloud.spanner.jdbc.shaded.io + io. + com.google.cloud.spanner.jdbc.shaded.io. io.grpc.netty.shaded.** - org - com.google.cloud.spanner.jdbc.shaded.org + org. + com.google.cloud.spanner.jdbc.shaded.org. org.conscrypt.** From 5daf86c9ba59fc9744da560665370b2dae218923 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 16 Jun 2021 22:00:06 +0200 Subject: [PATCH 0440/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.3 (#509) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6b8351848f3a..6808f6a53aef 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.2 + 2.2.3 From dff23ea0bef40bea1b4eba20fa854389ebbd6a14 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 22 Jun 2021 08:04:10 -0700 Subject: [PATCH 0441/1979] chore: minimize noise from build scripts (#512) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/88f2626c-4d2d-42a7-9d16-aaa685eaa74a/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/1c0c698705e668ccb3d68556ae7260f16ce63a6e --- java-spanner-jdbc/.kokoro/coerce_logs.sh | 1 - java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/coerce_logs.sh b/java-spanner-jdbc/.kokoro/coerce_logs.sh index 5cf7ba49e6bb..46edbf7f2fcd 100755 --- a/java-spanner-jdbc/.kokoro/coerce_logs.sh +++ b/java-spanner-jdbc/.kokoro/coerce_logs.sh @@ -28,7 +28,6 @@ job=$(basename ${KOKORO_JOB_NAME}) echo "coercing sponge logs..." for xml in `find . -name *-sponge_log.xml` do - echo "processing ${xml}" class=$(basename ${xml} | cut -d- -f2) dir=$(dirname ${xml})/${job}/${class} text=$(dirname ${xml})/${class}-sponge_log.txt diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index bf237ce168b6..328fd043f529 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "41a9cd49fed468f410ad226555f7b9ba46d857b3" + "sha": "f229b75c2eb905e483fb02ef62e168ac1c567f28" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8f76a885deaaf2fe234daeba4a8cc4d1b3de8086" + "sha": "1c0c698705e668ccb3d68556ae7260f16ce63a6e" } } ], From 56d3134da0de80b077ee5b2b5dea2927f53e6df4 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 23 Jun 2021 09:00:31 -0700 Subject: [PATCH 0442/1979] fix: Add `shopt -s nullglob` to dependencies script (#514) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/bc91c2d7-c025-42b9-ab03-f02a01c15622/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/87254ac89a9559864c0a245d6b150406439ce3d8 --- java-spanner-jdbc/.kokoro/dependencies.sh | 1 + java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index a7e999d33bfb..9030ba8f99ff 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -14,6 +14,7 @@ # limitations under the License. set -eo pipefail +shopt -s nullglob ## Get the directory of the build script scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 328fd043f529..1e125704d6ee 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "f229b75c2eb905e483fb02ef62e168ac1c567f28" + "sha": "72d109fdea7e17cda53cffbe640dc51adf4fdf1a" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "1c0c698705e668ccb3d68556ae7260f16ce63a6e" + "sha": "87254ac89a9559864c0a245d6b150406439ce3d8" } } ], From f2d7b9c099d77a60e9245e59d2fc3f1f22998c8b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 23 Jun 2021 21:12:31 +0200 Subject: [PATCH 0443/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.7.0 (#515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.6.0` -> `20.7.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/compatibility-slim/20.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/confidence-slim/20.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 321b143cb13a..39610eebba0d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.6.0 + 20.7.0 pom import From e3e5795317aa279150ba7f76e1f2f9b84ed56fd3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 25 Jun 2021 05:06:40 +0200 Subject: [PATCH 0444/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.7.0 (#513) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 76bf954dfff1..a6ed0e511d9a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.6.1 + 6.7.0 pom import From d29b441c02ee59424ec95b6f211c3839ef73db44 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 2 Jul 2021 01:28:11 +0200 Subject: [PATCH 0445/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 (#518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `1.3.0` -> `1.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/compatibility-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/confidence-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v1.4.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​140-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare130v140-2021-06-30) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.3.0...v1.4.0) ##### Features - add grpc-gcp to dependencyManagement ([#​389](https://www.github.com/googleapis/java-shared-dependencies/issues/389)) ([57fd2e6](https://www.github.com/googleapis/java-shared-dependencies/commit/57fd2e646e28e37e0b5e4e1b37425d4897a8776f)) ##### Bug Fixes - Add `shopt -s nullglob` to dependencies script ([#​392](https://www.github.com/googleapis/java-shared-dependencies/issues/392)) ([f8f29df](https://www.github.com/googleapis/java-shared-dependencies/commit/f8f29df1c9cc6eca517c99113fb9509fd611ac92)) - Add common httpclient and oauth dependencies ([#​391](https://www.github.com/googleapis/java-shared-dependencies/issues/391)) ([09660e1](https://www.github.com/googleapis/java-shared-dependencies/commit/09660e1e50c96dcd7df4e80d8ad357f8256eda6c)) - Update dependencies.sh to not break on mac ([#​384](https://www.github.com/googleapis/java-shared-dependencies/issues/384)) ([0ae2841](https://www.github.com/googleapis/java-shared-dependencies/commit/0ae2841d7ce2885d041795c58a38d2d3973c2e5a)) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.32.1 ([#​390](https://www.github.com/googleapis/java-shared-dependencies/issues/390)) ([00288c1](https://www.github.com/googleapis/java-shared-dependencies/commit/00288c18d09616582c8bec961ecc5c00ef1d4288)) - update dependency com.google.api:api-common to v1.10.4 ([#​385](https://www.github.com/googleapis/java-shared-dependencies/issues/385)) ([5f2b39b](https://www.github.com/googleapis/java-shared-dependencies/commit/5f2b39b5bdc4cec9d5ab2f050e11000ed372d057)) - update dependency com.google.api:gax-grpc to v1.65.1 ([#​382](https://www.github.com/googleapis/java-shared-dependencies/issues/382)) ([a2a1547](https://www.github.com/googleapis/java-shared-dependencies/commit/a2a15471dee21207a0b97b3bc8f6f59d6a4a2d13)) - update dependency com.google.protobuf:protobuf-bom to v3.17.3 ([#​379](https://www.github.com/googleapis/java-shared-dependencies/issues/379)) ([6f43eb5](https://www.github.com/googleapis/java-shared-dependencies/commit/6f43eb553dca98140d343bee3f1003096d79ee6c)) - update dependency io.grpc:grpc-bom to v1.38.1 ([#​386](https://www.github.com/googleapis/java-shared-dependencies/issues/386)) ([7b1d4cf](https://www.github.com/googleapis/java-shared-dependencies/commit/7b1d4cf317fbd75b91d6a63f82b5fc2f46eaf3ca)) - update dependency io.grpc:grpc-bom to v1.39.0 ([#​394](https://www.github.com/googleapis/java-shared-dependencies/issues/394)) ([ebc8af6](https://www.github.com/googleapis/java-shared-dependencies/commit/ebc8af6b3f850b58b35d9720a7a0b1545d4616bd)) - update gax.version to v1.66.0 ([#​395](https://www.github.com/googleapis/java-shared-dependencies/issues/395)) ([c73f73e](https://www.github.com/googleapis/java-shared-dependencies/commit/c73f73e84740a8117be342a66e179eaf3e29c6fd)) - update google.core.version to v1.95.1 ([#​381](https://www.github.com/googleapis/java-shared-dependencies/issues/381)) ([4496153](https://www.github.com/googleapis/java-shared-dependencies/commit/44961532f621b0ab19e9e7feebb7d588aef5d423)) - update google.core.version to v1.95.2 ([#​383](https://www.github.com/googleapis/java-shared-dependencies/issues/383)) ([7216859](https://www.github.com/googleapis/java-shared-dependencies/commit/7216859bcd67fa1ce1119831c33c50a2d5b79324)) - update google.core.version to v1.95.3 ([#​388](https://www.github.com/googleapis/java-shared-dependencies/issues/388)) ([354e4e8](https://www.github.com/googleapis/java-shared-dependencies/commit/354e4e811f4ba886406681a4261ac0455a9eb2d2)) - update google.core.version to v1.95.4 ([#​393](https://www.github.com/googleapis/java-shared-dependencies/issues/393)) ([be78ad8](https://www.github.com/googleapis/java-shared-dependencies/commit/be78ad85e31d8876eabafee7aa8242712573cb46))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a6ed0e511d9a..02ff8f19fae8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud google-cloud-shared-dependencies - 1.3.0 + 1.4.0 pom import From 9c36f5a1a52436fa84fa63d122b57f1d655047df Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 2 Jul 2021 22:44:23 +0200 Subject: [PATCH 0446/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.8.0 (#517) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.7.0` -> `6.8.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/compatibility-slim/6.7.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/confidence-slim/6.7.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.8.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​680-httpswwwgithubcomgoogleapisjava-spannercomparev670v680-2021-06-29) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.7.0...v6.8.0) ##### Features - add gRPC-GCP channel pool as an option ([#​1227](https://www.github.com/googleapis/java-spanner/issues/1227)) ([1fa95a9](https://www.github.com/googleapis/java-spanner/commit/1fa95a9993ea8c7a5f943ab39eced4ced4cb87e7)) - spanner JSON type ([#​1260](https://www.github.com/googleapis/java-spanner/issues/1260)) ([b2a56c6](https://www.github.com/googleapis/java-spanner/commit/b2a56c68695b6209e20f9f86d83d7c5a0f39c7a8)) ##### Bug Fixes - Add `shopt -s nullglob` to dependencies script ([#​1256](https://www.github.com/googleapis/java-spanner/issues/1256)) ([d1712f7](https://www.github.com/googleapis/java-spanner/commit/d1712f7c51752c2359045e5eabac8fc0530a2421))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 02ff8f19fae8..f058bb30569f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.7.0 + 6.8.0 pom import From 914aa9caefa5fa54f4562c661f6451061dfb4c18 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 21:44:16 +0000 Subject: [PATCH 0447/1979] chore: release 2.2.4 (#508) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.3...v2.2.4) (2021-07-02) ### Bug Fixes * Add `shopt -s nullglob` to dependencies script ([#514](https://www.github.com/googleapis/java-spanner-jdbc/issues/514)) ([56d3134](https://www.github.com/googleapis/java-spanner-jdbc/commit/56d3134da0de80b077ee5b2b5dea2927f53e6df4)) * prevent relocating urls that start with com like /computeMetadata/ ([#511](https://www.github.com/googleapis/java-spanner-jdbc/issues/511)) ([98d7214](https://www.github.com/googleapis/java-spanner-jdbc/commit/98d72146a1b21cd8adf7c89b0a698c63737813ad)) * Update dependencies.sh to not break on mac ([#506](https://www.github.com/googleapis/java-spanner-jdbc/issues/506)) ([3b71596](https://www.github.com/googleapis/java-spanner-jdbc/commit/3b7159618eb47306c2f5e0628d494e603d92f51e)) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 ([#518](https://www.github.com/googleapis/java-spanner-jdbc/issues/518)) ([d29b441](https://www.github.com/googleapis/java-spanner-jdbc/commit/d29b441c02ee59424ec95b6f211c3839ef73db44)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.7.0 ([#513](https://www.github.com/googleapis/java-spanner-jdbc/issues/513)) ([e3e5795](https://www.github.com/googleapis/java-spanner-jdbc/commit/e3e5795317aa279150ba7f76e1f2f9b84ed56fd3)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.8.0 ([#517](https://www.github.com/googleapis/java-spanner-jdbc/issues/517)) ([9c36f5a](https://www.github.com/googleapis/java-spanner-jdbc/commit/9c36f5a1a52436fa84fa63d122b57f1d655047df)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e01978820f3f..67c321f8478c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +### [2.2.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.3...v2.2.4) (2021-07-02) + + +### Bug Fixes + +* Add `shopt -s nullglob` to dependencies script ([#514](https://www.github.com/googleapis/java-spanner-jdbc/issues/514)) ([ae51b24](https://www.github.com/googleapis/java-spanner-jdbc/commit/ae51b241148606ffddeb0a703b853de67710e48b)) +* prevent relocating urls that start with com like /computeMetadata/ ([#511](https://www.github.com/googleapis/java-spanner-jdbc/issues/511)) ([1178a1d](https://www.github.com/googleapis/java-spanner-jdbc/commit/1178a1d35b4b0032acf71b3dbf862d4f9fb9399c)) +* Update dependencies.sh to not break on mac ([#506](https://www.github.com/googleapis/java-spanner-jdbc/issues/506)) ([e205c0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/e205c0c8eba6ac23d747c433b42d8e2365528bd8)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 ([#518](https://www.github.com/googleapis/java-spanner-jdbc/issues/518)) ([045b858](https://www.github.com/googleapis/java-spanner-jdbc/commit/045b8586a7ca7b0e2bd341b27ca3e8a3530c992a)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.7.0 ([#513](https://www.github.com/googleapis/java-spanner-jdbc/issues/513)) ([e1affe3](https://www.github.com/googleapis/java-spanner-jdbc/commit/e1affe358a812a45b9d2c0c9ccd0b00e3aa3791e)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.8.0 ([#517](https://www.github.com/googleapis/java-spanner-jdbc/issues/517)) ([c9013ff](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9013ff48269b158121e4c65c545be30752c31fb)) + ### [2.2.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.2...v2.2.3) (2021-06-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f058bb30569f..5696925c30f5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.4-SNAPSHOT + 2.2.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6d4c8162b9c5..fa1b62d09d97 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.4-SNAPSHOT + 2.2.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 659bd1f9d229..c8615754512c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.3:2.2.4-SNAPSHOT +google-cloud-spanner-jdbc:2.2.4:2.2.4 From 5b6f7b3e0ea980764cc6761ae6ab4d0d697cadb0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 22:00:45 +0000 Subject: [PATCH 0448/1979] chore: release 2.2.5-SNAPSHOT (#519) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5696925c30f5..e4a3dfe06a03 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.4 + 2.2.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fa1b62d09d97..a2542d45b5ec 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.4 + 2.2.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c8615754512c..165fde3905d7 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.4:2.2.4 +google-cloud-spanner-jdbc:2.2.4:2.2.5-SNAPSHOT From d5f7f9631065d19894f5578ba04f10147784c4d2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 6 Jul 2021 02:16:46 +0200 Subject: [PATCH 0449/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.0 (#521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.8.0` -> `6.9.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/compatibility-slim/6.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/confidence-slim/6.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.9.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​690-httpswwwgithubcomgoogleapisjava-spannercomparev680v690-2021-07-05) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.8.0...v6.9.0) ##### Features - add support for tagging to Connection API ([#​623](https://www.github.com/googleapis/java-spanner/issues/623)) ([5722372](https://www.github.com/googleapis/java-spanner/commit/5722372b7869828e372dec06e80e5b0e7280af61)) - **spanner:** add leader_options to InstanceConfig and default_leader to Database ([#​1271](https://www.github.com/googleapis/java-spanner/issues/1271)) ([f257671](https://www.github.com/googleapis/java-spanner/commit/f25767144344f0df67662f1b3ef662902384599a)) - support setting an async executor provider ([#​1263](https://www.github.com/googleapis/java-spanner/issues/1263)) ([369c8a7](https://www.github.com/googleapis/java-spanner/commit/369c8a771ec48fa1476236f800b0e8eb5982a33c)) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 ([#​1269](https://www.github.com/googleapis/java-spanner/issues/1269)) ([025e162](https://www.github.com/googleapis/java-spanner/commit/025e162813d6321dabe49e32f00934f9ae334e24))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e4a3dfe06a03..879f74d6e426 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.8.0 + 6.9.0 pom import From 9a124b80af422f5bba6f74e7c645497a655f2bb0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 00:36:15 +0000 Subject: [PATCH 0450/1979] chore: release 2.2.5 (#522) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.4...v2.2.5) (2021-07-06) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.0 ([#521](https://www.github.com/googleapis/java-spanner-jdbc/issues/521)) ([d5f7f96](https://www.github.com/googleapis/java-spanner-jdbc/commit/d5f7f9631065d19894f5578ba04f10147784c4d2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 67c321f8478c..40aa13b62c7c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.2.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.4...v2.2.5) (2021-07-06) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.0 ([#521](https://www.github.com/googleapis/java-spanner-jdbc/issues/521)) ([8d840ac](https://www.github.com/googleapis/java-spanner-jdbc/commit/8d840ac855f4466c1d53a3b38d964e213708e5e5)) + ### [2.2.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.3...v2.2.4) (2021-07-02) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 879f74d6e426..37e90c90a7f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.5-SNAPSHOT + 2.2.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a2542d45b5ec..8b940b7aabfa 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.5-SNAPSHOT + 2.2.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 165fde3905d7..cb92608d5b66 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.4:2.2.5-SNAPSHOT +google-cloud-spanner-jdbc:2.2.5:2.2.5 From e7651c623cb614a688b398d63e4a192fd1e8c91f Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 5 Jul 2021 17:38:20 -0700 Subject: [PATCH 0451/1979] chore: regenerate README (#523) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-06 00:20:39,365 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-06 00:20:40,571 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/c1ec5162-f264-4d89-804f-4f695017e997/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index a9f3e4274a41..86fa7727f49a 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ce3d0cdb5aa63753a26f55c524a6faa482884052" + "sha": "8d840ac855f4466c1d53a3b38d964e213708e5e5" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8f76a885deaaf2fe234daeba4a8cc4d1b3de8086" + "sha": "39652e3948f455fd0b77535a0145eeec561a3706" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index afafb1da45b6..b4cb3fef8c45 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.3 + 2.2.4 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.3' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.4' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.4" ``` ## Authentication From 8c4bc7e983c7881091fff14c7fb6f47d518d52c7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 00:52:28 +0000 Subject: [PATCH 0452/1979] chore: release 2.2.6-SNAPSHOT (#524) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 37e90c90a7f0..a5cd3d17dd47 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.5 + 2.2.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8b940b7aabfa..6a315d9c4641 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.5 + 2.2.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index cb92608d5b66..dda6efbf5a44 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.5:2.2.5 +google-cloud-spanner-jdbc:2.2.5:2.2.6-SNAPSHOT From 0dfd2865e15661d01f89bdeae083a32f4a83a8c3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 6 Jul 2021 03:46:24 +0200 Subject: [PATCH 0453/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.4 (#520) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6808f6a53aef..d83d18a54c7c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.3 + 2.2.4 From b64fd58e4f95e430b19eb18988c16e1ea87d529f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 6 Jul 2021 03:46:44 +0200 Subject: [PATCH 0454/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.1 (#525) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a5cd3d17dd47..1e0fcb098036 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -71,7 +71,7 @@ com.google.cloud google-cloud-spanner-bom - 6.9.0 + 6.9.1 pom import From ad598fa779293ea072a6b23a5248f4d24a5efcf5 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 5 Jul 2021 19:04:12 -0700 Subject: [PATCH 0455/1979] chore: regenerate README (#528) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-06 01:48:33,450 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-06 01:48:34,668 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/ca49248a-3908-48df-b9b2-6223c4d77cca/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 2 +- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 86fa7727f49a..109d30036324 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "8d840ac855f4466c1d53a3b38d964e213708e5e5" + "sha": "37023b8295c97304aa0a55a28f71905fcbf5b93f" } }, { diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index b4cb3fef8c45..a35c7eee8a54 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.4 + 2.2.5 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.4' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.5' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.4" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.5" ``` ## Authentication From 024f1184f3474a85e7c61a8d5f4874a95f1fe293 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 02:06:20 +0000 Subject: [PATCH 0456/1979] chore: release 2.2.6 (#527) :robot: I have created a release \*beep\* \*boop\* --- ### [2.2.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.5...v2.2.6) (2021-07-06) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.1 ([#525](https://www.github.com/googleapis/java-spanner-jdbc/issues/525)) ([b64fd58](https://www.github.com/googleapis/java-spanner-jdbc/commit/b64fd58e4f95e430b19eb18988c16e1ea87d529f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 40aa13b62c7c..55b6ee3745b7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.2.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.5...v2.2.6) (2021-07-06) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.1 ([#525](https://www.github.com/googleapis/java-spanner-jdbc/issues/525)) ([37023b8](https://www.github.com/googleapis/java-spanner-jdbc/commit/37023b8295c97304aa0a55a28f71905fcbf5b93f)) + ### [2.2.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.4...v2.2.5) (2021-07-06) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1e0fcb098036..bb116a07e4f7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.6-SNAPSHOT + 2.2.6 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6a315d9c4641..e4893ca514fc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.6-SNAPSHOT + 2.2.6 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index dda6efbf5a44..5d7374ae0189 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.5:2.2.6-SNAPSHOT +google-cloud-spanner-jdbc:2.2.6:2.2.6 From 7ea3810982eae41f6dbf34742c8c96107d0db27c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 02:22:26 +0000 Subject: [PATCH 0457/1979] chore: release 2.2.7-SNAPSHOT (#529) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bb116a07e4f7..f96265d3f1e7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.6 + 2.2.7-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e4893ca514fc..32249bb7427c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.6 + 2.2.7-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5d7374ae0189..dd8f71e62a22 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.6:2.2.6 +google-cloud-spanner-jdbc:2.2.6:2.2.7-SNAPSHOT From e1554d4a92ee0dfc2690ea581f67c565c8c73aff Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Wed, 7 Jul 2021 10:56:24 -0400 Subject: [PATCH 0458/1979] chore: remove distributionManagement section (#530) All java client libraries inherit the distributionManagement section form shared-config. To prevent individual pom files from overriding the shared-config version of distributionManagement, it is being removed. --- java-spanner-jdbc/pom.xml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f96265d3f1e7..e8e09364533d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -40,16 +40,7 @@ https://github.com/googleapis/java-spanner-jdbc/issues GitHub Issues - - - sonatype-nexus-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + Apache-2.0 From cf4b10ac836e391bf36ad6cf1903400b3b50ddd4 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 7 Jul 2021 08:16:25 -0700 Subject: [PATCH 0459/1979] chore: regenerate README (#531) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-07 14:59:54,920 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-07 14:59:56,130 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/ba544d15-79a9-4161-b4d1-03f316693e40/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 2 +- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 109d30036324..4d15e3c6866b 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "37023b8295c97304aa0a55a28f71905fcbf5b93f" + "sha": "0c3d02f41a4a5c5d3c3100c247a3ea2adc9090ff" } }, { diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a35c7eee8a54..e97f2eb8b1f5 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -17,18 +17,18 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.5 + 2.2.6 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.5' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.6' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.5" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.6" ``` ## Authentication From 6b8554ca0c67e0a6370922ac1d31c32620517a5f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 7 Jul 2021 18:41:57 +0200 Subject: [PATCH 0460/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.6 (#526) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d83d18a54c7c..6c2c269e800c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.4 + 2.2.6 From 15d59bcc215484f274fc5a3ef8c0a15f2615bc9b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 9 Jul 2021 16:38:18 +0200 Subject: [PATCH 0461/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.8.0 (#532) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.7.0` -> `20.8.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.8.0/compatibility-slim/20.7.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.8.0/confidence-slim/20.7.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 39610eebba0d..bceb475cdcc5 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.7.0 + 20.8.0 pom import From 5bb4caa47d26516d86e816fb26659a1b831e8a8b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 9 Jul 2021 10:02:09 -0700 Subject: [PATCH 0462/1979] chore: remove All rights reserved clause from java.header (#533) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/76b59ea3-9589-4be2-a86f-50cc3a39422e/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/09c59c20a4bf0daed1665af59035ff240fe356df --- java-spanner-jdbc/java.header | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/java.header b/java-spanner-jdbc/java.header index 3a9b503aa24f..d0970ba7d375 100644 --- a/java-spanner-jdbc/java.header +++ b/java-spanner-jdbc/java.header @@ -1,5 +1,5 @@ ^/\*$ -^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)( All [rR]ights [rR]eserved\.)?$ +^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)$ ^ \*$ ^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ ^ \* you may not use this file except in compliance with the License\.$ diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 1e125704d6ee..959044042f56 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "72d109fdea7e17cda53cffbe640dc51adf4fdf1a" + "sha": "e8539542a64fc839e263f6e181fd8bf69f482d49" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "87254ac89a9559864c0a245d6b150406439ce3d8" + "sha": "09c59c20a4bf0daed1665af59035ff240fe356df" } } ], From 0829e2d46325f5937cdd9d6f54a2a8271edc5d1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 14 Jul 2021 10:44:28 +0200 Subject: [PATCH 0463/1979] feat: add support for tagging to JDBC connection (#270) * feat: add support for tagging to JDBC connection * fix: add ignored differences + default implementations --- .../clirr-ignored-differences.xml | 22 ++++++++++ .../jdbc/CloudSpannerJdbcConnection.java | 41 +++++++++++++++++++ .../cloud/spanner/jdbc/JdbcConnection.java | 32 +++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index ac9c147d1978..0962d5e126ec 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -111,4 +111,26 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setReturnCommitStats(boolean) + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + java.lang.String getTransactionTag() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setTransactionTag(java.lang.String) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + java.lang.String getStatementTag() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setStatementTag(java.lang.String) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 4a5f001a8483..50ae71c56046 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -39,6 +39,47 @@ */ public interface CloudSpannerJdbcConnection extends Connection { + /** + * Sets the transaction tag to use for the current transaction. This method may only be called + * when in a transaction, and before the transaction is actually started, i.e. before any + * statements have been executed in the transaction. + * + *

    The tag will be set as the transaction tag of all statements during the transaction, and as + * the transaction tag of the commit. + * + *

    The transaction tag will automatically be cleared after the transaction has ended. + * + * @param tag The tag to use. + */ + default void setTransactionTag(String tag) throws SQLException { + throw new UnsupportedOperationException(); + }; + + /** @return The transaction tag of the current transaction. */ + default String getTransactionTag() throws SQLException { + throw new UnsupportedOperationException(); + }; + + /** + * Sets the statement tag to use for the next statement that will be executed. The tag is + * automatically cleared after the statement is executed. Statement tags can be used both with + * autocommit=true and autocommit=false, and can be used for partitioned DML. + * + * @param tag The statement tag to use with the next statement that will be executed on this + * connection. + */ + default void setStatementTag(String tag) throws SQLException { + throw new UnsupportedOperationException(); + }; + + /** + * @return The statement tag that will be used with the next statement that is executed on this + * connection. + */ + default String getStatementTag() throws SQLException { + throw new UnsupportedOperationException(); + }; + /** * Sets the transaction mode to use for current transaction. This method may only be called when * in a transaction, and before the transaction is actually started, i.e. before any statements diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index bf9120f536fd..53c1dc096822 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -78,6 +78,38 @@ public String nativeSQL(String sql) throws SQLException { .sqlWithNamedParameters; } + @Override + public String getStatementTag() throws SQLException { + checkClosed(); + return getSpannerConnection().getStatementTag(); + } + + @Override + public void setStatementTag(String tag) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setStatementTag(tag); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public String getTransactionTag() throws SQLException { + checkClosed(); + return getSpannerConnection().getTransactionTag(); + } + + @Override + public void setTransactionTag(String tag) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setTransactionTag(tag); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + @Override public void setTransactionMode(TransactionMode mode) throws SQLException { checkClosed(); From 593aa7409ef613ebe96706b62d4a15ee46d462e8 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 14 Jul 2021 02:06:08 -0700 Subject: [PATCH 0464/1979] chore: regenerate README (#535) This PR was generated using Autosynth. :rainbow:

    Log from Synthtool ``` 2021-07-14 08:46:45,315 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-14 08:46:46,598 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/ae6a79f2-326e-4d4f-ad8d-bf6a5da0ba25/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../readme/synth.metadata/synth.metadata | 4 +- java-spanner-jdbc/README.md | 48 ++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 4d15e3c6866b..0db3e4168aeb 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "0c3d02f41a4a5c5d3c3100c247a3ea2adc9090ff" + "sha": "a4bd82c8e4ce8b7179b943ac06b049598276f1b4" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "39652e3948f455fd0b77535a0145eeec561a3706" + "sha": "959d4f81f2d1397297ebda90212df92aa0ef3a6a" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index e97f2eb8b1f5..8b17696d2b05 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -128,10 +128,50 @@ activate the `shade` profile like this: To get help, follow the instructions in the [shared Troubleshooting document][troubleshooting]. -## Java Versions +## Supported Java Versions Java 8 or above is required for using this client. +Google's Java client libraries, +[Google Cloud Client Libraries][cloudlibs] +and +[Google Cloud API Libraries][apilibs], +follow the +[Oracle Java SE support roadmap][oracle] +(see the Oracle Java SE Product Releases section). + +### For new development + +In general, new feature development occurs with support for the lowest Java +LTS version covered by Oracle's Premier Support (which typically lasts 5 years +from initial General Availability). If the minimum required JVM for a given +library is changed, it is accompanied by a [semver][semver] major release. + +Java 11 and (in September 2021) Java 17 are the best choices for new +development. + +### Keeping production systems current + +Google tests its client libraries with all current LTS versions covered by +Oracle's Extended Support (which typically lasts 8 years from initial +General Availability). + +#### Legacy support + +Google's client libraries support legacy versions of Java runtimes with long +term stable libraries that don't receive feature updates on a best efforts basis +as it may not be possible to backport all patches. + +Google provides updates on a best efforts basis to apps that continue to use +Java 7, though apps might need to upgrade to current versions of the library +that supports their JVM. + +#### Where to find specific information + +The latest versions and the supported Java versions are identified on +the individual GitHub repository `github.com/GoogleAPIs/java-SERVICENAME` +and on [google-cloud-java][g-c-j]. + ## Versioning @@ -191,3 +231,9 @@ Java is a registered trademark of Oracle and/or its affiliates. [libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM [shell_img]: https://gstatic.com/cloudssh/images/open-btn.png + +[semver]: https://semver.org/ +[cloudlibs]: https://cloud.google.com/apis/docs/client-libraries-explained +[apilibs]: https://cloud.google.com/apis/docs/client-libraries-explained#google_api_client_libraries +[oracle]: https://www.oracle.com/java/technologies/java-se-support-roadmap.html +[g-c-j]: http://github.com/googleapis/google-cloud-java From 1796e3ae5f32dc1937677044d4364939e2213c2d Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 15 Jul 2021 07:28:15 -0700 Subject: [PATCH 0465/1979] chore: add dependencyDashboardLabels to renovate.json (#536) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/d9079f8e-3fa1-44e6-b6d8-65a7341e9be2/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/5d3c52f5db664eee9026db76b5bcb466f3a09ca9 --- java-spanner-jdbc/renovate.json | 5 ++++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 4ac4d97c635c..a95a109bdda5 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -69,5 +69,8 @@ } ], "semanticCommits": true, - "masterIssue": true + "dependencyDashboard": true, + "dependencyDashboardLabels": [ + "type: process" + ] } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 959044042f56..50c74895a2b4 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "e8539542a64fc839e263f6e181fd8bf69f482d49" + "sha": "7a6953004fd1401a98f95ea3b351662eb8ab81d7" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "09c59c20a4bf0daed1665af59035ff240fe356df" + "sha": "5d3c52f5db664eee9026db76b5bcb466f3a09ca9" } } ], From 730a8b14eca5383b44e2f29cb31c2a9c22324fec Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 19 Jul 2021 11:24:39 +0200 Subject: [PATCH 0466/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.0 (#537) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e8e09364533d..b5fc0bb7eae5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.9.1 + 6.10.0 pom import From a5754804ec8765d1f4f26ebad89daf11bc922d95 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 27 Jul 2021 22:48:31 +0200 Subject: [PATCH 0467/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.13.1 (#541) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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) | `0.12.0` -> `0.13.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.13.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.13.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.13.1/compatibility-slim/0.12.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.13.1/confidence-slim/0.12.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v0.13.1`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​0131-httpswwwgithubcomgoogleapisjava-shared-configcomparev0130v0131-2021-07-27) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v0.13.0...v0.13.1) ### [`v0.13.0`](https://togithub.com/googleapis/java-shared-config/releases/v0.13.0) ##### Features - add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#​264](https://www.github.com/googleapis/java-shared-config/issues/264)) ([d274af8](https://www.github.com/googleapis/java-shared-config/commit/d274af836ac9b3e98be84e551b7e9e552397ecc1)) ##### Bug Fixes - Add shopt -s nullglob to dependencies script ([865ca3c](https://www.github.com/googleapis/java-shared-config/commit/865ca3cbf106a7aaae1a989320a1ad5a47b6ffaf)) - Update dependencies.sh to not break on mac ([#​276](https://www.github.com/googleapis/java-shared-config/issues/276)) ([865ca3c](https://www.github.com/googleapis/java-shared-config/commit/865ca3cbf106a7aaae1a989320a1ad5a47b6ffaf)) ##### Dependencies - update auto-value-annotation.version to v1.8.2 ([#​275](https://www.github.com/googleapis/java-shared-config/issues/275)) ([4d15246](https://www.github.com/googleapis/java-shared-config/commit/4d152461a5592940a8be762c7a8698a02dbe26cf)) - update dependency com.puppycrawl.tools:checkstyle to v8.43 ([#​266](https://www.github.com/googleapis/java-shared-config/issues/266)) ([fae7961](https://www.github.com/googleapis/java-shared-config/commit/fae7961412b33e34e8fcfec78d1451894d4e61d9)) - update dependency com.puppycrawl.tools:checkstyle to v8.44 ([#​274](https://www.github.com/googleapis/java-shared-config/issues/274)) ([d53d0e0](https://www.github.com/googleapis/java-shared-config/commit/d53d0e0935e908d16f4e7cf763577cf3fd8128d3)) ***
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b5fc0bb7eae5..81b02cdd945e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.12.0 + 0.13.1 From 337887b3d1f6fffaab66f8e4aed9e225ba287ffe Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 27 Jul 2021 14:12:31 -0700 Subject: [PATCH 0468/1979] chore: regenerate README (#542) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-27 20:52:25,206 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-27 20:52:26,466 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/7ded6de6-d25f-40c9-81f2-ea9cb5641798/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 0db3e4168aeb..7cd540889887 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a4bd82c8e4ce8b7179b943ac06b049598276f1b4" + "sha": "68125c4d896a24f186d90648d3be64b5ad15aa37" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "959d4f81f2d1397297ebda90212df92aa0ef3a6a" + "sha": "3d32990b6f4b57be77455e3ca89e6e21cd0c06b3" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8b17696d2b05..7486c06df98f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -8,11 +8,13 @@ Java idiomatic client for [Google Cloud Spanner JDBC][product-docs]. - [Product Documentation][product-docs] - [Client Library Documentation][javadocs] + ## Quickstart If you are using Maven, add this to your pom.xml file: + ```xml com.google.cloud @@ -22,11 +24,13 @@ If you are using Maven, add this to your pom.xml file: ``` If you are using Gradle without BOM, add this to your dependencies + ```Groovy compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.6' ``` If you are using SBT, add this to your dependencies + ```Scala libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.6" ``` @@ -35,6 +39,10 @@ libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.6 See the [Authentication][authentication] section in the base directory's README. +## Authorization + +The client application making API calls must be granted [authorization scopes][auth-scopes] required for the desired Google Cloud Spanner JDBC APIs, and the authenticated principal must have the [IAM role(s)][predefined-iam-roles] required to access GCP resources using the Google Cloud Spanner JDBC API calls. + ## Getting Started ### Prerequisites @@ -178,6 +186,7 @@ and on [google-cloud-java][g-c-j]. This library follows [Semantic Versioning](http://semver.org/). + ## Contributing @@ -189,6 +198,7 @@ Please note that this project is released with a Contributor Code of Conduct. By this project you agree to abide by its terms. See [Code of Conduct][code-of-conduct] for more information. + ## License Apache 2.0 - See [LICENSE][license] for more information. @@ -220,6 +230,9 @@ Java is a registered trademark of Oracle and/or its affiliates. [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner-jdbc.svg [maven-version-link]: https://search.maven.org/search?q=g:com.google.cloud%20AND%20a:google-cloud-spanner-jdbc&core=gav [authentication]: https://github.com/googleapis/google-cloud-java#authentication +[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes +[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles +[iam-policy]: https://cloud.google.com/iam/docs/overview#cloud-iam-policy [developer-console]: https://console.developers.google.com/ [create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects [cloud-sdk]: https://cloud.google.com/sdk/ From b3ce834f0d8318354d1c362455f0b6c90be55c43 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 28 Jul 2021 01:24:26 +0200 Subject: [PATCH 0469/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v20.9.0 (#539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.8.0` -> `20.9.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.9.0/compatibility-slim/20.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.9.0/confidence-slim/20.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index bceb475cdcc5..23c5d00e8407 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.8.0 + 20.9.0 pom import From 5e1590180a1911819b751e4f71b8afb68ef879f9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 29 Jul 2021 21:57:42 +0200 Subject: [PATCH 0470/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1 (#543) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 81b02cdd945e..c54c39ef55b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 0.13.1 + 1.0.0 From d27dd3e2c0e3fd21b2614526d642c632d348fa05 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 12 Aug 2021 00:16:58 +0200 Subject: [PATCH 0471/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2 (#544) * deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2 * Update pom.xml Co-authored-by: Neenu Shaji --- java-spanner-jdbc/pom.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c54c39ef55b0..edf705fe518a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 1.4.0 + 2.0.1 pom import @@ -154,6 +154,12 @@ truth ${truth.version} test + + + org.checkerframework + checker-qual + + org.hamcrest From a5f61e69601fcab92fed72a58197d6e0009e2717 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:22:09 +0000 Subject: [PATCH 0472/1979] chore: release 2.3.0 (#534) :robot: I have created a release \*beep\* \*boop\* --- ## [2.3.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.6...v2.3.0) (2021-08-11) ### Features * add support for tagging to JDBC connection ([#270](https://www.github.com/googleapis/java-spanner-jdbc/issues/270)) ([0829e2d](https://www.github.com/googleapis/java-spanner-jdbc/commit/0829e2d46325f5937cdd9d6f54a2a8271edc5d1c)) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2 ([#544](https://www.github.com/googleapis/java-spanner-jdbc/issues/544)) ([d27dd3e](https://www.github.com/googleapis/java-spanner-jdbc/commit/d27dd3e2c0e3fd21b2614526d642c632d348fa05)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.0 ([#537](https://www.github.com/googleapis/java-spanner-jdbc/issues/537)) ([730a8b1](https://www.github.com/googleapis/java-spanner-jdbc/commit/730a8b14eca5383b44e2f29cb31c2a9c22324fec)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 55b6ee3745b7..9ffbaac49310 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.3.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.6...v2.3.0) (2021-08-11) + + +### Features + +* add support for tagging to JDBC connection ([#270](https://www.github.com/googleapis/java-spanner-jdbc/issues/270)) ([a4bd82c](https://www.github.com/googleapis/java-spanner-jdbc/commit/a4bd82c8e4ce8b7179b943ac06b049598276f1b4)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2 ([#544](https://www.github.com/googleapis/java-spanner-jdbc/issues/544)) ([366430d](https://www.github.com/googleapis/java-spanner-jdbc/commit/366430dc270edd09de1a0749ba360f312897b1aa)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.0 ([#537](https://www.github.com/googleapis/java-spanner-jdbc/issues/537)) ([8655ae5](https://www.github.com/googleapis/java-spanner-jdbc/commit/8655ae5955f5385a9d6445e13264427d73c4d37e)) + ### [2.2.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.5...v2.2.6) (2021-07-06) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index edf705fe518a..789a4b77c83f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.2.7-SNAPSHOT + 2.3.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 32249bb7427c..6f757a5926ba 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.7-SNAPSHOT + 2.3.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index dd8f71e62a22..4fc1d7c3d8b9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.2.6:2.2.7-SNAPSHOT +google-cloud-spanner-jdbc:2.3.0:2.3.0 From 21a65ef0b08dc825c65a358fb12c4360b4b85d1c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:44:14 +0000 Subject: [PATCH 0473/1979] chore: release 2.3.1-SNAPSHOT (#545) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 789a4b77c83f..64c93863570f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.0 + 2.3.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6f757a5926ba..45434d116051 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.0 + 2.3.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4fc1d7c3d8b9..746b1354adce 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.0:2.3.0 +google-cloud-spanner-jdbc:2.3.0:2.3.1-SNAPSHOT From d0bc6413f17824af7c02134bacb29b4b7bce74d5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 12 Aug 2021 19:44:17 +0200 Subject: [PATCH 0474/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.1 (#538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.10.0` -> `6.10.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.10.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.10.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.10.1/compatibility-slim/6.10.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.10.1/confidence-slim/6.10.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.10.1`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​6101-httpswwwgithubcomgoogleapisjava-spannercomparev6100v6101-2021-07-21) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.10.0...v6.10.1)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 64c93863570f..639a43ae756b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.10.0 + 6.10.1 pom import From 8ef855fdb28be2e089a5144098522dc5c645704f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 18:06:19 +0000 Subject: [PATCH 0475/1979] chore: release 2.3.1 (#546) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.0...v2.3.1) (2021-08-12) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.1 ([#538](https://www.github.com/googleapis/java-spanner-jdbc/issues/538)) ([d0bc641](https://www.github.com/googleapis/java-spanner-jdbc/commit/d0bc6413f17824af7c02134bacb29b4b7bce74d5)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 9ffbaac49310..b14c8e0651b3 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.3.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.0...v2.3.1) (2021-08-12) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.1 ([#538](https://www.github.com/googleapis/java-spanner-jdbc/issues/538)) ([75507c4](https://www.github.com/googleapis/java-spanner-jdbc/commit/75507c4a42c3b051e8a14c1233b3b2526c0d3ccc)) + ## [2.3.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.2.6...v2.3.0) (2021-08-11) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 639a43ae756b..9d541d57a34a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.1-SNAPSHOT + 2.3.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 45434d116051..7b7d4b2deec9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.1-SNAPSHOT + 2.3.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 746b1354adce..18bfe53d8b6f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.0:2.3.1-SNAPSHOT +google-cloud-spanner-jdbc:2.3.1:2.3.1 From d39af1d114c4867a7b4dd0272af802b319e99e01 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 18:22:40 +0000 Subject: [PATCH 0476/1979] chore: release 2.3.2-SNAPSHOT (#547) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9d541d57a34a..593b17611f06 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.1 + 2.3.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 7b7d4b2deec9..4bd9264bd6c6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.1 + 2.3.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 18bfe53d8b6f..0235542b6a1e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.1:2.3.1 +google-cloud-spanner-jdbc:2.3.1:2.3.2-SNAPSHOT From 5cd40339b2989eb877f79d66be2b27eaae644c33 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 12 Aug 2021 22:10:34 +0200 Subject: [PATCH 0477/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.0 (#549) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.10.1` -> `6.11.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.11.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.11.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.11.0/compatibility-slim/6.10.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.11.0/confidence-slim/6.10.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.11.0`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​6110-httpswwwgithubcomgoogleapisjava-spannercomparev6101v6110-2021-08-12) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.10.1...v6.11.0) ##### Features - release gapic-generator-java v2.0.0 ([#​1334](https://www.github.com/googleapis/java-spanner/issues/1334)) ([368fb80](https://www.github.com/googleapis/java-spanner/commit/368fb80e8ae9fd9bee7af81c13bef32b26361877)) ##### Documentation - use 'latest' stats package in samples to prevent build failures ([#​1313](https://www.github.com/googleapis/java-spanner/issues/1313)) ([6a8351c](https://www.github.com/googleapis/java-spanner/commit/6a8351c9d2cf0fe805b87a611ff1d94d4dba3f87)), closes [#​1273](https://www.github.com/googleapis/java-spanner/issues/1273) ##### Dependencies - update dependency com.google.cloud:google-cloud-monitoring to v3 ([#​1341](https://www.github.com/googleapis/java-spanner/issues/1341)) ([de7b540](https://www.github.com/googleapis/java-spanner/commit/de7b54094b6bb2928616e2e04215f4ba5b8bc750)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v2 ([#​1331](https://www.github.com/googleapis/java-spanner/issues/1331)) ([cd1ad7b](https://www.github.com/googleapis/java-spanner/commit/cd1ad7b4cd1716b60f3f96ee953f76c126742788)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.0.1 ([#​1344](https://www.github.com/googleapis/java-spanner/issues/1344)) ([300837f](https://www.github.com/googleapis/java-spanner/commit/300837f0a27dab89285895f753aececb8d641da9)) - update dependency com.google.cloud:google-cloud-trace to v2 ([#​1342](https://www.github.com/googleapis/java-spanner/issues/1342)) ([d24886b](https://www.github.com/googleapis/java-spanner/commit/d24886b058fd87ea744a4f375fb6affd8f9398d9)) ##### [6.10.1](https://www.github.com/googleapis/java-spanner/compare/v6.10.0...v6.10.1) (2021-07-21) ##### Dependencies - update dependency com.google.cloud:grpc-gcp to v1.1.0 ([#​1306](https://www.github.com/googleapis/java-spanner/issues/1306)) ([fa0c65d](https://www.github.com/googleapis/java-spanner/commit/fa0c65dc31236e05e6b10508281cf58e82ee87ef))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 593b17611f06..4ab07400a9df 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.10.1 + 6.11.0 pom import From eb126670979eeeef8866e8d754f4cce15f392189 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 20:30:21 +0000 Subject: [PATCH 0478/1979] chore: release 2.3.2 (#550) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.1...v2.3.2) (2021-08-12) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.0 ([#549](https://www.github.com/googleapis/java-spanner-jdbc/issues/549)) ([5cd4033](https://www.github.com/googleapis/java-spanner-jdbc/commit/5cd40339b2989eb877f79d66be2b27eaae644c33)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b14c8e0651b3..c64425ec0a3d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.3.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.1...v2.3.2) (2021-08-12) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.0 ([#549](https://www.github.com/googleapis/java-spanner-jdbc/issues/549)) ([2639e40](https://www.github.com/googleapis/java-spanner-jdbc/commit/2639e40ebbde19966653f06f8b664106568f6bac)) + ### [2.3.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.0...v2.3.1) (2021-08-12) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4ab07400a9df..dfb221eb475e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.2-SNAPSHOT + 2.3.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4bd9264bd6c6..471c2b1f2a6c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.2-SNAPSHOT + 2.3.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0235542b6a1e..1b7e21b20141 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.1:2.3.2-SNAPSHOT +google-cloud-spanner-jdbc:2.3.2:2.3.2 From 9005bb1ca3b93c70dd8d49180785a36177f6b809 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 12 Aug 2021 13:34:19 -0700 Subject: [PATCH 0479/1979] chore: regenerate README (#551) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-12 20:14:23,342 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-12 20:14:24,558 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/16f91a02-9987-4387-964e-2ee273dbe88d/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 7cd540889887..3ca93240260b 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "68125c4d896a24f186d90648d3be64b5ad15aa37" + "sha": "2639e40ebbde19966653f06f8b664106568f6bac" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "3d32990b6f4b57be77455e3ca89e6e21cd0c06b3" + "sha": "ff01716e16d2c6e87eaf87197b753ac9fcbbed5d" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7486c06df98f..0bb25af6b738 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.2.6 + 2.3.1 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.2.6' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.2.6" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.1" ``` ## Authentication From 06fb837c4d2ef416bba798c6dece517c5a37e673 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 20:48:33 +0000 Subject: [PATCH 0480/1979] chore: release 2.3.3-SNAPSHOT (#552) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dfb221eb475e..a6816e0bd370 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.2 + 2.3.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 471c2b1f2a6c..5da03ec3982f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.2 + 2.3.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1b7e21b20141..68b908b1b811 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.2:2.3.2 +google-cloud-spanner-jdbc:2.3.2:2.3.3-SNAPSHOT From 2b20fb3ce7ef4233546535f782871343d625c09b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 15 Aug 2021 17:59:07 -0700 Subject: [PATCH 0481/1979] build(java): use ENABLE_FLAKYBOT env variable (#553) Kokoro job config now supports both environment variables during this migration period. Source-Author: Jeff Ching Source-Date: Thu Aug 12 10:10:27 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: ff01716e16d2c6e87eaf87197b753ac9fcbbed5d Source-Link: https://github.com/googleapis/synthtool/commit/ff01716e16d2c6e87eaf87197b753ac9fcbbed5d --- java-spanner-jdbc/.kokoro/build.sh | 2 +- java-spanner-jdbc/.kokoro/nightly/integration.cfg | 2 +- java-spanner-jdbc/.kokoro/nightly/samples.cfg | 2 +- java-spanner-jdbc/synth.metadata | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 163c8526dd4e..a4c46cfcaafb 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -115,7 +115,7 @@ fi # fix output location of logs bash .kokoro/coerce_logs.sh -if [[ "${ENABLE_BUILD_COP}" == "true" ]] +if [[ "${ENABLE_FLAKYBOT}" == "true" ]] then chmod +x ${KOKORO_GFILE_DIR}/linux_amd64/flakybot ${KOKORO_GFILE_DIR}/linux_amd64/flakybot -repo=googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index 0048c8ece7e5..e51c7b4c6c11 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -22,7 +22,7 @@ env_vars: { } env_vars: { - key: "ENABLE_BUILD_COP" + key: "ENABLE_FLAKYBOT" value: "true" } diff --git a/java-spanner-jdbc/.kokoro/nightly/samples.cfg b/java-spanner-jdbc/.kokoro/nightly/samples.cfg index f25429314f4d..9761fd8648cb 100644 --- a/java-spanner-jdbc/.kokoro/nightly/samples.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/samples.cfg @@ -33,6 +33,6 @@ env_vars: { } env_vars: { - key: "ENABLE_BUILD_COP" + key: "ENABLE_FLAKYBOT" value: "true" } diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 50c74895a2b4..8f46bdb7c156 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "7a6953004fd1401a98f95ea3b351662eb8ab81d7" + "sha": "813a13d993ef2ad61ca7acda6700760a4cfcd512" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5d3c52f5db664eee9026db76b5bcb466f3a09ca9" + "sha": "ff01716e16d2c6e87eaf87197b753ac9fcbbed5d" } } ], From 4ce42e53185291fd8f96adc1886205bcb712a6f2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 16 Aug 2021 02:59:29 +0200 Subject: [PATCH 0482/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.3.2 (#548) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6c2c269e800c..a77aa2dcfea4 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.2.6 + 2.3.2 From 451d3cfde18ab1eb6c107c186b6a87294c05429e Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Sun, 15 Aug 2021 18:20:23 -0700 Subject: [PATCH 0483/1979] chore: regenerate README (#554) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-16 01:01:15,979 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-16 01:01:17,256 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/89da9f1b-f590-497f-968b-a6f0fc752b78/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 3ca93240260b..86de07c90cfe 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "2639e40ebbde19966653f06f8b664106568f6bac" + "sha": "95d6cbaaf28728258e916aa1dcf45b0dd1b7fd71" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ff01716e16d2c6e87eaf87197b753ac9fcbbed5d" + "sha": "facee4cc1ea096cd8bcc008bb85929daa7c414c0" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0bb25af6b738..ac433e67c9ae 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.3.1 + 2.3.2 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.1' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.2' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.2" ``` ## Authentication From b9b8a885b681668913a30cc0905f6ae5844fce24 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 17 Aug 2021 16:56:20 +0200 Subject: [PATCH 0484/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v21 (#555) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.9.0` -> `21.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/21.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/21.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/21.0.0/compatibility-slim/20.9.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/21.0.0/confidence-slim/20.9.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 23c5d00e8407..ae8f5954d966 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 20.9.0 + 21.0.0 pom import From 80a7010906cc88bae1fd1218dbeca4df112c7823 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 19 Aug 2021 06:49:30 +0200 Subject: [PATCH 0485/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.1 (#556) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a6816e0bd370..e3eac26fe8e5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.11.0 + 6.11.1 pom import From ad98c8e064393d01299a627c866f2c6c52f34f85 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 19 Aug 2021 05:06:20 +0000 Subject: [PATCH 0486/1979] chore: release 2.3.3 (#559) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.2...v2.3.3) (2021-08-19) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.1 ([#556](https://www.github.com/googleapis/java-spanner-jdbc/issues/556)) ([80a7010](https://www.github.com/googleapis/java-spanner-jdbc/commit/80a7010906cc88bae1fd1218dbeca4df112c7823)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c64425ec0a3d..842676451c9a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.3.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.2...v2.3.3) (2021-08-19) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.1 ([#556](https://www.github.com/googleapis/java-spanner-jdbc/issues/556)) ([36f0d32](https://www.github.com/googleapis/java-spanner-jdbc/commit/36f0d32aec65f098f7091d44a0e4acc98104aeb9)) + ### [2.3.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.1...v2.3.2) (2021-08-12) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e3eac26fe8e5..65b1f53f7956 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.3-SNAPSHOT + 2.3.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5da03ec3982f..1c48ce6d3b5e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.3-SNAPSHOT + 2.3.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 68b908b1b811..c341bbba09ef 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.2:2.3.3-SNAPSHOT +google-cloud-spanner-jdbc:2.3.3:2.3.3 From cbf0dcfd969b8c3d78779e60f26acaac0a4c4404 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 19 Aug 2021 05:22:24 +0000 Subject: [PATCH 0487/1979] chore: release 2.3.4-SNAPSHOT (#560) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 65b1f53f7956..9e2c996ae744 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.3 + 2.3.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1c48ce6d3b5e..4b7b1494b760 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.3 + 2.3.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c341bbba09ef..366b1680e734 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.3:2.3.3 +google-cloud-spanner-jdbc:2.3.3:2.3.4-SNAPSHOT From c11e43f7187c22ddf9200048a0fc90836611e665 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 19 Aug 2021 18:11:58 +0200 Subject: [PATCH 0488/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.3.3 (#561) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a77aa2dcfea4..e18c081e43d2 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.2 + 2.3.3 From dd0436368a88b1e381b5f4ff9475507ebdccf927 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 19 Aug 2021 09:34:24 -0700 Subject: [PATCH 0489/1979] chore: regenerate README (#562) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-19 16:14:05,660 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-19 16:14:06,662 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/42ee00f6-6a53-49f5-89dd-60be3f7682e4/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 86de07c90cfe..05a0f5ca18db 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "95d6cbaaf28728258e916aa1dcf45b0dd1b7fd71" + "sha": "a09b94bd75d3db728e187478a30a5589ac037aa7" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "facee4cc1ea096cd8bcc008bb85929daa7c414c0" + "sha": "484b7ec7bdef3909589a83e3d763e7588cb8c37c" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ac433e67c9ae..515d5dad151b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.3.2 + 2.3.3 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.2' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.3' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.3" ``` ## Authentication From 7c8f03715376f030e19427a2ec393489299bd0d5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 19 Aug 2021 20:55:54 +0200 Subject: [PATCH 0490/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.0.1 (#557) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9e2c996ae744..05b9bd78daee 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.0.0 + 1.0.1 From 2352f1ac16814c1af693d79bba38c7f7aa517fe9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 23 Aug 2021 22:58:19 +0200 Subject: [PATCH 0491/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.1.0 (#563) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.0.1` -> `2.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.1.0/compatibility-slim/2.0.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.1.0/confidence-slim/2.0.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.1.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​210-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare201v210-2021-08-23) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.0.1...v2.1.0) ##### Dependencies - update dependency com.google.auth:google-auth-library-bom to v1.1.0 ([#​439](https://www.togithub.com/googleapis/java-shared-dependencies/issues/439)) ([ca52bd9](https://www.github.com/googleapis/java-shared-dependencies/commit/ca52bd9c099c96bf7b5a57aa85d39b58a610c875)) - update dependency com.google.cloud:google-cloud-core-bom to v2.1.0 ([#​444](https://www.togithub.com/googleapis/java-shared-dependencies/issues/444)) ([ff914c6](https://www.github.com/googleapis/java-shared-dependencies/commit/ff914c6de9e3e7fa6ba75591d3d5077c5421827d)) - update dependency com.google.code.gson:gson to v2.8.8 ([#​442](https://www.togithub.com/googleapis/java-shared-dependencies/issues/442)) ([79a093f](https://www.github.com/googleapis/java-shared-dependencies/commit/79a093f9ccea4d47cf8b678570a1c9699029a8b2)) - update dependency com.google.errorprone:error_prone_annotations to v2.9.0 ([#​441](https://www.togithub.com/googleapis/java-shared-dependencies/issues/441)) ([e644a4b](https://www.github.com/googleapis/java-shared-dependencies/commit/e644a4b504ab8aa5771f9be36861d1730ea9bcc9)) - update dependency io.grpc:grpc-bom to v1.40.0 ([#​438](https://www.togithub.com/googleapis/java-shared-dependencies/issues/438)) ([c3f8fb4](https://www.github.com/googleapis/java-shared-dependencies/commit/c3f8fb4408f5dc6c7f7dc0e14f0c24fa755433a5)) - update gax.version to v2.3.0 ([#​437](https://www.togithub.com/googleapis/java-shared-dependencies/issues/437)) ([e59aaad](https://www.github.com/googleapis/java-shared-dependencies/commit/e59aaadd76e40ab5ea31c3e812686a4ba0471a49)) ##### [2.0.1](https://www.github.com/googleapis/java-shared-dependencies/compare/2.0.0...v2.0.1) (2021-08-11) ##### Dependencies - update dependency com.google.api:api-common to v2.0.1 ([#​431](https://www.togithub.com/googleapis/java-shared-dependencies/issues/431)) ([b1a52c8](https://www.github.com/googleapis/java-shared-dependencies/commit/b1a52c83e19be7be80086f2010e928171b046f62)) - update gax.version to v2.1.0 ([#​432](https://www.togithub.com/googleapis/java-shared-dependencies/issues/432)) ([7f53006](https://www.github.com/googleapis/java-shared-dependencies/commit/7f53006d021e839f52325a87d7c4715eff88818d)) - update google.core.version to v2.0.4 ([#​430](https://www.togithub.com/googleapis/java-shared-dependencies/issues/430)) ([d0465ad](https://www.github.com/googleapis/java-shared-dependencies/commit/d0465ad3a79993d4e854078ea992e53ab9add07f)) - update google.core.version to v2.0.5 ([#​434](https://www.togithub.com/googleapis/java-shared-dependencies/issues/434)) ([af00753](https://www.github.com/googleapis/java-shared-dependencies/commit/af0075390034cba5cefede8260ab03f728d525a8))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 05b9bd78daee..9faa07dc2fc5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.0.1 + 2.1.0 pom import From 6437a1af7f9111e23f98edea07eb89c96f03e63d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 21:40:31 +0000 Subject: [PATCH 0492/1979] chore: release 2.3.4 (#564) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.3...v2.3.4) (2021-08-23) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.1.0 ([#563](https://www.github.com/googleapis/java-spanner-jdbc/issues/563)) ([2352f1a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2352f1ac16814c1af693d79bba38c7f7aa517fe9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 842676451c9a..a0d2c22193f9 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.3.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.3...v2.3.4) (2021-08-23) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.1.0 ([#563](https://www.github.com/googleapis/java-spanner-jdbc/issues/563)) ([b0959a4](https://www.github.com/googleapis/java-spanner-jdbc/commit/b0959a412bae1a8024de92d5f9699d49863fb088)) + ### [2.3.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.2...v2.3.3) (2021-08-19) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9faa07dc2fc5..766098305df7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.4-SNAPSHOT + 2.3.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4b7b1494b760..c1b7c1cf501d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.4-SNAPSHOT + 2.3.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 366b1680e734..fdfff4feb645 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.3:2.3.4-SNAPSHOT +google-cloud-spanner-jdbc:2.3.4:2.3.4 From 27f105043f46e7428ea949013a73916e58e7b946 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 22:08:27 +0000 Subject: [PATCH 0493/1979] chore: release 2.3.5-SNAPSHOT (#565) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 766098305df7..6cfb6696098f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.4 + 2.3.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c1b7c1cf501d..935edd15c7b0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.4 + 2.3.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fdfff4feb645..fc32259011f7 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.4:2.3.4 +google-cloud-spanner-jdbc:2.3.4:2.3.5-SNAPSHOT From 8b36104f0d050c529b89191e34271c07a7b87405 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 24 Aug 2021 09:45:13 +0200 Subject: [PATCH 0494/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.0 (#568) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6cfb6696098f..60c54c55c52f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.11.1 + 6.12.0 pom import From 40ab5c28ecd4557b5e4914cacc7e926853b5b860 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 24 Aug 2021 10:48:21 +0200 Subject: [PATCH 0495/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.3.4 (#566) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e18c081e43d2..93f09b8338b2 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.3 + 2.3.4 From 514f8f26eca8cfa21590949828ef7d0dd43c8a6b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Aug 2021 10:16:24 +0000 Subject: [PATCH 0496/1979] chore: release 2.3.5 (#569) :robot: I have created a release \*beep\* \*boop\* --- ### [2.3.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.4...v2.3.5) (2021-08-24) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.0 ([#568](https://www.github.com/googleapis/java-spanner-jdbc/issues/568)) ([8b36104](https://www.github.com/googleapis/java-spanner-jdbc/commit/8b36104f0d050c529b89191e34271c07a7b87405)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a0d2c22193f9..315f5f2e69de 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.3.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.4...v2.3.5) (2021-08-24) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.0 ([#568](https://www.github.com/googleapis/java-spanner-jdbc/issues/568)) ([c032204](https://www.github.com/googleapis/java-spanner-jdbc/commit/c032204445d61c60385232216cdb52c217a85725)) + ### [2.3.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.3...v2.3.4) (2021-08-23) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 60c54c55c52f..d653b420d65f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.5-SNAPSHOT + 2.3.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 935edd15c7b0..0c79a23c5dc5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.5-SNAPSHOT + 2.3.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fc32259011f7..cc248652ff02 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.4:2.3.5-SNAPSHOT +google-cloud-spanner-jdbc:2.3.5:2.3.5 From 39e78b87ec0a38f68241845571f1168bcb4211e9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 Aug 2021 10:34:24 +0000 Subject: [PATCH 0497/1979] chore: release 2.3.6-SNAPSHOT (#571) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d653b420d65f..1fc8eb149795 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.5 + 2.3.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0c79a23c5dc5..7d0dbe5006a2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.5 + 2.3.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index cc248652ff02..4e03da498f95 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.5:2.3.5 +google-cloud-spanner-jdbc:2.3.5:2.3.6-SNAPSHOT From 9513689f49f67a576e089d9ee2489d523d3e92f6 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 24 Aug 2021 05:52:24 -0700 Subject: [PATCH 0498/1979] chore: regenerate README (#570) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-24 07:47:44,406 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-24 07:47:45,749 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/d36a3743-3de1-419d-b05e-ef8831fed40d/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index 05a0f5ca18db..a3c3f88b59ca 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "a09b94bd75d3db728e187478a30a5589ac037aa7" + "sha": "c032204445d61c60385232216cdb52c217a85725" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "484b7ec7bdef3909589a83e3d763e7588cb8c37c" + "sha": "8032ab5a32471d85ece8fc261df16cc40fbfa4fb" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 515d5dad151b..b5bcdae1c252 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.3.3 + 2.3.4 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.3' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.4' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.4" ``` ## Authentication From 5a14255ea93a75e844bd7a18cba823e63ad01fec Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 24 Aug 2021 06:10:24 -0700 Subject: [PATCH 0499/1979] chore: regenerate README (#573) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-24 12:54:29,931 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-24 12:54:30,999 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/29f19505-14bd-4aa6-a752-80c9daa7dee0/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 2 +- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index a3c3f88b59ca..ee98f7c4710e 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "c032204445d61c60385232216cdb52c217a85725" + "sha": "53114ec7393e7ff5d0c1f01082eaa0aceeb3bf10" } }, { diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index b5bcdae1c252..8bfaf97841f4 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.3.4 + 2.3.5 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.4' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.5' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.4" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.5" ``` ## Authentication From 874ba3f0456469b7fd6de7a02f17222b69854a85 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 24 Aug 2021 15:23:18 +0200 Subject: [PATCH 0500/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.3.5 (#572) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 93f09b8338b2..7de5356db118 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.4 + 2.3.5 From f0ac11045fa3d10f531e2e9f82a5c31140c74da4 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Tue, 24 Aug 2021 14:33:14 -0400 Subject: [PATCH 0501/1979] ci: removing linkage-monitor from the required checks (#575) Linkage Monitor is no longer needed, because the Libraries BOM synchronizes with Google Cloud BOM and the shared dependencies BOM https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/2137 --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 26d3273bb356..8a024006a783 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -31,7 +31,6 @@ branchProtectionRules: requiredStatusCheckContexts: - "dependencies (8)" - "dependencies (11)" - - "linkage-monitor" - "lint" - "clirr" - "units (8)" @@ -57,7 +56,6 @@ branchProtectionRules: requiredStatusCheckContexts: - "dependencies (8)" - "dependencies (11)" - - "linkage-monitor" - "lint" - "clirr" - "units (7)" From d63167206b9c0a79089da74e45b41146770f915d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 25 Aug 2021 08:23:17 +0200 Subject: [PATCH 0502/1979] feat: support JSON data type (#447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support JSON data type fix: NPE was thrown when getting an array of structs from a ResultSet (#445) A NullPointerException was thrown if a ResultSet contained an array of Structs and the getArray() method was called on the column. Fixes #444 fix: cleanup and add documentation chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.0.2 (#443) chore: regenerate README (#450) chore(deps): update dependency com.google.cloud:libraries-bom to v20.2.0 (#448) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.1.0` -> `20.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/compatibility-slim/20.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.2.0/confidence-slim/20.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- :date: **Schedule**: At any time (no schedule defined). :vertical_traffic_light: **Automerge**: Disabled by config. Please merge this manually once you are satisfied. :recycle: **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. :no_bell: **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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: add SECURITY.md (#446) chore: add SECURITY.md feat: allow get/set Spanner Value instances (#454) Adds support for getting a value from a `java.sql.ResultSet` as a `com.google.cloud.spanner.Value` instance, and for setting a parameter on a `java.sql.PreparedStatement` using a `com.google.cloud.spanner.Value` instance. Fixes #452 build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.1.2 (#451) deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 (#453) chore: remove unused statements file (#458) The ClientSideStatements.json file has been moved to the Connection API in the client library and is not needed in the JDBC driver. chore: release 2.0.3-SNAPSHOT (#442) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> chore: adding cloud-rad java xrefs (#461) Source-Author: Emily Ball Source-Date: Thu May 6 11:48:47 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 046994f491c02806aea60118e214a9edd67f5ab7 Source-Link: https://github.com/googleapis/synthtool/commit/046994f491c02806aea60118e214a9edd67f5ab7 deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 (#463) [![WhiteSource 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/java-shared-dependencies) | `1.0.0` -> `1.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/compatibility-slim/1.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.1.0/confidence-slim/1.0.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-shared-dependencies [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.0.0...v1.1.0) - update dependency com.google.protobuf:protobuf-bom to v3.16.0 ([#​348](https://www.github.com/googleapis/java-shared-dependencies/issues/348)) ([0aacfde](https://www.github.com/googleapis/java-shared-dependencies/commit/0aacfdeec70e30803734db8287c47e4fad5481ef)) - update gax.version to v1.64.0 ([#​345](https://www.github.com/googleapis/java-shared-dependencies/issues/345)) ([478bd35](https://www.github.com/googleapis/java-shared-dependencies/commit/478bd35296293e81c7e70157f50bfbebdc1bb54d)) - update iam.version to v1.0.13 ([#​343](https://www.github.com/googleapis/java-shared-dependencies/issues/343)) ([3637923](https://www.github.com/googleapis/java-shared-dependencies/commit/363792392b71deff5cc5731104b631122fba5e61))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore(deps): update dependency com.google.cloud:libraries-bom to v20.3.0 (#462) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.2.0` -> `20.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/compatibility-slim/20.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.3.0/confidence-slim/20.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). build(java): remove codecov action (#465) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/8e8c0070-26ea-4d86-b07a-e4dcc9e5b8b1/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/4f4b1b9b8d8b52f1e9e4a76165896debce5ab7f1 chore(deps): update dependency com.google.cloud:libraries-bom to v20.4.0 (#466) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.3.0` -> `20.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/compatibility-slim/20.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.4.0/confidence-slim/20.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: add changelog to cloud-rad (#467) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/41862329-45d0-4225-9ed2-ad5a75997ae8/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/c86c7a60985644eab557949363a38301d40d78d2 tests: fixes jdbc query options test (#468) * tests: fixes jdbc query options test This test was failing, because we were no longer recreating the jdbc connection from scratch. One of the tests, set an environment variable specifying the optimizer version, which was permanently applied, since the connection was not re-created. Here we make sure to start / stop the static server before each test. * chore: fixes linting errors tests: fixes sql script test (#469) In version 6.4.4 of spanner we have change the verifyStatementsInFile method to wrap any SQLExceptions into SpannerExceptions. In the failing tests we were catching SQLExceptions and ignoring them, since they were expected. We have changed the tests to also ignore the respective SpannerExceptions. deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 (#464) chore: release 2.1.0 (#460) :robot: I have created a release \*beep\* \*boop\* --- * allow get/set Spanner Value instances ([#454](https://www.github.com/googleapis/java-spanner-jdbc/issues/454)) ([c9df35d](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9df35d49065f552ff782a1169388b1ad4dd122c)), closes [#452](https://www.github.com/googleapis/java-spanner-jdbc/issues/452) * NPE was thrown when getting an array of structs from a ResultSet ([#445](https://www.github.com/googleapis/java-spanner-jdbc/issues/445)) ([93dd183](https://www.github.com/googleapis/java-spanner-jdbc/commit/93dd183ec4d567736ff55ffc25ca5f83ba467fb3)), closes [#444](https://www.github.com/googleapis/java-spanner-jdbc/issues/444) * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 ([#463](https://www.github.com/googleapis/java-spanner-jdbc/issues/463)) ([4df44bc](https://www.github.com/googleapis/java-spanner-jdbc/commit/4df44bce220796915205b912b620961caee6ecbd)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 ([#453](https://www.github.com/googleapis/java-spanner-jdbc/issues/453)) ([d8f0408](https://www.github.com/googleapis/java-spanner-jdbc/commit/d8f0408d3bfdbda84380991dc4d8682df93c7a48)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 ([#464](https://www.github.com/googleapis/java-spanner-jdbc/issues/464)) ([b64fbaa](https://www.github.com/googleapis/java-spanner-jdbc/commit/b64fbaa814f745e9a91a53e17b2af42f0dd44a7c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: release 2.1.1-SNAPSHOT (#470) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.1.0 (#471) [![WhiteSource 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.0.2` -> `2.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/compatibility-slim/2.0.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.1.0/confidence-slim/2.0.2)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-spanner-jdbc [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.0.2...v2.1.0) - allow get/set Spanner Value instances ([#​454](https://www.github.com/googleapis/java-spanner-jdbc/issues/454)) ([c9df35d](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9df35d49065f552ff782a1169388b1ad4dd122c)), closes [#​452](https://www.github.com/googleapis/java-spanner-jdbc/issues/452) - NPE was thrown when getting an array of structs from a ResultSet ([#​445](https://www.github.com/googleapis/java-spanner-jdbc/issues/445)) ([93dd183](https://www.github.com/googleapis/java-spanner-jdbc/commit/93dd183ec4d567736ff55ffc25ca5f83ba467fb3)), closes [#​444](https://www.github.com/googleapis/java-spanner-jdbc/issues/444) - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.1.0 ([#​463](https://www.github.com/googleapis/java-spanner-jdbc/issues/463)) ([4df44bc](https://www.github.com/googleapis/java-spanner-jdbc/commit/4df44bce220796915205b912b620961caee6ecbd)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.0 ([#​453](https://www.github.com/googleapis/java-spanner-jdbc/issues/453)) ([d8f0408](https://www.github.com/googleapis/java-spanner-jdbc/commit/d8f0408d3bfdbda84380991dc4d8682df93c7a48)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.4.4 ([#​464](https://www.github.com/googleapis/java-spanner-jdbc/issues/464)) ([b64fbaa](https://www.github.com/googleapis/java-spanner-jdbc/commit/b64fbaa814f745e9a91a53e17b2af42f0dd44a7c)) - release scripts from issuing overlapping phases ([#​434](https://www.github.com/googleapis/java-spanner-jdbc/issues/434)) ([41c85a2](https://www.github.com/googleapis/java-spanner-jdbc/commit/41c85a21256375664ce837d3531131f02806bd99)) - typo ([#​431](https://www.github.com/googleapis/java-spanner-jdbc/issues/431)) ([6b74d16](https://www.github.com/googleapis/java-spanner-jdbc/commit/6b74d1680f24cacc33e11267d87f231f978b2827)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.1 ([#​438](https://www.github.com/googleapis/java-spanner-jdbc/issues/438)) ([48e3d05](https://www.github.com/googleapis/java-spanner-jdbc/commit/48e3d05e3a83af63334f3e935984991b6d3fa0a7)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v1 ([#​441](https://www.github.com/googleapis/java-spanner-jdbc/issues/441)) ([9bbad0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/9bbad0cee0cb5e44892b6cef9d5bd5b36c829361)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.1 ([#​430](https://www.github.com/googleapis/java-spanner-jdbc/issues/430)) ([0157bcb](https://www.github.com/googleapis/java-spanner-jdbc/commit/0157bcbcbed8c47917b4006c3c8a2c07a6187c04)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.3.3 ([#​439](https://www.github.com/googleapis/java-spanner-jdbc/issues/439)) ([13c3783](https://www.github.com/googleapis/java-spanner-jdbc/commit/13c37836d9adaa4596e41609cf4e54da371d6eea)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v0.21.0 ([#​423](https://www.github.com/googleapis/java-spanner-jdbc/issues/423)) ([46b5494](https://www.github.com/googleapis/java-spanner-jdbc/commit/46b5494269893b73893c67609fd488c13431c1ef)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.2.0 ([#​420](https://www.github.com/googleapis/java-spanner-jdbc/issues/420)) ([5fd565a](https://www.github.com/googleapis/java-spanner-jdbc/commit/5fd565a0c014dfa98577f1df51c33a2ebc1c713b))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). feat: add `gcf-owl-bot[bot]` to `ignoreAuthors` (#474) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/35db7954-f063-42f8-9ff3-5d189e94e5d3/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/7332178a11ddddc91188dc0f25bca1ccadcaa6c6 deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 (#473) [![WhiteSource 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/java-shared-dependencies) | `1.1.0` -> `1.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/compatibility-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.2.0/confidence-slim/1.1.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-shared-dependencies [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.1.0...v1.2.0) - update dependency com.google.api-client:google-api-client-bom to v1.31.5 ([#​353](https://www.github.com/googleapis/java-shared-dependencies/issues/353)) ([8d72ab0](https://www.github.com/googleapis/java-shared-dependencies/commit/8d72ab003e08c864aedc17fc190ba26f393bf0c7)) - update dependency com.google.errorprone:error_prone_annotations to v2.7.1 ([#​360](https://www.github.com/googleapis/java-shared-dependencies/issues/360)) ([8f952d0](https://www.github.com/googleapis/java-shared-dependencies/commit/8f952d05745358fc426a1a2dcb688da5d5010239)) - update dependency com.google.protobuf:protobuf-bom to v3.17.0 ([#​355](https://www.github.com/googleapis/java-shared-dependencies/issues/355)) ([09858fb](https://www.github.com/googleapis/java-shared-dependencies/commit/09858fb4f1b78a77e828501597d20df4db0ebfcf)) - update dependency io.grpc:grpc-bom to v1.37.1 ([#​359](https://www.github.com/googleapis/java-shared-dependencies/issues/359)) ([bc9869e](https://www.github.com/googleapis/java-shared-dependencies/commit/bc9869e914314f951afd69f2acae95c414398f43)) - update google.common-protos.version to v2.2.1 ([#​358](https://www.github.com/googleapis/java-shared-dependencies/issues/358)) ([a3ed764](https://www.github.com/googleapis/java-shared-dependencies/commit/a3ed764a0e5143ee323d4b69c9747b8265d349e2)) - update iam.version to v1.0.14 ([#​352](https://www.github.com/googleapis/java-shared-dependencies/issues/352)) ([bea9a01](https://www.github.com/googleapis/java-shared-dependencies/commit/bea9a01788ac1332a4bc7e06574ef5701700fe90))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: regenerate README (#472) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-05-18 19:34:16,960 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-05-18 19:34:18,292 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/572b047a-da68-49ed-98fa-b98e7f88514a/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) build(deps): update dependency com.google.cloud:google-cloud-shared-config to v0.12.0 (#476) [![WhiteSource 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) | `0.11.2` -> `0.12.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/compatibility-slim/0.11.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/0.12.0/confidence-slim/0.11.2)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: dump maven version along with java (#477) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/9ea9dfcf-fef7-472c-9ebc-755e62e086c4/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/8eae0234a16b26c2ff616d305dbd9786c8b10a47 docs: document connection properties in README (#478) Adds documentation for the supported connection properties to the README file. Fixes #456 chore: regenerate README (#481) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-05-24 05:37:24,863 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-05-24 05:37:26,075 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/5da15a47-718f-4374-b505-dead2c234c76/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.3.0 (#480) chore(deps): update dependency com.google.cloud:libraries-bom to v20.5.0 (#482) deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 (#483) test(deps): update dependency com.google.truth:truth to v1.1.3 (#484) test(deps): update dependency com.google.truth:truth to v1.1.3 (#485) [![WhiteSource 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.truth:truth | `1.1.2` -> `1.1.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/compatibility-slim/1.1.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.3/confidence-slim/1.1.2)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: release 2.2.0 (#475) :robot: I have created a release \*beep\* \*boop\* --- * add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#474](https://www.github.com/googleapis/java-spanner-jdbc/issues/474)) ([5f9ed96](https://www.github.com/googleapis/java-spanner-jdbc/commit/5f9ed96272c818f07d9eb384f283f7e9c032a6ca)) * document connection properties in README ([#478](https://www.github.com/googleapis/java-spanner-jdbc/issues/478)) ([f5bca0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/f5bca0cd589b1839f569497f2e7efddef9934174)), closes [#456](https://www.github.com/googleapis/java-spanner-jdbc/issues/456) * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 ([#473](https://www.github.com/googleapis/java-spanner-jdbc/issues/473)) ([2d3097a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2d3097a65237eb0425ba3d2b52f594335190975c)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 ([#483](https://www.github.com/googleapis/java-spanner-jdbc/issues/483)) ([af87ed0](https://www.github.com/googleapis/java-spanner-jdbc/commit/af87ed0d50d6c8650c08d5f6f605882dcd8cfbab)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: release 2.2.1-SNAPSHOT (#487) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.0 (#488) [![WhiteSource 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.1.0` -> `2.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/compatibility-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.2.0/confidence-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-spanner-jdbc [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.1.0...v2.2.0) - add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#​474](https://www.github.com/googleapis/java-spanner-jdbc/issues/474)) ([5f9ed96](https://www.github.com/googleapis/java-spanner-jdbc/commit/5f9ed96272c818f07d9eb384f283f7e9c032a6ca)) - document connection properties in README ([#​478](https://www.github.com/googleapis/java-spanner-jdbc/issues/478)) ([f5bca0c](https://www.github.com/googleapis/java-spanner-jdbc/commit/f5bca0cd589b1839f569497f2e7efddef9934174)), closes [#​456](https://www.github.com/googleapis/java-spanner-jdbc/issues/456) - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.2.0 ([#​473](https://www.github.com/googleapis/java-spanner-jdbc/issues/473)) ([2d3097a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2d3097a65237eb0425ba3d2b52f594335190975c)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.5.0 ([#​483](https://www.github.com/googleapis/java-spanner-jdbc/issues/483)) ([af87ed0](https://www.github.com/googleapis/java-spanner-jdbc/commit/af87ed0d50d6c8650c08d5f6f605882dcd8cfbab))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: regenerate README (#489) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-02 20:28:22,584 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-02 20:28:23,968 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/f9c652de-b905-42d2-8dff-d97f0e0d5476/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.3.0 (#490) [![WhiteSource 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/java-shared-dependencies) | `1.2.0` -> `1.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/compatibility-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.3.0/confidence-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-shared-dependencies [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.2.0...v1.3.0) - add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#​365](https://www.github.com/googleapis/java-shared-dependencies/issues/365)) ([7e8309b](https://www.github.com/googleapis/java-shared-dependencies/commit/7e8309bf67ade0fe2b09f792848136cd88b4d2e4)) - update dependency com.google.auth:google-auth-library-bom to v0.26.0 ([#​368](https://www.github.com/googleapis/java-shared-dependencies/issues/368)) ([38256a8](https://www.github.com/googleapis/java-shared-dependencies/commit/38256a82cb6896c3f5e5ea6ca5d8d671c412bf84)) - update dependency com.google.cloud:google-cloud-core-bom to v1.95.0 ([#​377](https://www.github.com/googleapis/java-shared-dependencies/issues/377)) ([297ea62](https://www.github.com/googleapis/java-shared-dependencies/commit/297ea621e02f8c0679c8b07ed399d11eaacecc14)) - update dependency com.google.code.gson:gson to v2.8.7 ([#​370](https://www.github.com/googleapis/java-shared-dependencies/issues/370)) ([cdc1b8e](https://www.github.com/googleapis/java-shared-dependencies/commit/cdc1b8ea1c93f97b712081ca8dc8ea57f342b69e)) - update dependency com.google.protobuf:protobuf-bom to v3.17.1 ([#​369](https://www.github.com/googleapis/java-shared-dependencies/issues/369)) ([5a19574](https://www.github.com/googleapis/java-shared-dependencies/commit/5a19574bc626bb3c6b573ed1d177e8907188dec1)) - update dependency com.google.protobuf:protobuf-bom to v3.17.2 ([#​374](https://www.github.com/googleapis/java-shared-dependencies/issues/374)) ([83516e6](https://www.github.com/googleapis/java-shared-dependencies/commit/83516e691b99e5e5d22d27e561781a5ade5fb514)) - update dependency io.grpc:grpc-bom to v1.38.0 ([#​364](https://www.github.com/googleapis/java-shared-dependencies/issues/364)) ([00db570](https://www.github.com/googleapis/java-shared-dependencies/commit/00db5701c3b0aa609f3778c06911a9a0248ca342)) - update gax.version to v1.65.0 ([#​376](https://www.github.com/googleapis/java-shared-dependencies/issues/376)) ([b793a0d](https://www.github.com/googleapis/java-shared-dependencies/commit/b793a0d7744ff1b0f8ae5d3d13ec4776ae8d3089)) - update google.common-protos.version to v2.3.1 ([#​366](https://www.github.com/googleapis/java-shared-dependencies/issues/366)) ([7d6a7fa](https://www.github.com/googleapis/java-shared-dependencies/commit/7d6a7fa7a2cad2b3f2ecf45e42d2ed5db0b60a43)) - update google.common-protos.version to v2.3.2 ([#​375](https://www.github.com/googleapis/java-shared-dependencies/issues/375)) ([68a47ad](https://www.github.com/googleapis/java-shared-dependencies/commit/68a47ad3243f3e980db74c9c8505a1b3063c131b))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: release 2.2.1 (#491) :robot: I have created a release \*beep\* \*boop\* --- * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.3.0 ([#490](https://www.github.com/googleapis/java-spanner-jdbc/issues/490)) ([f4f05b9](https://www.github.com/googleapis/java-spanner-jdbc/commit/f4f05b9ce05476deb43a7601aa6ccdf053ca5ec1)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: release 2.2.2-SNAPSHOT (#492) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.1 (#493) chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.0.23 (#494) chore: regenerate README (#495) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-05 09:53:24,030 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-05 09:53:25,229 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/2c57a5bd-142d-430b-9931-a1a1a7e59a30/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) chore(deps): update dependency com.google.cloud:libraries-bom to v20.6.0 (#496) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.5.0` -> `20.6.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/compatibility-slim/20.5.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.6.0/confidence-slim/20.5.0)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 (#498) * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 Updates to Spanner client 6.6.0 and adds tests for optimizer stats package. Replaces #497 * test: implement missing method for integration test chore: release 2.2.2 (#499) :robot: I have created a release \*beep\* \*boop\* --- * update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.0 ([#498](https://www.github.com/googleapis/java-spanner-jdbc/issues/498)) ([412adf5](https://www.github.com/googleapis/java-spanner-jdbc/commit/412adf57e2b092074499d500071ca9968e0e9094)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: release 2.2.3-SNAPSHOT (#500) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.1 (#502) [![WhiteSource 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.6.0` -> `6.6.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/compatibility-slim/6.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.6.1/confidence-slim/6.6.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-spanner [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.6.0...v6.6.1)
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: release 2.2.3 (#504) :robot: I have created a release \*beep\* \*boop\* --- * update dependency com.google.cloud:google-cloud-spanner-bom to v6.6.1 ([#502](https://www.github.com/googleapis/java-spanner-jdbc/issues/502)) ([731d0e4](https://www.github.com/googleapis/java-spanner-jdbc/commit/731d0e4229b8dd97648f4319fdc03268aabc3ace)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: regenerate README (#505) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-15 21:17:11,110 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-15 21:17:12,273 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/0bc6fb82-3b4e-44b2-978c-65fa57b88268/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) chore: release 2.2.4-SNAPSHOT (#507) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). fix: Update dependencies.sh to not break on mac (#506) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/f853e0b6-9a6b-4346-9a07-ff7c7ec6f858/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/8f76a885deaaf2fe234daeba4a8cc4d1b3de8086 chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.2 (#501) chore: regenerate README (#510) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-06-15 23:11:37,759 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-06-15 23:11:38,999 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/61cfb5e0-68cd-47b3-89b4-af4a25c2c4b6/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) fix: prevent relocating urls that start with com like /computeMetadata/ (#511) Fixes #503 In addition to original problem I have added an exception for all the Netty libraries since I have got errors on service provider which claims that netty libraries are not a subtype. chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.3 (#509) chore: minimize noise from build scripts (#512) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/88f2626c-4d2d-42a7-9d16-aaa685eaa74a/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/1c0c698705e668ccb3d68556ae7260f16ce63a6e fix: Add `shopt -s nullglob` to dependencies script (#514) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/bc91c2d7-c025-42b9-ab03-f02a01c15622/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/87254ac89a9559864c0a245d6b150406439ce3d8 chore(deps): update dependency com.google.cloud:libraries-bom to v20.7.0 (#515) [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `20.6.0` -> `20.7.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/compatibility-slim/20.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/20.7.0/confidence-slim/20.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.7.0 (#513) deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 (#518) [![WhiteSource 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/java-shared-dependencies) | `1.3.0` -> `1.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/compatibility-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/1.4.0/confidence-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-shared-dependencies [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v1.3.0...v1.4.0) - add grpc-gcp to dependencyManagement ([#​389](https://www.github.com/googleapis/java-shared-dependencies/issues/389)) ([57fd2e6](https://www.github.com/googleapis/java-shared-dependencies/commit/57fd2e646e28e37e0b5e4e1b37425d4897a8776f)) - Add `shopt -s nullglob` to dependencies script ([#​392](https://www.github.com/googleapis/java-shared-dependencies/issues/392)) ([f8f29df](https://www.github.com/googleapis/java-shared-dependencies/commit/f8f29df1c9cc6eca517c99113fb9509fd611ac92)) - Add common httpclient and oauth dependencies ([#​391](https://www.github.com/googleapis/java-shared-dependencies/issues/391)) ([09660e1](https://www.github.com/googleapis/java-shared-dependencies/commit/09660e1e50c96dcd7df4e80d8ad357f8256eda6c)) - Update dependencies.sh to not break on mac ([#​384](https://www.github.com/googleapis/java-shared-dependencies/issues/384)) ([0ae2841](https://www.github.com/googleapis/java-shared-dependencies/commit/0ae2841d7ce2885d041795c58a38d2d3973c2e5a)) - update dependency com.google.api-client:google-api-client-bom to v1.32.1 ([#​390](https://www.github.com/googleapis/java-shared-dependencies/issues/390)) ([00288c1](https://www.github.com/googleapis/java-shared-dependencies/commit/00288c18d09616582c8bec961ecc5c00ef1d4288)) - update dependency com.google.api:api-common to v1.10.4 ([#​385](https://www.github.com/googleapis/java-shared-dependencies/issues/385)) ([5f2b39b](https://www.github.com/googleapis/java-shared-dependencies/commit/5f2b39b5bdc4cec9d5ab2f050e11000ed372d057)) - update dependency com.google.api:gax-grpc to v1.65.1 ([#​382](https://www.github.com/googleapis/java-shared-dependencies/issues/382)) ([a2a1547](https://www.github.com/googleapis/java-shared-dependencies/commit/a2a15471dee21207a0b97b3bc8f6f59d6a4a2d13)) - update dependency com.google.protobuf:protobuf-bom to v3.17.3 ([#​379](https://www.github.com/googleapis/java-shared-dependencies/issues/379)) ([6f43eb5](https://www.github.com/googleapis/java-shared-dependencies/commit/6f43eb553dca98140d343bee3f1003096d79ee6c)) - update dependency io.grpc:grpc-bom to v1.38.1 ([#​386](https://www.github.com/googleapis/java-shared-dependencies/issues/386)) ([7b1d4cf](https://www.github.com/googleapis/java-shared-dependencies/commit/7b1d4cf317fbd75b91d6a63f82b5fc2f46eaf3ca)) - update dependency io.grpc:grpc-bom to v1.39.0 ([#​394](https://www.github.com/googleapis/java-shared-dependencies/issues/394)) ([ebc8af6](https://www.github.com/googleapis/java-shared-dependencies/commit/ebc8af6b3f850b58b35d9720a7a0b1545d4616bd)) - update gax.version to v1.66.0 ([#​395](https://www.github.com/googleapis/java-shared-dependencies/issues/395)) ([c73f73e](https://www.github.com/googleapis/java-shared-dependencies/commit/c73f73e84740a8117be342a66e179eaf3e29c6fd)) - update google.core.version to v1.95.1 ([#​381](https://www.github.com/googleapis/java-shared-dependencies/issues/381)) ([4496153](https://www.github.com/googleapis/java-shared-dependencies/commit/44961532f621b0ab19e9e7feebb7d588aef5d423)) - update google.core.version to v1.95.2 ([#​383](https://www.github.com/googleapis/java-shared-dependencies/issues/383)) ([7216859](https://www.github.com/googleapis/java-shared-dependencies/commit/7216859bcd67fa1ce1119831c33c50a2d5b79324)) - update google.core.version to v1.95.3 ([#​388](https://www.github.com/googleapis/java-shared-dependencies/issues/388)) ([354e4e8](https://www.github.com/googleapis/java-shared-dependencies/commit/354e4e811f4ba886406681a4261ac0455a9eb2d2)) - update google.core.version to v1.95.4 ([#​393](https://www.github.com/googleapis/java-shared-dependencies/issues/393)) ([be78ad8](https://www.github.com/googleapis/java-shared-dependencies/commit/be78ad85e31d8876eabafee7aa8242712573cb46))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.8.0 (#517) [![WhiteSource 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.7.0` -> `6.8.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/compatibility-slim/6.7.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.8.0/confidence-slim/6.7.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-spanner [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.7.0...v6.8.0) - add gRPC-GCP channel pool as an option ([#​1227](https://www.github.com/googleapis/java-spanner/issues/1227)) ([1fa95a9](https://www.github.com/googleapis/java-spanner/commit/1fa95a9993ea8c7a5f943ab39eced4ced4cb87e7)) - spanner JSON type ([#​1260](https://www.github.com/googleapis/java-spanner/issues/1260)) ([b2a56c6](https://www.github.com/googleapis/java-spanner/commit/b2a56c68695b6209e20f9f86d83d7c5a0f39c7a8)) - Add `shopt -s nullglob` to dependencies script ([#​1256](https://www.github.com/googleapis/java-spanner/issues/1256)) ([d1712f7](https://www.github.com/googleapis/java-spanner/commit/d1712f7c51752c2359045e5eabac8fc0530a2421))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: release 2.2.4 (#508) :robot: I have created a release \*beep\* \*boop\* --- * Add `shopt -s nullglob` to dependencies script ([#514](https://www.github.com/googleapis/java-spanner-jdbc/issues/514)) ([56d3134](https://www.github.com/googleapis/java-spanner-jdbc/commit/56d3134da0de80b077ee5b2b5dea2927f53e6df4)) * prevent relocating urls that start with com like /computeMetadata/ ([#511](https://www.github.com/googleapis/java-spanner-jdbc/issues/511)) ([98d7214](https://www.github.com/googleapis/java-spanner-jdbc/commit/98d72146a1b21cd8adf7c89b0a698c63737813ad)) * Update dependencies.sh to not break on mac ([#506](https://www.github.com/googleapis/java-spanner-jdbc/issues/506)) ([3b71596](https://www.github.com/googleapis/java-spanner-jdbc/commit/3b7159618eb47306c2f5e0628d494e603d92f51e)) * update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 ([#518](https://www.github.com/googleapis/java-spanner-jdbc/issues/518)) ([d29b441](https://www.github.com/googleapis/java-spanner-jdbc/commit/d29b441c02ee59424ec95b6f211c3839ef73db44)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.7.0 ([#513](https://www.github.com/googleapis/java-spanner-jdbc/issues/513)) ([e3e5795](https://www.github.com/googleapis/java-spanner-jdbc/commit/e3e5795317aa279150ba7f76e1f2f9b84ed56fd3)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.8.0 ([#517](https://www.github.com/googleapis/java-spanner-jdbc/issues/517)) ([9c36f5a](https://www.github.com/googleapis/java-spanner-jdbc/commit/9c36f5a1a52436fa84fa63d122b57f1d655047df)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: release 2.2.5-SNAPSHOT (#519) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.0 (#521) [![WhiteSource 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.8.0` -> `6.9.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/compatibility-slim/6.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.9.0/confidence-slim/6.8.0)](https://docs.renovatebot.com/merge-confidence/) | ---
    googleapis/java-spanner [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.8.0...v6.9.0) - add support for tagging to Connection API ([#​623](https://www.github.com/googleapis/java-spanner/issues/623)) ([5722372](https://www.github.com/googleapis/java-spanner/commit/5722372b7869828e372dec06e80e5b0e7280af61)) - **spanner:** add leader_options to InstanceConfig and default_leader to Database ([#​1271](https://www.github.com/googleapis/java-spanner/issues/1271)) ([f257671](https://www.github.com/googleapis/java-spanner/commit/f25767144344f0df67662f1b3ef662902384599a)) - support setting an async executor provider ([#​1263](https://www.github.com/googleapis/java-spanner/issues/1263)) ([369c8a7](https://www.github.com/googleapis/java-spanner/commit/369c8a771ec48fa1476236f800b0e8eb5982a33c)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v1.4.0 ([#​1269](https://www.github.com/googleapis/java-spanner/issues/1269)) ([025e162](https://www.github.com/googleapis/java-spanner/commit/025e162813d6321dabe49e32f00934f9ae334e24))
    --- 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). chore: release 2.2.5 (#522) :robot: I have created a release \*beep\* \*boop\* --- * update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.0 ([#521](https://www.github.com/googleapis/java-spanner-jdbc/issues/521)) ([d5f7f96](https://www.github.com/googleapis/java-spanner-jdbc/commit/d5f7f9631065d19894f5578ba04f10147784c4d2)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore: regenerate README (#523) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-06 00:20:39,365 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-06 00:20:40,571 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/c1ec5162-f264-4d89-804f-4f695017e997/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) chore: release 2.2.6-SNAPSHOT (#524) :robot: I have created a release \*beep\* \*boop\* --- --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.2.4 (#520) deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.9.1 (#525) chore: regenerate README (#528) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-07-06 01:48:33,450 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-07-06 01:48:34,668 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata.… * fix: run linter * fix: integration test failure --- .../spanner/jdbc/AbstractJdbcWrapper.java | 3 + .../google/cloud/spanner/jdbc/JdbcArray.java | 4 + .../cloud/spanner/jdbc/JdbcDataType.java | 26 ++ .../spanner/jdbc/JdbcParameterStore.java | 80 ++++-- .../cloud/spanner/jdbc/JdbcResultSet.java | 17 ++ .../cloud/spanner/jdbc/JdbcTypeConverter.java | 7 +- .../google/cloud/spanner/jdbc/JsonType.java | 55 ++++ .../jdbc/DatabaseMetaData_GetColumns.sql | 3 + .../spanner/jdbc/ITAbstractJdbcTest.java | 10 +- .../cloud/spanner/jdbc/JdbcArrayTest.java | 22 ++ .../spanner/jdbc/JdbcParameterStoreTest.java | 40 ++- .../jdbc/JdbcResultSetMetaDataTest.java | 22 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 34 +++ .../spanner/jdbc/JdbcTypeConverterTest.java | 18 ++ .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 3 + .../jdbc/it/ITJdbcPreparedStatementTest.java | 254 +++++++++++------- .../spanner/jdbc/it/CreateMusicTables.sql | 2 + .../jdbc/it/CreateMusicTables_Emulator.sql | 104 +++++++ 18 files changed, 578 insertions(+), 126 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 9f9752452e43..5f296731040e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -48,6 +48,7 @@ static int extractColumnType(Type type) { if (type.equals(Type.int64())) return Types.BIGINT; if (type.equals(Type.numeric())) return Types.NUMERIC; if (type.equals(Type.string())) return Types.NVARCHAR; + if (type.equals(Type.json())) return Types.NVARCHAR; if (type.equals(Type.timestamp())) return Types.TIMESTAMP; if (type.getCode() == Code.ARRAY) return Types.ARRAY; return Types.OTHER; @@ -106,6 +107,7 @@ static String getClassName(Type type) { if (type == Type.int64()) return Long.class.getName(); if (type == Type.numeric()) return BigDecimal.class.getName(); if (type == Type.string()) return String.class.getName(); + if (type == Type.json()) return String.class.getName(); if (type == Type.timestamp()) return Timestamp.class.getName(); if (type.getCode() == Code.ARRAY) { if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); @@ -115,6 +117,7 @@ static String getClassName(Type type) { if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); if (type.getArrayElementType() == Type.numeric()) return BigDecimal[].class.getName(); if (type.getArrayElementType() == Type.string()) return String[].class.getName(); + if (type.getArrayElementType() == Type.json()) return String[].class.getName(); if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); } return null; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 2a9d9e77635c..4367740509be 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -21,6 +21,7 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.common.collect.ImmutableList; import com.google.rpc.Code; @@ -201,6 +202,9 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { case STRING: builder = binder.to((String) value); break; + case JSON: + builder = binder.to(Value.json((String) value)); + break; case TIMESTAMP: builder = binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); break; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 6e6c3bf82142..8da36e4c4bf1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -229,6 +229,32 @@ public Type getSpannerType() { return Type.string(); } }, + JSON { + @Override + public int getSqlType() { + return JsonType.VENDOR_TYPE_NUMBER; + } + + @Override + public Class getJavaClass() { + return String.class; + } + + @Override + public Code getCode() { + return Code.JSON; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getJsonList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.json(); + } + }, TIMESTAMP { @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 75f16cd8e18c..24773cdced80 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -19,6 +19,7 @@ import com.google.cloud.ByteArray; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Statement.Builder; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; @@ -264,6 +265,7 @@ private boolean isTypeSupported(int sqlType) { case Types.NCLOB: case Types.NUMERIC: case Types.DECIMAL: + case JsonType.VENDOR_TYPE_NUMBER: return true; } return false; @@ -315,6 +317,11 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { return value instanceof Clob || value instanceof Reader; case Types.NCLOB: return value instanceof NClob || value instanceof Reader; + case JsonType.VENDOR_TYPE_NUMBER: + return value instanceof String + || value instanceof InputStream + || value instanceof Reader + || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.JSON); } return false; } @@ -544,30 +551,34 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, case Types.NCHAR: case Types.NVARCHAR: case Types.LONGNVARCHAR: + String stringValue; if (value instanceof String) { - return binder.to((String) value); + stringValue = (String) value; } else if (value instanceof InputStream) { - InputStreamReader reader = - new InputStreamReader((InputStream) value, StandardCharsets.US_ASCII); - try { - return binder.to(CharStreams.toString(reader)); - } catch (IOException e) { - throw JdbcSqlExceptionFactory.of( - "could not set string from input stream", Code.INVALID_ARGUMENT, e); - } + stringValue = getStringFromInputStream((InputStream) value); } else if (value instanceof Reader) { - try { - return binder.to(CharStreams.toString((Reader) value)); - } catch (IOException e) { - throw JdbcSqlExceptionFactory.of( - "could not set string from reader", Code.INVALID_ARGUMENT, e); - } + stringValue = getStringFromReader((Reader) value); } else if (value instanceof URL) { - return binder.to(((URL) value).toString()); + stringValue = ((URL) value).toString(); } else if (value instanceof UUID) { - return binder.to(((UUID) value).toString()); + stringValue = ((UUID) value).toString(); + } else { + throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); + } + return binder.to(stringValue); + case JsonType.VENDOR_TYPE_NUMBER: + String jsonValue; + if (value instanceof String) { + jsonValue = (String) value; + } else if (value instanceof InputStream) { + jsonValue = getStringFromInputStream((InputStream) value); + } else if (value instanceof Reader) { + jsonValue = getStringFromReader((Reader) value); + } else { + throw JdbcSqlExceptionFactory.of( + value + " is not a valid JSON value", Code.INVALID_ARGUMENT); } - throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); + return binder.to(Value.json(jsonValue)); case Types.DATE: if (value instanceof Date) { return binder.to(JdbcTypeConverter.toGoogleDate((Date) value)); @@ -652,6 +663,25 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, return null; } + private String getStringFromInputStream(InputStream inputStream) throws SQLException { + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.US_ASCII); + try { + return CharStreams.toString(reader); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from input stream", Code.INVALID_ARGUMENT, e); + } + } + + private String getStringFromReader(Reader reader) throws SQLException { + try { + return CharStreams.toString(reader); + } catch (IOException e) { + throw JdbcSqlExceptionFactory.of( + "could not set string from reader", Code.INVALID_ARGUMENT, e); + } + } + /** Set the parameter value based purely on the type of the value. */ private Builder setParamWithUnknownType(ValueBinder binder, Object value) throws SQLException { @@ -769,14 +799,16 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.LONGNVARCHAR: case Types.CLOB: case Types.NCLOB: - return binder.toStringArray((Iterable) null); + return binder.toStringArray(null); + case JsonType.VENDOR_TYPE_NUMBER: + return binder.toJsonArray(null); case Types.DATE: - return binder.toDateArray((Iterable) null); + return binder.toDateArray(null); case Types.TIME: case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: - return binder.toTimestampArray((Iterable) null); + return binder.toTimestampArray(null); case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: @@ -829,7 +861,11 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value)); } else if (String[].class.isAssignableFrom(value.getClass())) { - return binder.toStringArray(Arrays.asList((String[]) value)); + if (type == JsonType.VENDOR_TYPE_NUMBER) { + return binder.toJsonArray(Arrays.asList((String[]) value)); + } else { + return binder.toStringArray(Arrays.asList((String[]) value)); + } } else if (byte[][].class.isAssignableFrom(value.getClass())) { return binder.toBytesArray(JdbcTypeConverter.toGoogleBytes((byte[][]) value)); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index c4ca6b5e220d..489c2d27f045 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -142,6 +142,8 @@ public String getString(int columnIndex) throws SQLException { return isNull ? null : spanner.getBigDecimal(spannerIndex).toString(); case STRING: return isNull ? null : spanner.getString(spannerIndex); + case JSON: + return isNull ? null : spanner.getJson(spannerIndex); case TIMESTAMP: return isNull ? null : spanner.getTimestamp(spannerIndex).toString(); case STRUCT: @@ -169,6 +171,7 @@ public boolean getBoolean(int columnIndex) throws SQLException { case STRING: return isNull ? false : Boolean.valueOf(spanner.getString(spannerIndex)); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -198,6 +201,7 @@ public byte getByte(int columnIndex) throws SQLException { case STRING: return isNull ? (byte) 0 : checkedCastToByte(parseLong(spanner.getString(spannerIndex))); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -227,6 +231,7 @@ public short getShort(int columnIndex) throws SQLException { case STRING: return isNull ? 0 : checkedCastToShort(parseLong(spanner.getString(spannerIndex))); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -256,6 +261,7 @@ public int getInt(int columnIndex) throws SQLException { case STRING: return isNull ? 0 : checkedCastToInt(parseLong(spanner.getString(spannerIndex))); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -283,6 +289,7 @@ public long getLong(int columnIndex) throws SQLException { case STRING: return isNull ? 0L : parseLong(spanner.getString(spannerIndex)); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -310,6 +317,7 @@ public float getFloat(int columnIndex) throws SQLException { case STRING: return isNull ? 0 : checkedCastToFloat(parseDouble(spanner.getString(spannerIndex))); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -337,6 +345,7 @@ public double getDouble(int columnIndex) throws SQLException { case STRING: return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); case BYTES: + case JSON: case DATE: case STRUCT: case TIMESTAMP: @@ -372,6 +381,7 @@ public Date getDate(int columnIndex) throws SQLException { case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: @@ -396,6 +406,7 @@ public Time getTime(int columnIndex) throws SQLException { case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: @@ -421,6 +432,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: @@ -576,6 +588,7 @@ private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.int64()) return getLong(columnIndex); if (type == Type.numeric()) return getBigDecimal(columnIndex); if (type == Type.string()) return getString(columnIndex); + if (type == Type.json()) return getString(columnIndex); if (type == Type.timestamp()) return getTimestamp(columnIndex); if (type.getCode() == Code.ARRAY) return getArray(columnIndex); throw JdbcSqlExceptionFactory.of( @@ -664,6 +677,7 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) e); } case BYTES: + case JSON: case DATE: case TIMESTAMP: case STRUCT: @@ -749,6 +763,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: @@ -778,6 +793,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: @@ -810,6 +826,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException case INT64: case NUMERIC: case BYTES: + case JSON: case STRUCT: case ARRAY: default: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 6aa9b48a6949..4b2e4f0f7109 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -81,7 +81,8 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx } if (targetType.equals(byte[].class)) { if (type.getCode() == Code.BYTES) return value; - if (type.getCode() == Code.STRING) return ((String) value).getBytes(UTF8); + if (type.getCode() == Code.STRING || type.getCode() == Code.JSON) + return ((String) value).getBytes(UTF8); } if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; @@ -186,6 +187,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx case TIMESTAMP: return Value.timestampArray( toGoogleTimestamps((java.sql.Timestamp[]) ((java.sql.Array) value).getArray())); + case JSON: + return Value.jsonArray(Arrays.asList((String[]) ((java.sql.Array) value).getArray())); case STRUCT: default: throw JdbcSqlExceptionFactory.of( @@ -207,6 +210,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.string((String) value); case TIMESTAMP: return Value.timestamp(toGoogleTimestamp((java.sql.Timestamp) value)); + case JSON: + return Value.json((String) value); case STRUCT: default: throw JdbcSqlExceptionFactory.of( diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java new file mode 100644 index 000000000000..44af26b6eac5 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java @@ -0,0 +1,55 @@ +/* + * Copyright 2021 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.spanner.v1.TypeCode; +import java.sql.PreparedStatement; +import java.sql.SQLType; + +/** + * Custom SQL type for Spanner JSON data type. This type (or the vendor type number) must be used + * when setting a JSON parameter using {@link PreparedStatement#setObject(int, Object, SQLType)}. + */ +public class JsonType implements SQLType { + public static final JsonType INSTANCE = new JsonType(); + /** + * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid + * conflicts with the type numbers in java.sql.Types. + */ + public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.JSON_VALUE; + + private JsonType() {} + + @Override + public String getName() { + return "JSON"; + } + + @Override + public String getVendor() { + return JsonType.class.getPackage().getName(); + } + + @Override + public Integer getVendorTypeNumber() { + return VENDOR_TYPE_NUMBER; + } + + public String toString() { + return getName(); + } +} diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 69b1f6a8ec3e..14106ee1e92e 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -24,6 +24,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE = 'INT64' THEN -5 WHEN SPANNER_TYPE = 'NUMERIC' THEN 2 WHEN SPANNER_TYPE LIKE 'STRING%' THEN -9 + WHEN SPANNER_TYPE = 'JSON' THEN -9 WHEN SPANNER_TYPE = 'TIMESTAMP' THEN 93 END AS DATA_TYPE, SPANNER_TYPE AS TYPE_NAME, @@ -36,6 +37,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE = 'BOOL' OR SPANNER_TYPE = 'ARRAY' THEN NULL WHEN SPANNER_TYPE = 'DATE' OR SPANNER_TYPE = 'ARRAY' THEN 10 WHEN SPANNER_TYPE = 'TIMESTAMP' OR SPANNER_TYPE = 'ARRAY' THEN 35 + WHEN SPANNER_TYPE = 'JSON' OR SPANNER_TYPE = 'ARRAY' THEN 2621440 ELSE 0 END ELSE CAST(REPLACE(SUBSTR(SPANNER_TYPE, STRPOS(SPANNER_TYPE, '(')+1, STRPOS(SPANNER_TYPE, ')')-STRPOS(SPANNER_TYPE, '(')-1), 'MAX', CASE WHEN UPPER(SPANNER_TYPE) LIKE '%STRING%' THEN '2621440' ELSE '10485760' END) AS INT64) @@ -63,6 +65,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU CASE WHEN (SPANNER_TYPE LIKE 'STRING%' OR SPANNER_TYPE LIKE 'ARRAY getAllTypes() { types.add(Type.float64()); types.add(Type.int64()); types.add(Type.string()); + types.add(Type.json()); types.add(Type.timestamp()); List arrayTypes = new ArrayList<>(); for (Type type : types) { @@ -219,6 +221,7 @@ private Value getDefaultValue(Type type, int row) { if (type == Type.float64()) return Value.float64(123.45D); if (type == Type.int64()) return Value.int64(12345L); if (type == Type.string()) return Value.string("test value " + row); + if (type == Type.json()) return Value.json("{\"test_value\": " + row + "}"); if (type == Type.timestamp()) return Value.timestamp(com.google.cloud.Timestamp.now()); if (type.getCode() == Code.ARRAY) { @@ -240,6 +243,9 @@ private Value getDefaultValue(Type type, int row) { return Value.int64Array(Arrays.asList(12345L, 54321L)); if (type.getArrayElementType() == Type.string()) return Value.stringArray(Arrays.asList("test value " + row, "test value " + row)); + if (type.getArrayElementType() == Type.json()) + return Value.jsonArray( + Arrays.asList("{\"test_value\": " + row + "}", "{\"test_value\": " + row + "}")); if (type.getArrayElementType() == Type.timestamp()) return Value.timestampArray( Arrays.asList(com.google.cloud.Timestamp.now(), com.google.cloud.Timestamp.now())); @@ -263,7 +269,9 @@ public void testIsAutoIncrement() throws SQLException { public void testIsCaseSensitive() throws SQLException { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { Type type = TEST_COLUMNS.get(i - 1).type; - assertEquals(type == Type.string() || type == Type.bytes(), subject.isCaseSensitive(i)); + assertEquals( + type == Type.string() || type == Type.bytes() || type == Type.json(), + subject.isCaseSensitive(i)); } } @@ -319,6 +327,7 @@ private int getDefaultDisplaySize(Type type, int column) throws SQLException { int length = subject.getPrecision(column); return length == 0 ? 50 : length; } + if (type == Type.json()) return 50; if (type == Type.timestamp()) return 16; return 10; } @@ -397,6 +406,7 @@ private int getSqlType(Type type) { if (type == Type.float64()) return Types.DOUBLE; if (type == Type.int64()) return Types.BIGINT; if (type == Type.string()) return Types.NVARCHAR; + if (type == Type.json()) return Types.NVARCHAR; if (type == Type.timestamp()) return Types.TIMESTAMP; if (type.getCode() == Code.ARRAY) return Types.ARRAY; return Types.OTHER; @@ -446,6 +456,7 @@ private String getTypeClassName(Type type) { if (type == Type.float64()) return Double.class.getName(); if (type == Type.int64()) return Long.class.getName(); if (type == Type.string()) return String.class.getName(); + if (type == Type.json()) return String.class.getName(); if (type == Type.timestamp()) return Timestamp.class.getName(); if (type.getCode() == Code.ARRAY) { if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); @@ -454,6 +465,7 @@ private String getTypeClassName(Type type) { if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); if (type.getArrayElementType() == Type.string()) return String[].class.getName(); + if (type.getArrayElementType() == Type.json()) return String[].class.getName(); if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); } return null; @@ -466,15 +478,17 @@ private String getTypeClassName(Type type) { + "Col 4: COL4 FLOAT64\n" + "Col 5: COL5 INT64\n" + "Col 6: COL6 STRING\n" - + "Col 7: COL7 TIMESTAMP\n" - + "Col 8: COL8 ARRAY\n" + + "Col 7: COL7 JSON\n" + + "Col 8: COL8 TIMESTAMP\n" + "Col 9: COL9 ARRAY\n" + "Col 10: COL10 ARRAY\n" + "Col 11: COL11 ARRAY\n" + "Col 12: COL12 ARRAY\n" + "Col 13: COL13 ARRAY\n" + "Col 14: COL14 ARRAY\n" - + "Col 15: CALCULATED INT64\n"; + + "Col 15: COL15 ARRAY\n" + + "Col 16: COL16 ARRAY\n" + + "Col 17: CALCULATED INT64\n"; @Test public void testToString() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 9fa5f3e9c9c7..506992c47309 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -132,6 +132,11 @@ public class JdbcResultSetTest { private static final BigDecimal NUMERIC_VALUE = new BigDecimal("3.14"); private static final int NUMERIC_COLINDEX_NULL = 25; private static final int NUMERIC_COLINDEX_NOTNULL = 26; + private static final String JSON_COL_NULL = "JSON_COL_NULL"; + private static final String JSON_COL_NOT_NULL = "JSON_COL_NOT_NULL"; + private static final int JSON_COLINDEX_NULL = 27; + private static final int JSON_COLINDEX_NOT_NULL = 28; + private static final String JSON_VALUE = "{\"name\":\"John\", \"age\":30, \"car\":null}"; private static final String BOOL_ARRAY_COL = "BOOL_ARRAY"; private static final List BOOL_ARRAY_VALUE = Arrays.asList(true, null, false); @@ -149,6 +154,8 @@ public class JdbcResultSetTest { private static final List STRING_ARRAY_VALUE = Arrays.asList(STRING_VALUE, null); private static final String TIMESTAMP_ARRAY_COL = "TIMESTAMP_ARRAY"; private static final List TIMESTAMP_ARRAY_VALUE = Arrays.asList(TIMESTAMP_VALUE, null); + private static final String JSON_ARRAY_COL = "JSON_ARRAY"; + private static final List JSON_ARRAY_VALUE = Arrays.asList(JSON_VALUE, null); private JdbcResultSet subject; @@ -181,12 +188,15 @@ static ResultSet getMockResultSet() { StructField.of(STRING_COL_TIME, Type.string()), StructField.of(NUMERIC_COL_NULL, Type.numeric()), StructField.of(NUMERIC_COL_NOT_NULL, Type.numeric()), + StructField.of(JSON_COL_NULL, Type.json()), + StructField.of(JSON_COL_NOT_NULL, Type.json()), StructField.of(BOOL_ARRAY_COL, Type.array(Type.bool())), StructField.of(BYTES_ARRAY_COL, Type.array(Type.bytes())), StructField.of(DATE_ARRAY_COL, Type.array(Type.date())), StructField.of(FLOAT64_ARRAY_COL, Type.array(Type.float64())), StructField.of(INT64_ARRAY_COL, Type.array(Type.int64())), StructField.of(NUMERIC_ARRAY_COL, Type.array(Type.numeric())), + StructField.of(JSON_ARRAY_COL, Type.array(Type.json())), StructField.of(STRING_ARRAY_COL, Type.array(Type.string())), StructField.of(TIMESTAMP_ARRAY_COL, Type.array(Type.timestamp()))), Arrays.asList( @@ -243,6 +253,10 @@ static ResultSet getMockResultSet() { .to((BigDecimal) null) .set(NUMERIC_COL_NOT_NULL) .to(NUMERIC_VALUE) + .set(JSON_COL_NULL) + .to(Value.json(null)) + .set(JSON_COL_NOT_NULL) + .to(Value.json(JSON_VALUE)) .set(BOOL_ARRAY_COL) .toBoolArray(BOOL_ARRAY_VALUE) .set(BYTES_ARRAY_COL) @@ -255,6 +269,8 @@ static ResultSet getMockResultSet() { .toInt64Array(INT64_ARRAY_VALUE) .set(NUMERIC_ARRAY_COL) .toNumericArray(NUMERIC_ARRAY_VALUE) + .set(JSON_ARRAY_COL) + .toJsonArray(JSON_ARRAY_VALUE) .set(STRING_ARRAY_COL) .toStringArray(STRING_ARRAY_VALUE) .set(TIMESTAMP_ARRAY_COL) @@ -322,6 +338,15 @@ public void testGetStringIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetJsonIndex() throws SQLException { + assertNotNull(subject.getString(JSON_COLINDEX_NOT_NULL)); + assertEquals(JSON_VALUE, subject.getString(JSON_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getString(JSON_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @Test public void testGetStringIndexForBool() throws SQLException { assertNotNull(subject.getString(BOOLEAN_COLINDEX_NOTNULL)); @@ -1344,6 +1369,15 @@ public void testGetObjectIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetJsonAsObjectIndex() throws SQLException { + assertNotNull(subject.getObject(JSON_COLINDEX_NOT_NULL)); + assertEquals(JSON_VALUE, subject.getObject(JSON_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(JSON_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + @SuppressWarnings("deprecation") @Test public void testGetObjectLabelMap() throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 19f760bb6b59..1bb0e374ed02 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -70,6 +70,7 @@ public void testConvertArray() throws SQLException { Type.float64(), Type.int64(), Type.string(), + Type.json(), Type.timestamp(), Type.numeric() }) { @@ -126,6 +127,23 @@ public void testConvertBytes() throws SQLException { assertThat(convert(testValues, Type.bytes(), String.class)).isEqualTo("test"); } + @Test + public void testConvertJson() throws SQLException { + String testValue = "{\"test\": foo}"; + assertConvertThrows(testValue, Type.json(), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValue, Type.json(), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertThat(convert(testValue, Type.json(), byte[].class)).isEqualTo(testValue.getBytes(UTF8)); + assertThat(convert(testValue, Type.json(), String.class)).isEqualTo(testValue); + } + private TimeZone[] getTestTimeZones() { return new TimeZone[] { TimeZone.getTimeZone("GMT-12:00"), diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 755539987f1e..087d688fc1fc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -122,6 +122,7 @@ private Column( new Column("ColTimestamp", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColCommitTS", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColNumeric", Types.NUMERIC, "NUMERIC", 15, null, 10, false, null), + new Column("ColJson", Types.NVARCHAR, "JSON", 2621440, null, null, false, 2621440), new Column("ColInt64Array", Types.ARRAY, "ARRAY", 19, null, 10, true, null), new Column("ColFloat64Array", Types.ARRAY, "ARRAY", 15, 16, 2, true, null), new Column("ColBoolArray", Types.ARRAY, "ARRAY", null, null, null, true, null), @@ -151,6 +152,8 @@ private Column( new Column( "ColTimestampArray", Types.ARRAY, "ARRAY", 35, null, null, true, null), new Column("ColNumericArray", Types.ARRAY, "ARRAY", 15, null, 10, true, null), + new Column( + "ColJsonArray", Types.ARRAY, "ARRAY", 2621440, null, null, true, 2621440), new Column( "ColComputed", Types.NVARCHAR, diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index d52e56025369..ea1bbfb328ea 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -30,6 +30,8 @@ import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.jdbc.JsonType; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; import java.io.File; @@ -748,84 +750,113 @@ public void test07_StatementBatchUpdateWithException() throws SQLException { @Test public void test08_InsertAllColumnTypes() throws SQLException { + String sql; + if (EmulatorSpannerHelper.isUsingEmulator()) { + sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } else { + sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } try (Connection con = createConnection()) { - try (PreparedStatement ps = - con.prepareStatement( - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { - ps.setLong(1, 1L); - ps.setDouble(2, 2D); - ps.setBoolean(3, true); - ps.setString(4, "test"); - ps.setObject(5, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); - ps.setBytes(6, "test".getBytes()); - ps.setBytes(7, "testtest".getBytes()); - ps.setDate(8, new Date(System.currentTimeMillis())); - ps.setTimestamp(9, new Timestamp(System.currentTimeMillis())); - ps.setBigDecimal(10, BigDecimal.TEN); - ps.setArray(11, con.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); - ps.setArray(12, con.createArrayOf("FLOAT64", new Double[] {1.1D, 2.2D, 3.3D})); + try (PreparedStatement ps = con.prepareStatement(sql)) { + int index = 0; + ps.setLong(++index, 1L); + ps.setDouble(++index, 2D); + ps.setBoolean(++index, true); + ps.setString(++index, "test"); + ps.setObject(++index, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); + ps.setBytes(++index, "test".getBytes()); + ps.setBytes(++index, "testtest".getBytes()); + ps.setDate(++index, new Date(System.currentTimeMillis())); + ps.setTimestamp(++index, new Timestamp(System.currentTimeMillis())); + ps.setBigDecimal(++index, BigDecimal.TEN); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + ps.setObject(++index, "{\"test_value\": \"foo\"}", JsonType.INSTANCE); + } + ps.setArray(++index, con.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); + ps.setArray(++index, con.createArrayOf("FLOAT64", new Double[] {1.1D, 2.2D, 3.3D})); ps.setArray( - 13, con.createArrayOf("BOOL", new Boolean[] {Boolean.TRUE, null, Boolean.FALSE})); - ps.setArray(14, con.createArrayOf("STRING", new String[] {"1", "2", "3"})); - ps.setArray(15, con.createArrayOf("STRING", new String[] {"3", "2", "1"})); + ++index, con.createArrayOf("BOOL", new Boolean[] {Boolean.TRUE, null, Boolean.FALSE})); + ps.setArray(++index, con.createArrayOf("STRING", new String[] {"1", "2", "3"})); + ps.setArray(++index, con.createArrayOf("STRING", new String[] {"3", "2", "1"})); ps.setArray( - 16, + ++index, con.createArrayOf( "BYTES", new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()})); ps.setArray( - 17, + ++index, con.createArrayOf( "BYTES", new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()})); ps.setArray( - 18, + ++index, con.createArrayOf( "DATE", new Date[] {new Date(System.currentTimeMillis()), null, new Date(0)})); ps.setArray( - 19, + ++index, con.createArrayOf( "TIMESTAMP", new Timestamp[] { new Timestamp(System.currentTimeMillis()), null, new Timestamp(0) })); ps.setArray( - 20, + ++index, con.createArrayOf("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN})); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + ps.setArray( + ++index, + con.createArrayOf( + "JSON", new String[] {"{\"test_value\": \"foo\"}", "{}", "[]", null})); + } assertEquals(1, ps.executeUpdate()); } try (ResultSet rs = con.createStatement().executeQuery("SELECT * FROM TableWithAllColumnTypes")) { + int index = 0; assertTrue(rs.next()); - assertEquals(1L, rs.getLong(1)); - assertEquals(2d, rs.getDouble(2), 0.0d); - assertTrue(rs.getBoolean(3)); - assertEquals("test", rs.getString(4)); - assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(5)); - assertArrayEquals("test".getBytes(), rs.getBytes(6)); - assertArrayEquals("testtest".getBytes(), rs.getBytes(7)); - assertNotNull(rs.getDate(8)); - assertNotNull(rs.getTimestamp(9)); - assertNotNull(rs.getTime(10)); // Commit timestamp - assertEquals(BigDecimal.TEN, rs.getBigDecimal(11)); - assertArrayEquals(new Long[] {1L, 2L, 3L}, (Long[]) rs.getArray(12).getArray()); - assertArrayEquals(new Double[] {1.1D, 2.2D, 3.3D}, (Double[]) rs.getArray(13).getArray()); + assertEquals(1L, rs.getLong(++index)); + assertEquals(2d, rs.getDouble(++index), 0.0d); + assertTrue(rs.getBoolean(++index)); + assertEquals("test", rs.getString(++index)); + assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(++index)); + assertArrayEquals("test".getBytes(), rs.getBytes(++index)); + assertArrayEquals("testtest".getBytes(), rs.getBytes(++index)); + assertNotNull(rs.getDate(++index)); + assertNotNull(rs.getTimestamp(++index)); + assertNotNull(rs.getTime(++index)); // Commit timestamp + assertEquals(BigDecimal.TEN, rs.getBigDecimal(++index)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + assertEquals("{\"test_value\":\"foo\"}", rs.getString(++index)); + } + assertArrayEquals(new Long[] {1L, 2L, 3L}, (Long[]) rs.getArray(++index).getArray()); + assertArrayEquals( + new Double[] {1.1D, 2.2D, 3.3D}, (Double[]) rs.getArray(++index).getArray()); assertArrayEquals( - new Boolean[] {true, null, false}, (Boolean[]) rs.getArray(14).getArray()); - assertArrayEquals(new String[] {"1", "2", "3"}, (String[]) rs.getArray(15).getArray()); - assertArrayEquals(new String[] {"3", "2", "1"}, (String[]) rs.getArray(16).getArray()); + new Boolean[] {true, null, false}, (Boolean[]) rs.getArray(++index).getArray()); + assertArrayEquals(new String[] {"1", "2", "3"}, (String[]) rs.getArray(++index).getArray()); + assertArrayEquals(new String[] {"3", "2", "1"}, (String[]) rs.getArray(++index).getArray()); assertArrayEquals( new byte[][] {"1".getBytes(), "2".getBytes(), "3".getBytes()}, - (byte[][]) rs.getArray(17).getArray()); + (byte[][]) rs.getArray(++index).getArray()); assertArrayEquals( new byte[][] {"333".getBytes(), "222".getBytes(), "111".getBytes()}, - (byte[][]) rs.getArray(18).getArray()); - assertEquals(3, ((Date[]) rs.getArray(19).getArray()).length); - assertEquals(3, ((Timestamp[]) rs.getArray(20).getArray()).length); + (byte[][]) rs.getArray(++index).getArray()); + assertEquals(3, ((Date[]) rs.getArray(++index).getArray()).length); + assertEquals(3, ((Timestamp[]) rs.getArray(++index).getArray()).length); assertArrayEquals( new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}, - (BigDecimal[]) rs.getArray(21).getArray()); + (BigDecimal[]) rs.getArray(++index).getArray()); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + assertArrayEquals( + new String[] {"{\"test_value\":\"foo\"}", "{}", "[]", null}, + (String[]) rs.getArray(++index).getArray()); + } assertFalse(rs.next()); } } @@ -838,7 +869,7 @@ public void test09_MetaData_FromQuery() throws SQLException { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { ResultSetMetaData metadata = ps.getMetaData(); - assertEquals(22, metadata.getColumnCount()); + assertEquals(24, metadata.getColumnCount()); int index = 0; assertEquals("ColInt64", metadata.getColumnLabel(++index)); assertEquals("ColFloat64", metadata.getColumnLabel(++index)); @@ -851,6 +882,7 @@ public void test09_MetaData_FromQuery() throws SQLException { assertEquals("ColTimestamp", metadata.getColumnLabel(++index)); assertEquals("ColCommitTS", metadata.getColumnLabel(++index)); assertEquals("ColNumeric", metadata.getColumnLabel(++index)); + assertEquals("ColJson", metadata.getColumnLabel(++index)); assertEquals("ColInt64Array", metadata.getColumnLabel(++index)); assertEquals("ColFloat64Array", metadata.getColumnLabel(++index)); assertEquals("ColBoolArray", metadata.getColumnLabel(++index)); @@ -861,6 +893,7 @@ public void test09_MetaData_FromQuery() throws SQLException { assertEquals("ColDateArray", metadata.getColumnLabel(++index)); assertEquals("ColTimestampArray", metadata.getColumnLabel(++index)); assertEquals("ColNumericArray", metadata.getColumnLabel(++index)); + assertEquals("ColJsonArray", metadata.getColumnLabel(++index)); assertEquals("ColComputed", metadata.getColumnLabel(++index)); } } @@ -880,104 +913,135 @@ public void test10_MetaData_FromDML() throws SQLException { @Test public void test11_InsertDataUsingSpannerValue() throws SQLException { + String sql; + if (EmulatorSpannerHelper.isUsingEmulator()) { + sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } else { + sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + } try (Connection con = createConnection()) { - try (PreparedStatement ps = - con.prepareStatement( - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { - ps.setObject(1, Value.int64(2L)); - ps.setObject(2, Value.float64(2D)); - ps.setObject(3, Value.bool(true)); - ps.setObject(4, Value.string("testvalues")); - ps.setObject(5, Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967")); - ps.setObject(6, Value.bytes(ByteArray.copyFrom("test".getBytes()))); - ps.setObject(7, Value.bytes(ByteArray.copyFrom("testtest".getBytes()))); - ps.setObject(8, Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3))); + try (PreparedStatement ps = con.prepareStatement(sql)) { + int index = 1; + ps.setObject(index++, Value.int64(2L)); + ps.setObject(index++, Value.float64(2D)); + ps.setObject(index++, Value.bool(true)); + ps.setObject(index++, Value.string("testvalues")); + ps.setObject(index++, Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967")); + ps.setObject(index++, Value.bytes(ByteArray.copyFrom("test".getBytes()))); + ps.setObject(index++, Value.bytes(ByteArray.copyFrom("testtest".getBytes()))); + ps.setObject(index++, Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3))); ps.setObject( - 9, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99))); - ps.setObject(10, Value.numeric(BigDecimal.TEN)); - ps.setObject(11, Value.int64Array(new long[] {1L, 2L, 3L})); - ps.setObject(12, Value.float64Array(new double[] {1.1D, 2.2D, 3.3D})); - ps.setObject(13, Value.boolArray(Arrays.asList(Boolean.TRUE, null, Boolean.FALSE))); - ps.setObject(14, Value.stringArray(Arrays.asList("1", "2", "3"))); - ps.setObject(15, Value.stringArray(Arrays.asList("3", "2", "1"))); + index++, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99))); + ps.setObject(index++, Value.numeric(BigDecimal.TEN)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + ps.setObject(index++, Value.json("{\"test_value\": \"foo\"}")); + } + ps.setObject(index++, Value.int64Array(new long[] {1L, 2L, 3L})); + ps.setObject(index++, Value.float64Array(new double[] {1.1D, 2.2D, 3.3D})); + ps.setObject(index++, Value.boolArray(Arrays.asList(Boolean.TRUE, null, Boolean.FALSE))); + ps.setObject(index++, Value.stringArray(Arrays.asList("1", "2", "3"))); + ps.setObject(index++, Value.stringArray(Arrays.asList("3", "2", "1"))); ps.setObject( - 16, + index++, Value.bytesArray( Arrays.asList( ByteArray.copyFrom("1"), ByteArray.copyFrom("2"), ByteArray.copyFrom("3")))); ps.setObject( - 17, + index++, Value.bytesArray( Arrays.asList( ByteArray.copyFrom("333"), ByteArray.copyFrom("222"), ByteArray.copyFrom("111")))); ps.setObject( - 18, + index++, Value.dateArray( Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3), null))); ps.setObject( - 19, + index++, Value.timestampArray( Arrays.asList(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99), null))); - ps.setObject(20, Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN))); + ps.setObject( + index++, Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN))); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + ps.setObject( + index++, + Value.jsonArray(Arrays.asList("{\"key1\": \"val1\"}", null, "{\"key2\": \"val2\"}"))); + } assertEquals(1, ps.executeUpdate()); } try (ResultSet rs = con.createStatement() .executeQuery("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=2")) { assertTrue(rs.next()); - assertEquals(Value.int64(2L), rs.getObject(1, Value.class)); - assertEquals(Value.float64(2d), rs.getObject(2, Value.class)); - assertEquals(Value.bool(true), rs.getObject(3, Value.class)); - assertEquals(Value.string("testvalues"), rs.getObject(4, Value.class)); + int index = 1; + assertEquals(Value.int64(2L), rs.getObject(index++, Value.class)); + assertEquals(Value.float64(2d), rs.getObject(index++, Value.class)); + assertEquals(Value.bool(true), rs.getObject(index++, Value.class)); + assertEquals(Value.string("testvalues"), rs.getObject(index++, Value.class)); + assertEquals( + Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967"), + rs.getObject(index++, Value.class)); + assertEquals(Value.bytes(ByteArray.copyFrom("test")), rs.getObject(index++, Value.class)); assertEquals( - Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967"), rs.getObject(5, Value.class)); - assertEquals(Value.bytes(ByteArray.copyFrom("test")), rs.getObject(6, Value.class)); - assertEquals(Value.bytes(ByteArray.copyFrom("testtest")), rs.getObject(7, Value.class)); + Value.bytes(ByteArray.copyFrom("testtest")), rs.getObject(index++, Value.class)); assertEquals( Value.date(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3)), - rs.getObject(8, Value.class)); + rs.getObject(index++, Value.class)); assertEquals( Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99)), - rs.getObject(9, Value.class)); - assertNotNull(rs.getObject(10, Value.class)); // Commit timestamp - assertEquals(Value.numeric(BigDecimal.TEN), rs.getObject(11, Value.class)); - assertEquals(Value.int64Array(new long[] {1L, 2L, 3L}), rs.getObject(12, Value.class)); + rs.getObject(index++, Value.class)); + assertNotNull(rs.getObject(index++, Value.class)); // Commit timestamp + assertEquals(Value.numeric(BigDecimal.TEN), rs.getObject(index++, Value.class)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + assertEquals(Value.json("{\"test_value\":\"foo\"}"), rs.getObject(index++, Value.class)); + } + assertEquals(Value.int64Array(new long[] {1L, 2L, 3L}), rs.getObject(index++, Value.class)); assertEquals( - Value.float64Array(new double[] {1.1D, 2.2D, 3.3D}), rs.getObject(13, Value.class)); + Value.float64Array(new double[] {1.1D, 2.2D, 3.3D}), + rs.getObject(index++, Value.class)); assertEquals( - Value.boolArray(Arrays.asList(true, null, false)), rs.getObject(14, Value.class)); + Value.boolArray(Arrays.asList(true, null, false)), rs.getObject(index++, Value.class)); assertEquals( - Value.stringArray(Arrays.asList("1", "2", "3")), rs.getObject(15, Value.class)); + Value.stringArray(Arrays.asList("1", "2", "3")), rs.getObject(index++, Value.class)); assertEquals( - Value.stringArray(Arrays.asList("3", "2", "1")), rs.getObject(16, Value.class)); + Value.stringArray(Arrays.asList("3", "2", "1")), rs.getObject(index++, Value.class)); assertEquals( Value.bytesArray( Arrays.asList( ByteArray.copyFrom("1"), ByteArray.copyFrom("2"), ByteArray.copyFrom("3"))), - rs.getObject(17, Value.class)); + rs.getObject(index++, Value.class)); assertEquals( Value.bytesArray( Arrays.asList( ByteArray.copyFrom("333"), ByteArray.copyFrom("222"), ByteArray.copyFrom("111"))), - rs.getObject(18, Value.class)); + rs.getObject(index++, Value.class)); assertEquals( Value.dateArray( Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2021, 5, 3), null)), - rs.getObject(19, Value.class)); + rs.getObject(index++, Value.class)); assertEquals( Value.timestampArray( Arrays.asList(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99), null)), - rs.getObject(20, Value.class)); + rs.getObject(index++, Value.class)); assertEquals( Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN)), - rs.getObject(21, Value.class)); + rs.getObject(index++, Value.class)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + assertEquals( + Value.jsonArray(Arrays.asList("{\"key1\":\"val1\"}", null, "{\"key2\":\"val2\"}")), + rs.getObject(index++, Value.class)); + } assertFalse(rs.next()); } } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 6a8c4616d1d6..9b2cb3bad0f3 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -74,6 +74,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColTimestamp TIMESTAMP NOT NULL, ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), ColNumeric NUMERIC NOT NULL, + ColJson JSON NOT NULL, ColInt64Array ARRAY, ColFloat64Array ARRAY, @@ -85,6 +86,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColDateArray ARRAY, ColTimestampArray ARRAY, ColNumericArray ARRAY, + ColJsonArray ARRAY, ColComputed STRING(MAX) AS (CONCAT(COALESCE(ColString, ''), ' ', COALESCE(ColStringMax, ''))) STORED, ) PRIMARY KEY (ColInt64) diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql new file mode 100644 index 000000000000..d1e73bba2009 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql @@ -0,0 +1,104 @@ +/* + * Copyright 2019 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. + */ + +START BATCH DDL; + +CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo BYTES(MAX), + BirthDate DATE +) PRIMARY KEY(SingerId); + +CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); + +CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX), + MarketingBudget INT64 +) PRIMARY KEY(SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE; + +CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); + +CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget); + +CREATE TABLE Songs ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + TrackId INT64 NOT NULL, + SongName STRING(MAX), + Duration INT64, + SongGenre STRING(25) +) PRIMARY KEY(SingerId, AlbumId, TrackId), + INTERLEAVE IN PARENT Albums ON DELETE CASCADE; + +CREATE UNIQUE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums; + +CREATE INDEX SongsBySongName ON Songs(SongName); + +CREATE TABLE Concerts ( + VenueId INT64 NOT NULL, + SingerId INT64 NOT NULL, + ConcertDate DATE NOT NULL, + BeginTime TIMESTAMP, + EndTime TIMESTAMP, + TicketPrices ARRAY, + CONSTRAINT Fk_Concerts_Singer FOREIGN KEY (SingerId) REFERENCES Singers (SingerId) +) PRIMARY KEY(VenueId, SingerId, ConcertDate); + +CREATE TABLE TableWithAllColumnTypes ( + ColInt64 INT64 NOT NULL, + ColFloat64 FLOAT64 NOT NULL, + ColBool BOOL NOT NULL, + ColString STRING(100) NOT NULL, + ColStringMax STRING(MAX) NOT NULL, + ColBytes BYTES(100) NOT NULL, + ColBytesMax BYTES(MAX) NOT NULL, + ColDate DATE NOT NULL, + ColTimestamp TIMESTAMP NOT NULL, + ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), + ColNumeric NUMERIC NOT NULL, + + ColInt64Array ARRAY, + ColFloat64Array ARRAY, + ColBoolArray ARRAY, + ColStringArray ARRAY, + ColStringMaxArray ARRAY, + ColBytesArray ARRAY, + ColBytesMaxArray ARRAY, + ColDateArray ARRAY, + ColTimestampArray ARRAY, + ColNumericArray ARRAY, + + ColComputed STRING(MAX) AS (CONCAT(COALESCE(ColString, ''), ' ', COALESCE(ColStringMax, ''))) STORED, +) PRIMARY KEY (ColInt64) +; + +CREATE TABLE TableWithRef ( + Id INT64 NOT NULL, + RefFloat FLOAT64 NOT NULL, + RefString STRING(100) NOT NULL, + RefDate DATE NOT NULL, + CONSTRAINT Fk_TableWithRef_TableWithAllColumnTypes + FOREIGN KEY (RefFloat, RefString, RefDate) + REFERENCES TableWithAllColumnTypes (ColFloat64, ColString, ColDate) +) PRIMARY KEY (Id) +; + +RUN BATCH; \ No newline at end of file From 7f6e87867a6cbb2b2f773be4d2750be29da039f3 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 25 Aug 2021 16:32:09 -0700 Subject: [PATCH 0503/1979] chore: enable release-trigger bot (#578) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/0ceba58c-0130-48cd-b39f-2943de71b108/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/63cff634aabb85854caa511c5837ea6b45f42b4b --- java-spanner-jdbc/.github/release-trigger.yml | 1 + java-spanner-jdbc/synth.metadata | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.github/release-trigger.yml diff --git a/java-spanner-jdbc/.github/release-trigger.yml b/java-spanner-jdbc/.github/release-trigger.yml new file mode 100644 index 000000000000..d4ca94189e16 --- /dev/null +++ b/java-spanner-jdbc/.github/release-trigger.yml @@ -0,0 +1 @@ +enabled: true diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 8f46bdb7c156..f253e5ec7e32 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "813a13d993ef2ad61ca7acda6700760a4cfcd512" + "sha": "ca1c906e1ed3cad6444068ab9c8465401d6d3074" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ff01716e16d2c6e87eaf87197b753ac9fcbbed5d" + "sha": "63cff634aabb85854caa511c5837ea6b45f42b4b" } } ], @@ -23,6 +23,7 @@ ".github/PULL_REQUEST_TEMPLATE.md", ".github/generated-files-bot.yml", ".github/readme/synth.py", + ".github/release-trigger.yml", ".github/snippet-bot.yml", ".github/trusted-contribution.yml", ".github/workflows/approve-readme.yaml", From 216bd0dfd950d08744c2385ce228b034f481e937 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 27 Aug 2021 06:02:55 +0200 Subject: [PATCH 0504/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v22 (#581) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ae8f5954d966..0e78b22dcc1f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 21.0.0 + 22.0.0 pom import From cb2ae621d3300516dfb9472f2a4476bb21dd2dd7 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 26 Aug 2021 21:03:35 -0700 Subject: [PATCH 0505/1979] ci: removing linkage-monitor from the required checks (#580) Source-Author: Tomo Suzuki Source-Date: Wed Aug 25 13:18:10 2021 -0400 Source-Repo: googleapis/synthtool Source-Sha: e2aa5bcc3356d9e3b8b53de3b5c86226447d3a22 Source-Link: https://github.com/googleapis/synthtool/commit/e2aa5bcc3356d9e3b8b53de3b5c86226447d3a22 --- java-spanner-jdbc/.github/workflows/ci.yaml | 13 ------------- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 65ae6ecdda77..d510359d97df 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -42,19 +42,6 @@ jobs: java-version: ${{matrix.java}} - run: java -version - run: .kokoro/dependencies.sh - linkage-monitor: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 - with: - java-version: 8 - - run: java -version - - name: Install artifacts to local Maven repository - run: .kokoro/build.sh - shell: bash - - name: Validate any conflicts with regard to com.google.cloud:libraries-bom (latest release) - uses: GoogleCloudPlatform/cloud-opensource-java/linkage-monitor@v1-linkagemonitor lint: runs-on: ubuntu-latest steps: diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index f253e5ec7e32..802184ed3d21 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ca1c906e1ed3cad6444068ab9c8465401d6d3074" + "sha": "6bdbbbcdec6095cdf4f66d34a6d91644501fa955" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "63cff634aabb85854caa511c5837ea6b45f42b4b" + "sha": "e2aa5bcc3356d9e3b8b53de3b5c86226447d3a22" } } ], From 25b96f418f84e4b941c81ced7a018ae2dfadf664 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 27 Aug 2021 06:44:35 +0200 Subject: [PATCH 0506/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.1 (#577) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1fc8eb149795..d147fd5e803f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.12.0 + 6.12.1 pom import From 5d3289a4706ffd1df610be22f0042cbafa974f81 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 Aug 2021 11:04:12 +0000 Subject: [PATCH 0507/1979] chore: release 2.4.0 (#576) :robot: I have created a release \*beep\* \*boop\* --- ## [2.4.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.5...v2.4.0) (2021-08-27) ### Features * support JSON data type ([#447](https://www.github.com/googleapis/java-spanner-jdbc/issues/447)) ([d631672](https://www.github.com/googleapis/java-spanner-jdbc/commit/d63167206b9c0a79089da74e45b41146770f915d)) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.1 ([#577](https://www.github.com/googleapis/java-spanner-jdbc/issues/577)) ([25b96f4](https://www.github.com/googleapis/java-spanner-jdbc/commit/25b96f418f84e4b941c81ced7a018ae2dfadf664)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 315f5f2e69de..7db9bc63b0b0 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.4.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.5...v2.4.0) (2021-08-27) + + +### Features + +* support JSON data type ([#447](https://www.github.com/googleapis/java-spanner-jdbc/issues/447)) ([ca1c906](https://www.github.com/googleapis/java-spanner-jdbc/commit/ca1c906e1ed3cad6444068ab9c8465401d6d3074)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.1 ([#577](https://www.github.com/googleapis/java-spanner-jdbc/issues/577)) ([a78b177](https://www.github.com/googleapis/java-spanner-jdbc/commit/a78b177f97c298a5b43fcadbca125e957e9f781a)) + ### [2.3.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.4...v2.3.5) (2021-08-24) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d147fd5e803f..50546f0ca200 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.3.6-SNAPSHOT + 2.4.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 7d0dbe5006a2..c1d4be500a9d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.6-SNAPSHOT + 2.4.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4e03da498f95..148bf607e37d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.3.5:2.3.6-SNAPSHOT +google-cloud-spanner-jdbc:2.4.0:2.4.0 From bfc2de238e91af6a9e415d9b0f92980d22458dd4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 27 Aug 2021 15:38:24 +0200 Subject: [PATCH 0508/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.4.0 (#583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.3.5` -> `2.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.0/compatibility-slim/2.3.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.0/confidence-slim/2.3.5)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.4.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​240-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev235v240-2021-08-27) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.3.5...v2.4.0) ##### Features - support JSON data type ([#​447](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/447)) ([d631672](https://www.github.com/googleapis/java-spanner-jdbc/commit/d63167206b9c0a79089da74e45b41146770f915d)) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.1 ([#​577](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/577)) ([25b96f4](https://www.github.com/googleapis/java-spanner-jdbc/commit/25b96f418f84e4b941c81ced7a018ae2dfadf664)) ##### [2.3.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.4...v2.3.5) (2021-08-24) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.0 ([#​568](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/568)) ([8b36104](https://www.github.com/googleapis/java-spanner-jdbc/commit/8b36104f0d050c529b89191e34271c07a7b87405)) ##### [2.3.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.3...v2.3.4) (2021-08-23) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.1.0 ([#​563](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/563)) ([2352f1a](https://www.github.com/googleapis/java-spanner-jdbc/commit/2352f1ac16814c1af693d79bba38c7f7aa517fe9)) ##### [2.3.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.2...v2.3.3) (2021-08-19) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.1 ([#​556](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/556)) ([80a7010](https://www.github.com/googleapis/java-spanner-jdbc/commit/80a7010906cc88bae1fd1218dbeca4df112c7823)) ##### [2.3.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.1...v2.3.2) (2021-08-12) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.11.0 ([#​549](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/549)) ([5cd4033](https://www.github.com/googleapis/java-spanner-jdbc/commit/5cd40339b2989eb877f79d66be2b27eaae644c33)) ##### [2.3.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.0...v2.3.1) (2021-08-12) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.10.1 ([#​538](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/538)) ([d0bc641](https://www.github.com/googleapis/java-spanner-jdbc/commit/d0bc6413f17824af7c02134bacb29b4b7bce74d5))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7de5356db118..52456c7558ba 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.3.5 + 2.4.0 From 2e1f360944765e9a619ea8fd81aa62a92be9f2d6 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 27 Aug 2021 06:56:24 -0700 Subject: [PATCH 0509/1979] chore: regenerate README (#584) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-27 13:40:27,564 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-27 13:40:28,602 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/00c1dbb5-da89-41bb-b027-43a6d015dfe2/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index ee98f7c4710e..e919a1a6c779 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "53114ec7393e7ff5d0c1f01082eaa0aceeb3bf10" + "sha": "c4621747c1d02e2abc1d5a01c0c0870399bbfca8" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "8032ab5a32471d85ece8fc261df16cc40fbfa4fb" + "sha": "31728d872f50e439ded2f67fa8d67955b26a4e35" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8bfaf97841f4..2c37598ae700 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.3.5 + 2.4.0 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.3.5' +compile 'com.google.cloud:google-cloud-spanner-jdbc:2.4.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.3.5" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.4.0" ``` ## Authentication From 03b49a71a9847539350749cc4e475896fac1457a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 14:49:55 +1000 Subject: [PATCH 0510/1979] chore: release 2.4.1-SNAPSHOT (#582) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 50546f0ca200..4888c6754c81 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.0 + 2.4.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c1d4be500a9d..7c76ac486ca6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.0 + 2.4.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 148bf607e37d..fb05158f8388 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.0:2.4.0 +google-cloud-spanner-jdbc:2.4.0:2.4.1-SNAPSHOT From 0e8704dd22f14a4624d42d336078eb88fd2a56c2 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Mon, 30 Aug 2021 22:10:27 -0700 Subject: [PATCH 0511/1979] chore: regenerate README (#585) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-08-31 04:52:01,965 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-08-31 04:52:03,388 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/2e7ba583-448b-4508-a2b5-5d04cd343c74/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index e919a1a6c779..b6b055839d61 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "c4621747c1d02e2abc1d5a01c0c0870399bbfca8" + "sha": "7b341394dfe0ee7cae5131681ee72d9750eccce1" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "31728d872f50e439ded2f67fa8d67955b26a4e35" + "sha": "dfd55ad78a700acf987d592c8279789b1319b8c5" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 2c37598ae700..cb2022bcee79 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -26,7 +26,7 @@ If you are using Maven, add this to your pom.xml file: If you are using Gradle without BOM, add this to your dependencies ```Groovy -compile 'com.google.cloud:google-cloud-spanner-jdbc:2.4.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.4.0' ``` If you are using SBT, add this to your dependencies From 8e9d2f8e301520802979feff59da6684ff55899b Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Tue, 31 Aug 2021 15:04:49 -0700 Subject: [PATCH 0512/1979] build(java): update renovate config to mark conformance tests as a test commit type (#587) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/453a1ad7-572e-4fc1-9d6e-c50f07456c5f/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/9a238a0623879c3de129a376c6085d4a862f6eb9 --- java-spanner-jdbc/renovate.json | 3 ++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index a95a109bdda5..d469dda3018d 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -50,7 +50,8 @@ "^junit:junit", "^com.google.truth:truth", "^org.mockito:mockito-core", - "^org.objenesis:objenesis" + "^org.objenesis:objenesis", + "^com.google.cloud:google-cloud-conformance-tests" ], "semanticCommitType": "test", "semanticCommitScope": "deps" diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index 802184ed3d21..f5b0f453e0fb 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "6bdbbbcdec6095cdf4f66d34a6d91644501fa955" + "sha": "2c9650facf3e9e5a327caeb2ab7550299b38a57b" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "e2aa5bcc3356d9e3b8b53de3b5c86226447d3a22" + "sha": "9a238a0623879c3de129a376c6085d4a862f6eb9" } } ], From 58e90f7ee86906bf9936fef6f587741d5bd34e5e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 1 Sep 2021 00:08:38 +0200 Subject: [PATCH 0513/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.0 (#586) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.1.0` -> `2.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.0/compatibility-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.0/confidence-slim/2.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.2.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​220-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare210v220-2021-08-31) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.1.0...v2.2.0) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.12.5 ([#​456](https://www.togithub.com/googleapis/java-shared-dependencies/issues/456)) ([05b58e8](https://www.github.com/googleapis/java-shared-dependencies/commit/05b58e84ff6617bdcbb1ea644aa6e061bdea0319)) - update dependency com.google.api:api-common to v2.0.2 ([#​450](https://www.togithub.com/googleapis/java-shared-dependencies/issues/450)) ([51caebe](https://www.github.com/googleapis/java-shared-dependencies/commit/51caebe89bfade98866f63952bf82bc663a0179a)) - update dependency com.google.http-client:google-http-client-bom to v1.40.0 ([#​455](https://www.togithub.com/googleapis/java-shared-dependencies/issues/455)) ([82a5e42](https://www.github.com/googleapis/java-shared-dependencies/commit/82a5e42b06570a2c7c9d53b03161b110a44487a1)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.32.1 ([#​447](https://www.togithub.com/googleapis/java-shared-dependencies/issues/447)) ([9d2b895](https://www.github.com/googleapis/java-shared-dependencies/commit/9d2b8958f62daa6a3015a8ac052762fb3d79b35b)) - update dependency io.grpc:grpc-bom to v1.40.1 ([#​451](https://www.togithub.com/googleapis/java-shared-dependencies/issues/451)) ([df668ea](https://www.github.com/googleapis/java-shared-dependencies/commit/df668ead8830a40acf9d5605d47f93c465b779c0)) - update gax.version to v2.4.0 ([#​458](https://www.togithub.com/googleapis/java-shared-dependencies/issues/458)) ([a797d9e](https://www.github.com/googleapis/java-shared-dependencies/commit/a797d9eb8a4bcb3025a9511eae61271278a4a5c9)) - update google.common-protos.version to v2.5.0 ([#​457](https://www.togithub.com/googleapis/java-shared-dependencies/issues/457)) ([38c7bb9](https://www.github.com/googleapis/java-shared-dependencies/commit/38c7bb925414d90ff3065650d06589f79bcab9b6)) - update google.core.version to v2.1.1 ([#​449](https://www.togithub.com/googleapis/java-shared-dependencies/issues/449)) ([b28723a](https://www.github.com/googleapis/java-shared-dependencies/commit/b28723ace0c27ebc73f23a2d094e0fe9ba8a9075)) - update google.core.version to v2.1.2 ([#​459](https://www.togithub.com/googleapis/java-shared-dependencies/issues/459)) ([df4d5b7](https://www.github.com/googleapis/java-shared-dependencies/commit/df4d5b7717386f5e0e2cca87bd9afc56b2c7aee8)) - update iam.version to v1.1.0 ([#​448](https://www.togithub.com/googleapis/java-shared-dependencies/issues/448)) ([3967928](https://www.github.com/googleapis/java-shared-dependencies/commit/39679287f3ef8c1cbca5dfc8aca3f69cfee3d4a6))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4888c6754c81..f6a2df168f61 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.1.0 + 2.2.0 pom import From 52c8efe6c476f0c824cd812ae6c1e26d605c6b10 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 22:36:36 +0000 Subject: [PATCH 0514/1979] chore: release 2.4.1 (#588) :robot: I have created a release \*beep\* \*boop\* --- ### [2.4.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.0...v2.4.1) (2021-08-31) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.0 ([#586](https://www.github.com/googleapis/java-spanner-jdbc/issues/586)) ([58e90f7](https://www.github.com/googleapis/java-spanner-jdbc/commit/58e90f7ee86906bf9936fef6f587741d5bd34e5e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 7db9bc63b0b0..654d4ad1343c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.4.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.0...v2.4.1) (2021-08-31) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.0 ([#586](https://www.github.com/googleapis/java-spanner-jdbc/issues/586)) ([5c681bf](https://www.github.com/googleapis/java-spanner-jdbc/commit/5c681bf4a1c46535759cf6a0820798141051c1d0)) + ## [2.4.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.3.5...v2.4.0) (2021-08-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f6a2df168f61..ffa71be031d0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.1-SNAPSHOT + 2.4.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 7c76ac486ca6..d028c19bd7f8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.1-SNAPSHOT + 2.4.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fb05158f8388..ad026822b5ca 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.0:2.4.1-SNAPSHOT +google-cloud-spanner-jdbc:2.4.1:2.4.1 From d687f326037df66a39ed66ca04af6e25dcb16915 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 22:58:34 +0000 Subject: [PATCH 0515/1979] chore: release 2.4.2-SNAPSHOT (#589) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ffa71be031d0..8ba859c23278 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.1 + 2.4.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d028c19bd7f8..8c328af5fec4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.1 + 2.4.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ad026822b5ca..7c0c1241057f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.1:2.4.1 +google-cloud-spanner-jdbc:2.4.1:2.4.2-SNAPSHOT From a0e52df5e9507e46a2ab809aeaac7c7b1eac5716 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 2 Sep 2021 03:19:44 +0200 Subject: [PATCH 0516/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.2 (#591) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8ba859c23278..4a81b80ad6f4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.12.1 + 6.12.2 pom import From 9a92d5a3c112afbfe4add9dcca660e403206ee72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 2 Sep 2021 03:20:53 +0200 Subject: [PATCH 0517/1979] build: execute integration tests in parallel (#592) * build: execute integration tests in parallel * chore: run linter --- java-spanner-jdbc/pom.xml | 37 +++++++++++++++---- .../spanner/jdbc/ITAbstractJdbcTest.java | 4 +- .../spanner/jdbc/it/ITJdbcConnectTest.java | 4 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 4 +- .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 4 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 4 +- .../jdbc/it/ITJdbcQueryOptionsTest.java | 4 +- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 4 +- .../it/ITJdbcReadWriteAutocommitTest.java | 4 +- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 4 +- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 4 +- .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 4 +- 12 files changed, 51 insertions(+), 30 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4a81b80ad6f4..8f4bf0f2ae11 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -141,7 +141,7 @@ com.google.api.grpc proto-google-cloud-spanner-v1 - + com.google.cloud @@ -219,18 +219,41 @@ maven-failsafe-plugin - com.google.cloud.spanner.GceTestEnvConfig - projects/gcloud-devel/instances/spanner-testing + + com.google.cloud.spanner.GceTestEnvConfig + + + projects/gcloud-devel/instances/spanner-testing + - com.google.cloud.spanner.IntegrationTest - com.google.cloud.spanner.FlakyTest 2400 + default + + integration-test + + + com.google.cloud.spanner.IntegrationTest + + com.google.cloud.spanner.FlakyTest,com.google.cloud.spanner.ParallelIntegrationTest + + + + + parallel-integration-test integration-test + + com.google.cloud.spanner.ParallelIntegrationTest + + com.google.cloud.spanner.FlakyTest,com.google.cloud.spanner.IntegrationTest + + 8 + true + @@ -318,7 +341,7 @@ - + shade @@ -361,7 +384,7 @@ - + diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index 67af3179d628..64b6aa6cf803 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -27,7 +27,6 @@ import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.sql.Connection; @@ -35,7 +34,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.concurrent.ExecutionException; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -90,7 +88,7 @@ protected static Database getDatabase() { } @BeforeClass - public static void setup() throws IOException, InterruptedException, ExecutionException { + public static void setup() { database = env.getTestHelper().createTestDatabase(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 88f577ec9ae4..6d7cd0622cca 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -20,7 +20,7 @@ import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -49,7 +49,7 @@ * * This class tests all three possibilities. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcConnectTest extends ITAbstractJdbcTest { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 087d688fc1fc..9c0d9a6e532c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -23,7 +23,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeFalse; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; @@ -40,7 +40,7 @@ import org.junit.runners.JUnit4; /** Integration tests for {@link DatabaseMetaData} implementation for Spanner. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String DEFAULT_CATALOG = ""; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index 0b192127d7ef..c559bb3fc2f5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -16,7 +16,7 @@ package com.google.cloud.spanner.jdbc.it; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; @@ -26,7 +26,7 @@ import org.junit.runners.JUnit4; /** Execute DDL statements using JDBC. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcDdlTest extends ITAbstractJdbcTest { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index ea1bbfb328ea..24a9e01f4fc3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -27,7 +27,7 @@ import static org.junit.Assume.assumeFalse; import com.google.cloud.ByteArray; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JsonType; @@ -64,7 +64,7 @@ import org.junit.runners.MethodSorters; /** Integration tests for JDBC {@link PreparedStatement}s. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcPreparedStatementTest extends ITAbstractJdbcTest { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index ac90687c8217..990331074ea2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -23,7 +23,7 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -53,7 +53,7 @@ * * This class tests all three possibilities. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcQueryOptionsTest extends ITAbstractJdbcTest { private String connectionUriSuffix; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 98700d5ed26d..0e5a2f91a45d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -16,8 +16,8 @@ package com.google.cloud.spanner.jdbc.it; -import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; @@ -37,7 +37,7 @@ import org.junit.runners.JUnit4; /** This test class runs a SQL script for testing a connection in read-only mode. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcReadOnlyTest extends ITAbstractJdbcTest { private static final long TEST_ROWS_COUNT = 1000L; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index e6a296285afc..d72992aec0ca 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -20,8 +20,8 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -33,7 +33,7 @@ import org.junit.runners.JUnit4; import org.junit.runners.MethodSorters; -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcReadWriteAutocommitTest extends ITAbstractJdbcTest { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index fcb3b0e44073..0793849344bc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -23,7 +23,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -41,7 +41,7 @@ /** Test executing simple statements through JDBC. */ @RunWith(JUnit4.class) -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) public class ITJdbcSimpleStatementsTest extends ITAbstractJdbcTest { @Test public void testSelect1() throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 244e9f1db4de..31b8394ad9b1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -16,7 +16,7 @@ package com.google.cloud.spanner.jdbc.it; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; @@ -27,7 +27,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcSqlMusicScriptTest extends ITAbstractJdbcTest { private static final String SCRIPT_FILE = "ITSqlMusicScriptTest.sql"; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index 5133fc4d38d2..fdb752965b23 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -22,7 +22,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.IntegrationTest; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; @@ -44,7 +44,7 @@ * performs all possible operations on this test database using only sql scripts. This test uses the * JDBC driver for Spanner. */ -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcSqlScriptTest extends ITAbstractJdbcTest { From 8098e42a252d62cad7f559bad21e1cfd28934d38 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Wed, 1 Sep 2021 18:28:29 -0700 Subject: [PATCH 0518/1979] chore: regenerate README (#594) This PR was generated using Autosynth. :rainbow:
    Log from Synthtool ``` 2021-09-02 01:21:44,227 synthtool [DEBUG] > Executing /root/.cache/synthtool/java-spanner-jdbc/.github/readme/synth.py. On branch autosynth-readme nothing to commit, working tree clean 2021-09-02 01:21:46,100 synthtool [DEBUG] > Wrote metadata to .github/readme/synth.metadata/synth.metadata. ```
    Full log will be available here: https://source.cloud.google.com/results/invocations/56eab260-2a0e-4455-80ae-e9acfadb443b/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) --- .../.github/readme/synth.metadata/synth.metadata | 4 ++-- java-spanner-jdbc/README.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata index b6b055839d61..2d26f0385947 100644 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "7b341394dfe0ee7cae5131681ee72d9750eccce1" + "sha": "5e1504d217563e4b9cd34211cbca55856fad0e60" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "dfd55ad78a700acf987d592c8279789b1319b8c5" + "sha": "5c0fa62eea9c33ebe61e582424b659eb264e1ba4" } } ] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index cb2022bcee79..9a086c957457 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -19,20 +19,20 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.4.0 + 2.4.1 ``` If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.4.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.4.1' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.4.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.4.1" ``` ## Authentication From 875413e1f41aad03dc66863bc99502191cf36421 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 2 Sep 2021 03:32:36 +0200 Subject: [PATCH 0519/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.4.1 (#590) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.4.0` -> `2.4.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.1/compatibility-slim/2.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.1/confidence-slim/2.4.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.4.1`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​241-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev240v241-2021-08-31) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.4.0...v2.4.1)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 52456c7558ba..7d3ad28dd710 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.0 + 2.4.1 From ddd1a4025c66feeb56f2f8e85fa5afc7c749368a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:36:13 +0000 Subject: [PATCH 0520/1979] chore: release 2.4.2 (#593) :robot: I have created a release \*beep\* \*boop\* --- ### [2.4.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.1...v2.4.2) (2021-09-02) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.2 ([#591](https://www.github.com/googleapis/java-spanner-jdbc/issues/591)) ([a0e52df](https://www.github.com/googleapis/java-spanner-jdbc/commit/a0e52df5e9507e46a2ab809aeaac7c7b1eac5716)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 654d4ad1343c..6cd08c39ccf5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.4.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.1...v2.4.2) (2021-09-02) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.2 ([#591](https://www.github.com/googleapis/java-spanner-jdbc/issues/591)) ([0f39b23](https://www.github.com/googleapis/java-spanner-jdbc/commit/0f39b23d66c8d3fb9314affbb67a47c394db3b46)) + ### [2.4.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.0...v2.4.1) (2021-08-31) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8f4bf0f2ae11..e0c39f4f2f0f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.2-SNAPSHOT + 2.4.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8c328af5fec4..b122e6dbfdf9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.2-SNAPSHOT + 2.4.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7c0c1241057f..4e2729bd22a7 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.1:2.4.2-SNAPSHOT +google-cloud-spanner-jdbc:2.4.2:2.4.2 From 0d085d44bceb90137e8ffe413687f9a7e7d8ffe2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 01:42:29 +0000 Subject: [PATCH 0521/1979] chore: release 2.4.3-SNAPSHOT (#595) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e0c39f4f2f0f..1e209c7873e3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.2 + 2.4.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b122e6dbfdf9..5ce451791d13 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.2 + 2.4.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4e2729bd22a7..219f0d8f5e37 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.2:2.4.2 +google-cloud-spanner-jdbc:2.4.2:2.4.3-SNAPSHOT From ef7c25fcc1af7ddec23f17674ac6e0d315fe0fe6 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 2 Sep 2021 17:58:31 +0200 Subject: [PATCH 0522/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.4.2 (#596) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.4.1` -> `2.4.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.2/compatibility-slim/2.4.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.4.2/confidence-slim/2.4.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.4.2`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​242-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev241v242-2021-09-02) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.4.1...v2.4.2)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7d3ad28dd710..cf34d1d57ab8 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.1 + 2.4.2 From 61dded9ad253793361d501e3c55a735f065c4c67 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Fri, 3 Sep 2021 08:46:24 -0700 Subject: [PATCH 0523/1979] chore(java): install maven 3.8.1 at runtime (#598) This PR was generated using Autosynth. :rainbow: Synth log will be available here: https://source.cloud.google.com/results/invocations/b322e4c1-fcf2-40ff-9f55-6ae5173625bf/targets - [ ] To automatically regenerate this PR, check this box. (May take up to 24 hours.) Source-Link: https://github.com/googleapis/synthtool/commit/ad7fd76e17bf9494a3e47ff9cf445f61564432e0 --- java-spanner-jdbc/.github/workflows/ci.yaml | 14 +++++++++++++- java-spanner-jdbc/synth.metadata | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index d510359d97df..e23d923e1e72 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -12,6 +12,9 @@ jobs: java: [8, 11] steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: ${{matrix.java}} @@ -37,6 +40,9 @@ jobs: java: [8, 11] steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: ${{matrix.java}} @@ -46,6 +52,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 @@ -57,10 +66,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 - run: java -version - run: .kokoro/build.sh env: - JOB_TYPE: clirr + JOB_TYPE: clirr \ No newline at end of file diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index f5b0f453e0fb..e674d473abc3 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "2c9650facf3e9e5a327caeb2ab7550299b38a57b" + "sha": "223e884f223efe2531067e1c154d0d720b455b74" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "9a238a0623879c3de129a376c6085d4a862f6eb9" + "sha": "ad7fd76e17bf9494a3e47ff9cf445f61564432e0" } } ], From 25ccbda2e1d945875dc3264e7ce10289d235429c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 8 Sep 2021 23:14:21 +0200 Subject: [PATCH 0524/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v23 (#602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `22.0.0` -> `23.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.0.0/compatibility-slim/22.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.0.0/confidence-slim/22.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0e78b22dcc1f..9fb986ed4514 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 22.0.0 + 23.0.0 pom import From 75f841b8349dd720e6d782ab1bb09cab9a11ff5a Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Thu, 9 Sep 2021 10:54:21 +1000 Subject: [PATCH 0525/1979] chore: setup maven 3.8.1 for ci tasks (#599) There is a bug with the maven-flattened plugin and maven 3.8.2, which is causing an error on builds. The yoshi team will file a bug under the plugin, but for now we need to downgrade maven to < 3.8.2. --- java-spanner-jdbc/.github/workflows/ci.yaml | 3 +++ .../.github/workflows/integration-tests-against-emulator.yaml | 3 +++ java-spanner-jdbc/.github/workflows/samples.yaml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index e23d923e1e72..aeb5916ae273 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -26,6 +26,9 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index 60647235c60c..b9b595434fc8 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -17,6 +17,9 @@ jobs: steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index c46230a78c38..4140db22be59 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -6,6 +6,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 From eb10535b8d68446a9e1ac0f7b0b2d81550ca25d3 Mon Sep 17 00:00:00 2001 From: Jeff Ching Date: Thu, 9 Sep 2021 12:42:29 -0700 Subject: [PATCH 0526/1979] chore: remove readme autosynth config (#604) --- .../readme/synth.metadata/synth.metadata | 18 ------ java-spanner-jdbc/.github/readme/synth.py | 19 ------- .../.kokoro/continuous/readme.cfg | 55 ------------------- 3 files changed, 92 deletions(-) delete mode 100644 java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata delete mode 100644 java-spanner-jdbc/.github/readme/synth.py delete mode 100644 java-spanner-jdbc/.kokoro/continuous/readme.cfg diff --git a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata b/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata deleted file mode 100644 index 2d26f0385947..000000000000 --- a/java-spanner-jdbc/.github/readme/synth.metadata/synth.metadata +++ /dev/null @@ -1,18 +0,0 @@ -{ - "sources": [ - { - "git": { - "name": ".", - "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "5e1504d217563e4b9cd34211cbca55856fad0e60" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5c0fa62eea9c33ebe61e582424b659eb264e1ba4" - } - } - ] -} \ No newline at end of file diff --git a/java-spanner-jdbc/.github/readme/synth.py b/java-spanner-jdbc/.github/readme/synth.py deleted file mode 100644 index 7b48cc28d361..000000000000 --- a/java-spanner-jdbc/.github/readme/synth.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2020 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. - -"""This script is used to synthesize generated the README for this library.""" - -from synthtool.languages import java - -java.custom_templates(["java_library/README.md"]) diff --git a/java-spanner-jdbc/.kokoro/continuous/readme.cfg b/java-spanner-jdbc/.kokoro/continuous/readme.cfg deleted file mode 100644 index 8c130dec7700..000000000000 --- a/java-spanner-jdbc/.kokoro/continuous/readme.cfg +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2020 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. - -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/readme.sh" -} - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - regex: "**/*sponge_log.log" - } -} - -# The github token is stored here. -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "yoshi-automation-github-key" - # TODO(theacodes): remove this after secrets have globally propagated - backend_type: FASTCONFIGPUSH - } - } -} - -# Common env vars for all repositories and builds. -env_vars: { - key: "GITHUB_USER" - value: "yoshi-automation" -} -env_vars: { - key: "GITHUB_EMAIL" - value: "yoshi-automation@google.com" -} From 8f9eb476e3b282d901eb28d9c231241edb00936a Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 9 Sep 2021 22:06:44 -0700 Subject: [PATCH 0527/1979] chore(java): update windows build (#601) * changes without context autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. * chore(java): update windows build to install maven 3.8.1 at runtime too (related to #1202) Tested in [java-bigquerystorage](https://github.com/googleapis/java-bigquerystorage/pull/1291/commits/7834f4ff86858f6ed0b8068ea66dadf6365e399a) Source-Author: Stephanie Wang Source-Date: Tue Sep 7 13:04:27 2021 -0400 Source-Repo: googleapis/synthtool Source-Sha: 17ee6e5c08f2eb47029beee4776ce990e56b3925 Source-Link: https://github.com/googleapis/synthtool/commit/17ee6e5c08f2eb47029beee4776ce990e56b3925 * chore(java): remove readme autosynth job config README generation is now handled by owlbot Source-Author: Jeff Ching Source-Date: Wed Sep 8 12:11:28 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: df5093b950d4aafd49a4c7758d74c44485263ada Source-Link: https://github.com/googleapis/synthtool/commit/df5093b950d4aafd49a4c7758d74c44485263ada * chore: remove readme synth.py config Source-Author: Jeff Ching Source-Date: Wed Sep 8 13:23:41 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: 2d31a9243781b282202b4f76dc7bbc8b45803196 Source-Link: https://github.com/googleapis/synthtool/commit/2d31a9243781b282202b4f76dc7bbc8b45803196 * chore: add gcf-owl-bot to list of trusted contributors Source-Author: Jeff Ching Source-Date: Wed Sep 8 13:42:12 2021 -0700 Source-Repo: googleapis/synthtool Source-Sha: a6b97202771f89a4b76873d43ea9a07d7fc95f91 Source-Link: https://github.com/googleapis/synthtool/commit/a6b97202771f89a4b76873d43ea9a07d7fc95f91 * chore(java): update shared-config and shared-dependencies version in pom template Source-Author: Neenu Shaji Source-Date: Wed Sep 8 17:28:48 2021 -0400 Source-Repo: googleapis/synthtool Source-Sha: 396d9b84a1e93880f5bf88b59ecd38a0a6dffc5e Source-Link: https://github.com/googleapis/synthtool/commit/396d9b84a1e93880f5bf88b59ecd38a0a6dffc5e --- java-spanner-jdbc/.github/trusted-contribution.yml | 3 ++- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- java-spanner-jdbc/.github/workflows/samples.yaml | 3 --- java-spanner-jdbc/.kokoro/release/common.sh | 2 +- java-spanner-jdbc/.kokoro/release/drop.sh | 2 +- java-spanner-jdbc/.kokoro/release/promote.sh | 2 +- java-spanner-jdbc/.kokoro/release/publish_javadoc.sh | 2 +- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 2 +- java-spanner-jdbc/.kokoro/release/stage.sh | 2 +- java-spanner-jdbc/.kokoro/trampoline.sh | 2 +- java-spanner-jdbc/synth.metadata | 6 ++---- 11 files changed, 12 insertions(+), 16 deletions(-) diff --git a/java-spanner-jdbc/.github/trusted-contribution.yml b/java-spanner-jdbc/.github/trusted-contribution.yml index f247d5c78934..a0ba1f7d9078 100644 --- a/java-spanner-jdbc/.github/trusted-contribution.yml +++ b/java-spanner-jdbc/.github/trusted-contribution.yml @@ -1,2 +1,3 @@ trustedContributors: -- renovate-bot \ No newline at end of file +- renovate-bot +- gcf-owl-bot[bot] diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index aeb5916ae273..3becb5c022a3 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -78,4 +78,4 @@ jobs: - run: java -version - run: .kokoro/build.sh env: - JOB_TYPE: clirr \ No newline at end of file + JOB_TYPE: clirr diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index 4140db22be59..c46230a78c38 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -6,9 +6,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 diff --git a/java-spanner-jdbc/.kokoro/release/common.sh b/java-spanner-jdbc/.kokoro/release/common.sh index 6e3f65999b3d..7f78ee414faf 100755 --- a/java-spanner-jdbc/.kokoro/release/common.sh +++ b/java-spanner-jdbc/.kokoro/release/common.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2018 Google Inc. +# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/release/drop.sh b/java-spanner-jdbc/.kokoro/release/drop.sh index 5c4551efa2c0..742ec1a88600 100755 --- a/java-spanner-jdbc/.kokoro/release/drop.sh +++ b/java-spanner-jdbc/.kokoro/release/drop.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2018 Google Inc. +# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/release/promote.sh b/java-spanner-jdbc/.kokoro/release/promote.sh index 1fa95fa537a3..3cac3d8a97d7 100755 --- a/java-spanner-jdbc/.kokoro/release/promote.sh +++ b/java-spanner-jdbc/.kokoro/release/promote.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2018 Google Inc. +# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index caa7dddfb5f5..2f1cac7d1139 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2019 Google Inc. +# Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 38ee2e5c8ec8..3b65375ef7dc 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2021 Google Inc. +# Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 8a1033843cb1..77dc4e8f0f3a 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2018 Google Inc. +# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/.kokoro/trampoline.sh b/java-spanner-jdbc/.kokoro/trampoline.sh index 9da0f8398773..8b69b793c9ec 100644 --- a/java-spanner-jdbc/.kokoro/trampoline.sh +++ b/java-spanner-jdbc/.kokoro/trampoline.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2018 Google Inc. +# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index e674d473abc3..ea55c524738a 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,14 +4,14 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "223e884f223efe2531067e1c154d0d720b455b74" + "sha": "256ba0683a9095d54a8e60595d5fa7e31f9b2b54" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "ad7fd76e17bf9494a3e47ff9cf445f61564432e0" + "sha": "396d9b84a1e93880f5bf88b59ecd38a0a6dffc5e" } } ], @@ -22,7 +22,6 @@ ".github/ISSUE_TEMPLATE/support_request.md", ".github/PULL_REQUEST_TEMPLATE.md", ".github/generated-files-bot.yml", - ".github/readme/synth.py", ".github/release-trigger.yml", ".github/snippet-bot.yml", ".github/trusted-contribution.yml", @@ -37,7 +36,6 @@ ".kokoro/common.sh", ".kokoro/continuous/common.cfg", ".kokoro/continuous/java8.cfg", - ".kokoro/continuous/readme.cfg", ".kokoro/dependencies.sh", ".kokoro/nightly/common.cfg", ".kokoro/nightly/integration.cfg", From 9851bee2adb811a6a2000e760583d78814f7ce51 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 13 Sep 2021 19:39:06 +0200 Subject: [PATCH 0528/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.3.1 (#600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-javadoc-plugin](https://maven.apache.org/plugins/) | `3.3.0` -> `3.3.1` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.1/compatibility-slim/3.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.1/confidence-slim/3.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1e209c7873e3..05fc8864737b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -417,7 +417,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.0 + 3.3.1 html From 8b9996f008c7ea8841ab0bf4d443e413d126c68b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 14 Sep 2021 04:22:44 +0200 Subject: [PATCH 0529/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.1 (#606) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.2.0` -> `2.2.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.1/compatibility-slim/2.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.2.1/confidence-slim/2.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.2.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​221-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare220v221-2021-09-13) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.2.0...v2.2.1)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 05fc8864737b..c1cc699e936b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.2.0 + 2.2.1 pom import From 8ef841686dd957cada16951f06bbaa3eed45aab6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 02:32:20 +0000 Subject: [PATCH 0530/1979] chore: release 2.4.3 (#608) :robot: I have created a release \*beep\* \*boop\* --- ### [2.4.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.2...v2.4.3) (2021-09-14) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.1 ([#606](https://www.github.com/googleapis/java-spanner-jdbc/issues/606)) ([8b9996f](https://www.github.com/googleapis/java-spanner-jdbc/commit/8b9996f008c7ea8841ab0bf4d443e413d126c68b)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6cd08c39ccf5..735d2e67d5d7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.4.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.2...v2.4.3) (2021-09-14) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.2.1 ([#606](https://www.github.com/googleapis/java-spanner-jdbc/issues/606)) ([36c1791](https://www.github.com/googleapis/java-spanner-jdbc/commit/36c17916e2891d6c13ea6437a328dae8e16ffc13)) + ### [2.4.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.1...v2.4.2) (2021-09-02) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c1cc699e936b..91b1eb52fc28 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.3-SNAPSHOT + 2.4.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5ce451791d13..217948c10431 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.3-SNAPSHOT + 2.4.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 219f0d8f5e37..d7477ecebb34 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.2:2.4.3-SNAPSHOT +google-cloud-spanner-jdbc:2.4.3:2.4.3 From a0932f31899a472df54a94452d745540b0d3c452 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 02:42:21 +0000 Subject: [PATCH 0531/1979] chore: release 2.4.4-SNAPSHOT (#609) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 91b1eb52fc28..8019c4fe6325 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.3 + 2.4.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 217948c10431..d97369128e68 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.3 + 2.4.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d7477ecebb34..9a3f6f0dcbec 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.3:2.4.3 +google-cloud-spanner-jdbc:2.4.3:2.4.4-SNAPSHOT From 3479ec0fea2b49f57bcebdb9ac9e4e174dba7838 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 14 Sep 2021 04:56:23 +0200 Subject: [PATCH 0532/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.0.2 (#607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.0.1` -> `1.0.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.2/compatibility-slim/1.0.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.2/confidence-slim/1.0.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.0.2`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​102-httpswwwgithubcomgoogleapisjava-shared-configcomparev101v102-2021-09-13) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.0.1...v1.0.2)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8019c4fe6325..4213423ca8e0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.0.1 + 1.0.2 From afc74c8538f34e5233ac2c76d2b049c414e8453e Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 16 Sep 2021 11:44:53 -0700 Subject: [PATCH 0533/1979] changes without context (#605) autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. --- java-spanner-jdbc/.github/workflows/ci.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 3becb5c022a3..12890848c64f 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -26,9 +26,6 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 From 5b11c6a54f665cc760265b2719b49b94bca7f032 Mon Sep 17 00:00:00 2001 From: Yoshi Automation Bot Date: Thu, 16 Sep 2021 15:05:15 -0700 Subject: [PATCH 0534/1979] changes without context (#611) autosynth cannot find the source of changes triggered by earlier changes in this repository, or by version upgrades to tools such as linters. --- java-spanner-jdbc/.github/workflows/ci.yaml | 3 +++ java-spanner-jdbc/synth.metadata | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 12890848c64f..3becb5c022a3 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -26,6 +26,9 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 + - uses: stCarolas/setup-maven@v4 + with: + maven-version: 3.8.1 - uses: actions/setup-java@v1 with: java-version: 8 diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index ea55c524738a..f335115e602b 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/synth.metadata @@ -4,7 +4,7 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "256ba0683a9095d54a8e60595d5fa7e31f9b2b54" + "sha": "ade66635bd24f9d3fb44867d7f883fc59eb5a2db" } }, { From e81de14e41249c1ae5b63e7a8430cdea7b712513 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 22 Sep 2021 17:48:34 +0200 Subject: [PATCH 0535/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.0.3 (#613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.0.2` -> `1.0.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.3/compatibility-slim/1.0.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.0.3/confidence-slim/1.0.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.0.3`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​103-httpswwwgithubcomgoogleapisjava-shared-configcomparev102v103-2021-09-21) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.0.2...v1.0.3)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4213423ca8e0..f4ace8713038 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.0.2 + 1.0.3 From e61249f0f5ae3a5f8b598f2952751aa62d16d22e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 22 Sep 2021 22:21:14 +0200 Subject: [PATCH 0536/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.3.0 (#614) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f4ace8713038..108a553c28a1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.2.1 + 2.3.0 pom import From d5411c8bba79f2e283fc222ef8f156e403b60969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 23 Sep 2021 12:53:09 +0200 Subject: [PATCH 0537/1979] test: remove the category from the base class for all integration tests (#616) Removes the category from the base class for all integration tests so they are not excluded from multiple builds, as the result is that both the category of the base class as well as the concrete class are applied. --- .../java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index 64b6aa6cf803..efc2d8df16ce 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -18,7 +18,6 @@ import com.google.cloud.spanner.Database; import com.google.cloud.spanner.GceTestEnvConfig; -import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; import com.google.cloud.spanner.connection.ConnectionOptions; @@ -38,10 +37,8 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.experimental.categories.Category; /** Base class for all JDBC integration tests. */ -@Category(IntegrationTest.class) public class ITAbstractJdbcTest { protected class ITJdbcConnectionProvider implements com.google.cloud.spanner.connection.AbstractSqlScriptVerifier From e131f163ebd9ffbe8cdbe013ec550455c9a25b13 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Thu, 23 Sep 2021 14:06:52 -0400 Subject: [PATCH 0538/1979] chore: migrate to owlbot (#612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: migrate to owlbot * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 +++ java-spanner-jdbc/.github/.OwlBot.yaml | 16 ++++++++++++++++ java-spanner-jdbc/{synth.py => owlbot.py} | 3 --- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 java-spanner-jdbc/.github/.OwlBot.lock.yaml create mode 100644 java-spanner-jdbc/.github/.OwlBot.yaml rename java-spanner-jdbc/{synth.py => owlbot.py} (95%) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml new file mode 100644 index 000000000000..5607b418e74c --- /dev/null +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -0,0 +1,3 @@ +docker: + image: gcr.io/repo-automation-bots/owlbot-java:latest + digest: sha256:b328758e5113c392d3eccad613c2b18097eaebcb4d8bf77fab0326a6cad90bc7 \ No newline at end of file diff --git a/java-spanner-jdbc/.github/.OwlBot.yaml b/java-spanner-jdbc/.github/.OwlBot.yaml new file mode 100644 index 000000000000..eede3d3f6cc0 --- /dev/null +++ b/java-spanner-jdbc/.github/.OwlBot.yaml @@ -0,0 +1,16 @@ +# Copyright 2021 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. + +docker: + image: "gcr.io/repo-automation-bots/owlbot-java:latest" \ No newline at end of file diff --git a/java-spanner-jdbc/synth.py b/java-spanner-jdbc/owlbot.py similarity index 95% rename from java-spanner-jdbc/synth.py rename to java-spanner-jdbc/owlbot.py index de866777b818..8ea5787cbc99 100644 --- a/java-spanner-jdbc/synth.py +++ b/java-spanner-jdbc/owlbot.py @@ -16,11 +16,8 @@ import synthtool.languages.java as java -AUTOSYNTH_MULTIPLE_COMMITS = True - java.common_templates(excludes=[ 'README.md', - '.github/release-please.yml', '.github/sync-repo-settings.yaml', '.github/blunderbuss.yml', From ef88222af6b24cf2dddf0515559c3a61a664e793 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 21:37:26 +1000 Subject: [PATCH 0539/1979] chore: release 2.4.4 (#615) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 735d2e67d5d7..c44e24c39751 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.4.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.3...v2.4.4) (2021-09-23) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.3.0 ([#614](https://www.github.com/googleapis/java-spanner-jdbc/issues/614)) ([259e395](https://www.github.com/googleapis/java-spanner-jdbc/commit/259e395a2bd1db967a5686b321e752fcab92b500)) + ### [2.4.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.2...v2.4.3) (2021-09-14) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 108a553c28a1..0b385e0c5640 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.4-SNAPSHOT + 2.4.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d97369128e68..bd86a0c1e56a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.4-SNAPSHOT + 2.4.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9a3f6f0dcbec..dff9eb842ec5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.3:2.4.4-SNAPSHOT +google-cloud-spanner-jdbc:2.4.4:2.4.4 From c83680222dfdaed3c314a19fc15461b8790c821e Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 24 Sep 2021 21:37:52 +1000 Subject: [PATCH 0540/1979] chore(java): remove dependencyDashboardLabel config from renovate.json (#1220) (#617) Source-Link: https://github.com/googleapis/synthtool/commit/0752ff727a19a467dffed335d5e59303689cf0d1 Post-Processor: gcr.io/repo-automation-bots/owlbot-java:latest@sha256:52b5557b7155a80e6f1684c2376d5eef0df6d8d5c785551e1ff8cc000603b62a Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/renovate.json | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 5607b418e74c..9fb406b3b6d3 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-java:latest - digest: sha256:b328758e5113c392d3eccad613c2b18097eaebcb4d8bf77fab0326a6cad90bc7 \ No newline at end of file + digest: sha256:52b5557b7155a80e6f1684c2376d5eef0df6d8d5c785551e1ff8cc000603b62a diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index d469dda3018d..5371695645d9 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -70,8 +70,5 @@ } ], "semanticCommits": true, - "dependencyDashboard": true, - "dependencyDashboardLabels": [ - "type: process" - ] + "dependencyDashboard": true } From c691492f2a27fc7f1a9c3ad25cfa8089ad1ef9e4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 28 Sep 2021 21:04:12 +0200 Subject: [PATCH 0541/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.5 (#622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.12.2` -> `6.12.5` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.12.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.12.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.12.5/compatibility-slim/6.12.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.12.5/confidence-slim/6.12.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.12.5`](https://togithub.com/googleapis/java-spanner/blob/master/CHANGELOG.md#​6125-httpswwwgithubcomgoogleapisjava-spannercomparev6124v6125-2021-09-27) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.12.2...v6.12.5)
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0b385e0c5640..29c1231c5b3a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.12.2 + 6.12.5 pom import From e8058acf3faed2644f58b2cad61ed5d16d111807 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 28 Sep 2021 12:11:42 -0700 Subject: [PATCH 0542/1979] chore: release 2.4.5-SNAPSHOT (#618) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: release 2.4.5-SNAPSHOT * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- .../clirr-ignored-differences.xml | 136 ------------------ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 3 insertions(+), 139 deletions(-) delete mode 100644 java-spanner-jdbc/clirr-ignored-differences.xml diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml deleted file mode 100644 index 0962d5e126ec..000000000000 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - boolean removeTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - java.util.Iterator getTransactionRetryListenersFromConnection() - - - 8001 - com/google/cloud/spanner/jdbc/ConnectionOptions$Builder - - - 8001 - com/google/cloud/spanner/jdbc/ConnectionOptions$ConnectionProperty - - - 8001 - com/google/cloud/spanner/jdbc/StatementResult$ClientSideStatementType - - - 8001 - com/google/cloud/spanner/jdbc/StatementResult$ResultType - - - 8001 - com/google/cloud/spanner/jdbc/UnitOfWork$Type - - - 8001 - com/google/cloud/spanner/jdbc/UnitOfWork$UnitOfWorkState - - - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - com.google.cloud.spanner.connection.AutocommitDmlMode getAutocommitDmlMode() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - java.lang.String getOptimizerVersion() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - com.google.cloud.spanner.TimestampBound getReadOnlyStaleness() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - com.google.cloud.spanner.connection.TransactionMode getTransactionMode() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - boolean isInTransaction() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - boolean isTransactionStarted() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setAutocommitDmlMode(com.google.cloud.spanner.connection.AutocommitDmlMode) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setOptimizerVersion(java.lang.String) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setReadOnlyStaleness(com.google.cloud.spanner.TimestampBound) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setTransactionMode(com.google.cloud.spanner.connection.TransactionMode) - - - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - com.google.cloud.spanner.CommitResponse getCommitResponse() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - boolean isReturnCommitStats() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setReturnCommitStats(boolean) - - - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - java.lang.String getTransactionTag() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setTransactionTag(java.lang.String) - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - java.lang.String getStatementTag() - - - 7012 - com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection - void setStatementTag(java.lang.String) - - diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 29c1231c5b3a..45099c4126d1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.4 + 2.4.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index bd86a0c1e56a..82d1061a1091 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.4 + 2.4.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index dff9eb842ec5..546bce02c515 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.4:2.4.4 +google-cloud-spanner-jdbc:2.4.4:2.4.5-SNAPSHOT From ef5515156d3c84f5fcdf0149a6f06fc982181d30 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Tue, 28 Sep 2021 17:04:12 -0400 Subject: [PATCH 0543/1979] build: configure release-please should tag releases (#624) --- java-spanner-jdbc/.github/release-please.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index 127277a02466..cbc451149254 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -1,7 +1,9 @@ releaseType: java-yoshi bumpMinorPreMajor: true +handleGHRelease: true branches: - branch: 1.21.x releaseType: java-yoshi bumpMinorPreMajor: true + handleGHRelease: true From 8868e0b9855d1e287f368367c43cd484f022d396 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Wed, 29 Sep 2021 10:32:13 -0400 Subject: [PATCH 0544/1979] chore: change branch master to main in github configurations (#628) --- java-spanner-jdbc/.github/blunderbuss.yml | 2 +- java-spanner-jdbc/.github/sync-repo-settings.yaml | 8 ++++---- .../workflows/integration-tests-against-emulator.yaml | 2 +- java-spanner-jdbc/README.md | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml index f3e67a049132..ff884f2733ff 100644 --- a/java-spanner-jdbc/.github/blunderbuss.yml +++ b/java-spanner-jdbc/.github/blunderbuss.yml @@ -1,5 +1,5 @@ # Configuration for the Blunderbuss GitHub app. For more info see -# https://github.com/googleapis/repo-automation-bots/tree/master/packages/blunderbuss +# https://github.com/googleapis/repo-automation-bots/tree/main/packages/blunderbuss assign_issues: - thiagotnunes assign_prs_by: diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 8a024006a783..c6354959c2f8 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -11,11 +11,11 @@ squashMergeAllowed: true # Defaults to `false` mergeCommitAllowed: false -# Rules for master branch protection +# Rules for main branch protection branchProtectionRules: # Identifies the protection rule pattern. Name of the branch to be protected. -# Defaults to `master` -- pattern: master +# Defaults to `main` +- pattern: main # Can admins overwrite branch protection. # Defaults to `true` isAdminEnforced: true @@ -39,7 +39,7 @@ branchProtectionRules: - "cla/google" # Identifies the protection rule pattern. Name of the branch to be protected. -# Defaults to `master` +# Defaults to `main` - pattern: 1.21.x # Can admins overwrite branch protection. # Defaults to `true` diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index b9b595434fc8..8ee7c4d5d6b8 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -1,7 +1,7 @@ on: push: branches: - - master + - main pull_request: name: Integration tests against emulator jobs: diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 9a086c957457..e7c6e9e6c945 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -236,10 +236,10 @@ Java is a registered trademark of Oracle and/or its affiliates. [developer-console]: https://console.developers.google.com/ [create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects [cloud-sdk]: https://cloud.google.com/sdk/ -[troubleshooting]: https://github.com/googleapis/google-cloud-common/blob/master/troubleshooting/readme.md#troubleshooting -[contributing]: https://github.com/googleapis/java-spanner-jdbc/blob/master/CONTRIBUTING.md -[code-of-conduct]: https://github.com/googleapis/java-spanner-jdbc/blob/master/CODE_OF_CONDUCT.md#contributor-code-of-conduct -[license]: https://github.com/googleapis/java-spanner-jdbc/blob/master/LICENSE +[troubleshooting]: https://github.com/googleapis/google-cloud-common/blob/main/troubleshooting/readme.md#troubleshooting +[contributing]: https://github.com/googleapis/java-spanner-jdbc/blob/main/CONTRIBUTING.md +[code-of-conduct]: https://github.com/googleapis/java-spanner-jdbc/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct +[license]: https://github.com/googleapis/java-spanner-jdbc/blob/main/LICENSE [libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM From 080e9beb281a6567a47a9bc814b7eb9e2498d779 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:38:33 +0000 Subject: [PATCH 0545/1979] chore: release 2.4.5 (#625) :robot: I have created a release \*beep\* \*boop\* --- ### [2.4.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.4...v2.4.5) (2021-09-29) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.5 ([#622](https://www.github.com/googleapis/java-spanner-jdbc/issues/622)) ([c691492](https://www.github.com/googleapis/java-spanner-jdbc/commit/c691492f2a27fc7f1a9c3ad25cfa8089ad1ef9e4)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c44e24c39751..f6987230b09d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.4.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.4...v2.4.5) (2021-09-29) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.12.5 ([#622](https://www.github.com/googleapis/java-spanner-jdbc/issues/622)) ([b255c54](https://www.github.com/googleapis/java-spanner-jdbc/commit/b255c5434141a900dca30c1e5dbe465b10b88718)) + ### [2.4.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.3...v2.4.4) (2021-09-23) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 45099c4126d1..29ece9c34573 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.5-SNAPSHOT + 2.4.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 82d1061a1091..9690dee55eaa 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.5-SNAPSHOT + 2.4.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 546bce02c515..20257f9e9849 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.4:2.4.5-SNAPSHOT +google-cloud-spanner-jdbc:2.4.5:2.4.5 From 116c9383b5e2c08ca0565dada502d08b5c231215 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 4 Oct 2021 15:36:28 +0200 Subject: [PATCH 0546/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v23.1.0 (#631) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `23.0.0` -> `23.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.1.0/compatibility-slim/23.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/23.1.0/confidence-slim/23.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 9fb986ed4514..d657da5d8b89 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 23.0.0 + 23.1.0 pom import From ac27d4e01b57134f765af3d5ad86d9c9a1fe677a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 6 Oct 2021 03:04:19 +0200 Subject: [PATCH 0547/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.4.5 (#626) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cf34d1d57ab8..aa924fe72bae 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.2 + 2.4.5 From c9e6214915f47d8b9a554fcdfd06117ed8a48f90 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 Oct 2021 16:17:13 +0200 Subject: [PATCH 0548/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.13.0 (#637) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 29ece9c34573..c07adcaa4afe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.12.5 + 6.13.0 pom import From 4067d7ad00e4efd340ebeee92f23003dcaaa30c3 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 8 Oct 2021 12:10:18 -0400 Subject: [PATCH 0549/1979] build: add jdk 17 to java units and dependency builds (#1216) (#630) * chore(java): fix release-please version replace tags for initial samples pom.xml (#1229) Source-Link: https://github.com/googleapis/synthtool/commit/595dbf0d06c7dee6e5825c58e94ff4fb7da1fec9 Post-Processor: gcr.io/repo-automation-bots/owlbot-java:latest@sha256:e56a9ac49143216f08cd6d5f7f8769b456ce35b576ae14dbbf8d9891bbb859c3 * Fix Java 17 test build Co-authored-by: Owl Bot Co-authored-by: Chanseok Oh --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 21 ++++++++++++------- java-spanner-jdbc/.kokoro/dependencies.sh | 23 ++++++++++++++++++++- java-spanner-jdbc/pom.xml | 20 +++++++++++++++++- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 9fb406b3b6d3..227d343e917c 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-java:latest - digest: sha256:52b5557b7155a80e6f1684c2376d5eef0df6d8d5c785551e1ff8cc000603b62a + digest: sha256:e56a9ac49143216f08cd6d5f7f8769b456ce35b576ae14dbbf8d9891bbb859c3 diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 3becb5c022a3..2425d7234f42 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -1,7 +1,7 @@ on: push: branches: - - master + - main pull_request: name: ci jobs: @@ -9,14 +9,15 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11] + java: [8, 11, 17] steps: - uses: actions/checkout@v2 - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: zulu java-version: ${{matrix.java}} - run: java -version - run: .kokoro/build.sh @@ -29,8 +30,9 @@ jobs: - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: zulu java-version: 8 - run: java -version - run: .kokoro/build.bat @@ -40,14 +42,15 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11] + java: [8, 11, 17] steps: - uses: actions/checkout@v2 - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: zulu java-version: ${{matrix.java}} - run: java -version - run: .kokoro/dependencies.sh @@ -58,8 +61,9 @@ jobs: - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: zulu java-version: 8 - run: java -version - run: .kokoro/build.sh @@ -72,8 +76,9 @@ jobs: - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/setup-java@v2 with: + distribution: zulu java-version: 8 - run: java -version - run: .kokoro/build.sh diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 9030ba8f99ff..9a5105d7ebf4 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -28,7 +28,28 @@ source ${scriptDir}/common.sh java -version echo $JOB_TYPE -export MAVEN_OPTS="-Xmx1024m -XX:MaxPermSize=128m" +function determineMavenOpts() { + local javaVersion=$( + # filter down to the version line, then pull out the version between quotes, + # then trim the version number down to its minimal number (removing any + # update or suffix number). + java -version 2>&1 | grep "version" \ + | sed -E 's/^.*"(.*?)".*$/\1/g' \ + | sed -E 's/^(1\.[0-9]\.0).*$/\1/g' + ) + + case $javaVersion in + "17") + # MaxPermSize is no longer supported as of jdk 17 + echo -n "-Xmx1024m" + ;; + *) + echo -n "-Xmx1024m -XX:MaxPermSize=128m" + ;; + esac +} + +export MAVEN_OPTS=$(determineMavenOpts) # this should run maven enforcer retry_with_backoff 3 10 \ diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c07adcaa4afe..b20f2f1b9228 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 1.10.19 + 2.28.2 2.2 @@ -383,6 +383,24 @@
    + + jdk17 + + [17,) + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.io=ALL-UNNAMED + + + + + From d3b84e44dc9671fd754ad311e1264c668207c3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 11 Oct 2021 03:17:04 +0200 Subject: [PATCH 0550/1979] feat: support VIEW in metadata queries (#633) - Report views with table type VIEW in metadata queries. - Allow applications to filter for VIEWs in metadata queries Fixes #632 --- .../jdbc/DatabaseMetaData_GetTables.sql | 16 +++---- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 46 ++++++++++++++----- .../spanner/jdbc/it/CreateMusicTables.sql | 5 ++ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql index b2028df9a1c9..1d4855810851 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql @@ -15,16 +15,16 @@ */ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, - CASE WHEN TABLE_SCHEMA = '' THEN 'TABLE' ELSE 'VIEW' END AS TABLE_TYPE, + CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END AS TABLE_TYPE, NULL AS REMARKS, NULL AS TYPE_CAT, NULL AS TYPE_SCHEM, NULL AS TYPE_NAME, - NULL AS SELF_REFERENCING_COL_NAME, NULL AS REF_GENERATION -FROM INFORMATION_SCHEMA.TABLES AS T + NULL AS SELF_REFERENCING_COL_NAME, NULL AS REF_GENERATION +FROM INFORMATION_SCHEMA.TABLES AS T WHERE UPPER(TABLE_CATALOG) LIKE ? AND UPPER(TABLE_SCHEMA) LIKE ? AND UPPER(TABLE_NAME) LIKE ? AND ( - (CASE WHEN TABLE_SCHEMA = '' THEN 'TABLE' ELSE 'VIEW' END) LIKE ? - OR - (CASE WHEN TABLE_SCHEMA = '' THEN 'TABLE' ELSE 'VIEW' END) LIKE ? - ) -ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME \ No newline at end of file + (CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END) LIKE ? + OR + (CASE WHEN TABLE_TYPE = 'BASE TABLE' THEN 'TABLE' ELSE TABLE_TYPE END) LIKE ? + ) +ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 9c0d9a6e532c..a8a09fab78b9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -21,6 +21,10 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.ParallelIntegrationTest; @@ -801,6 +805,19 @@ public void testGetPrimaryKeys() throws SQLException { } } + @Test + public void testGetViews() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = connection.getMetaData().getTables("", "", null, new String[] {"VIEW"})) { + assertTrue(rs.next()); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals("SingersView", rs.getString("TABLE_NAME")); + assertFalse(rs.next()); + } + } + } + @Test public void testGetSchemas() throws SQLException { try (Connection connection = createConnection()) { @@ -820,9 +837,15 @@ public void testGetSchemas() throws SQLException { private static final class Table { private final String name; + private final String type; private Table(String name) { + this(name, "TABLE"); + } + + private Table(String name, String type) { this.name = name; + this.type = type; } } @@ -831,6 +854,7 @@ private Table(String name) { new Table("Albums"), new Table("Concerts"), new Table("Singers"), + new Table("SingersView", "VIEW"), new Table("Songs"), new Table("TableWithAllColumnTypes"), new Table("TableWithRef")); @@ -841,17 +865,17 @@ public void testGetTables() throws SQLException { try (ResultSet rs = connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { for (Table table : EXPECTED_TABLES) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(table.name))); - assertThat(rs.getString("TABLE_TYPE"), is(equalTo("TABLE"))); - assertThat(rs.getString("REMARKS"), is(nullValue())); - assertThat(rs.getString("TYPE_CAT"), is(nullValue())); - assertThat(rs.getString("TYPE_SCHEM"), is(nullValue())); - assertThat(rs.getString("TYPE_NAME"), is(nullValue())); - assertThat(rs.getString("SELF_REFERENCING_COL_NAME"), is(nullValue())); - assertThat(rs.getString("REF_GENERATION"), is(nullValue())); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(table.name, rs.getString("TABLE_NAME")); + assertEquals(table.type, rs.getString("TABLE_TYPE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("TYPE_CAT")); + assertNull(rs.getString("TYPE_SCHEM")); + assertNull(rs.getString("TYPE_NAME")); + assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); + assertNull(rs.getString("REF_GENERATION")); } assertThat(rs.next(), is(false)); } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 9b2cb3bad0f3..24579b27208c 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -26,6 +26,11 @@ CREATE TABLE Singers ( CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); +CREATE VIEW SingersView SQL SECURITY INVOKER AS +SELECT s.SingerId AS SingerId, s.FirstName AS FirstName, s.LastName AS LastName +FROM Singers s +ORDER BY s.LastName, s.FirstName; + CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, From 9c6e96005cc7bd01b903a4e0dcfb143205e45b9c Mon Sep 17 00:00:00 2001 From: Emily Ball Date: Sun, 10 Oct 2021 18:43:51 -0700 Subject: [PATCH 0551/1979] chore: update repo-metadata.json client_documentation link (#636) * chore: updating doc link * chore: fix missing comma --- java-spanner-jdbc/.repo-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index e787150b31a9..c8768f786ab5 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -2,7 +2,7 @@ "name": "spanner-jdbc", "name_pretty": "Google Cloud Spanner JDBC", "product_documentation": "https://cloud.google.com/spanner/docs/use-oss-jdbc", - "client_documentation": "https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html", + "client_documentation": "https://cloud.google.com/java/docs/reference/google-cloud-spanner-jdbc/latest/history", "release_level": "ga", "language": "java", "min_java_version": 8, From 826b363209f6424446bc2bbcbf7e20212a628c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 13 Oct 2021 10:01:18 +0200 Subject: [PATCH 0552/1979] deps: upgrade Mockito to support Java17 (#635) * deps: upgrade Mockito to support Java17 Update Mockito to a version that supports the Java module system. This should enable Java17 support. Also cleans up one of the test files that failed for Java17. Fixes the build error in #621 * test: do not restart mock server before each test --- java-spanner-jdbc/pom.xml | 20 +- .../jdbc/AbstractJdbcResultSetTest.java | 1004 ++++------------- .../spanner/jdbc/JdbcConnectionTest.java | 2 +- .../jdbc/JdbcPreparedStatementTest.java | 4 +- .../spanner/jdbc/JdbcQueryOptionsTest.java | 12 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 4 +- 6 files changed, 229 insertions(+), 817 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b20f2f1b9228..885612d0c414 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 2.28.2 + 3.12.4 2.2 @@ -383,24 +383,6 @@ - - jdk17 - - [17,) - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - --add-opens java.base/java.io=ALL-UNNAMED - - - - - diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java index 2be79bf20cbb..53fd0e6d2b0c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java @@ -16,10 +16,10 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; +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.mockito.Mockito.mock; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; @@ -63,33 +63,33 @@ public void setup() { @Test public void testFetchSize() throws SQLException { - assertThat(rs.getFetchSize(), is(equalTo(0))); + assertEquals(0, rs.getFetchSize()); for (int size : new int[] {0, 1, 10, 100}) { rs.setFetchSize(size); - assertThat(rs.getFetchSize(), is(equalTo(size))); + assertEquals(size, rs.getFetchSize()); } } @Test public void testGetType() throws SQLException { - assertThat(rs.getType(), is(equalTo(ResultSet.TYPE_FORWARD_ONLY))); + assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType()); } @Test public void testGetConcurrency() throws SQLException { - assertThat(rs.getConcurrency(), is(equalTo(ResultSet.CONCUR_READ_ONLY))); + assertEquals(ResultSet.CONCUR_READ_ONLY, rs.getConcurrency()); } @Test public void testRowInsertedUpdatedDeleted() throws SQLException { - assertThat(rs.rowInserted(), is(false)); - assertThat(rs.rowUpdated(), is(false)); - assertThat(rs.rowDeleted(), is(false)); + assertFalse(rs.rowInserted()); + assertFalse(rs.rowUpdated()); + assertFalse(rs.rowDeleted()); } @Test public void testGetFetchDirection() throws SQLException { - assertThat(rs.getFetchDirection(), is(equalTo(ResultSet.FETCH_FORWARD))); + assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection()); } @Test @@ -99,786 +99,216 @@ public void testSetFetchDirection() throws SQLException { new int[] {ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, ResultSet.FETCH_UNKNOWN}) { try { rs.setFetchDirection(direction); - assertThat(supported.contains(direction), is(true)); + assertTrue(supported.contains(direction)); } catch (JdbcSqlExceptionImpl e) { - assertThat(supported.contains(direction), is(false)); - assertThat(e.getCode(), is(equalTo(Code.INVALID_ARGUMENT))); + assertFalse(supported.contains(direction)); + assertEquals(Code.INVALID_ARGUMENT, e.getCode()); } } } - private static interface SqlRunnable { - void run() throws SQLException; - } - @Test - public void testUnsupportedFeatures() throws SQLException { - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getCursorName(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.isLast(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.beforeFirst(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.afterLast(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.first(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.last(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.absolute(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.relative(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.previous(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNull(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNull("test"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBoolean(1, Boolean.TRUE); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBoolean("test", Boolean.TRUE); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateByte(1, (byte) 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateByte("test", (byte) 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateShort(1, (short) 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateShort("test", (short) 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateInt(1, 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateInt("test", 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateLong(1, 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateLong("test", 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateFloat(1, 1F); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateFloat("test", 1F); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateDouble(1, 1D); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateDouble("test", 1D); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBigDecimal(1, BigDecimal.ONE); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBigDecimal("test", BigDecimal.ONE); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateString(1, "value"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateString("test", "value"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBytes(1, "value".getBytes()); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBytes("test", "value".getBytes()); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateDate(1, new Date(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateDate("test", new Date(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateTimestamp(1, new Timestamp(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateTimestamp("test", new Timestamp(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateTime(1, new Time(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateTime("test", new Time(System.currentTimeMillis())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes())); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream(1, new StringReader("value")); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream("test", new StringReader("value")); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream(1, new StringReader("value"), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream("test", new StringReader("value"), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream(1, new StringReader("value"), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateCharacterStream("test", new StringReader("value"), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject(1, new Object()); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject(1, new Object(), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject(1, new Object(), mock(SQLType.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject(1, new Object(), mock(SQLType.class), 0); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject("test", new Object()); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject("test", new Object(), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject("test", new Object(), mock(SQLType.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateObject("test", new Object(), mock(SQLType.class), 1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.insertRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.deleteRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.refreshRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.cancelRowUpdates(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.moveToInsertRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.moveToCurrentRow(); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getRef(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getRef("test"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateRef(1, mock(Ref.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateRef("test", mock(Ref.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob(1, mock(Blob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob("test", mock(Blob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob(1, mock(InputStream.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob("test", mock(InputStream.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob(1, mock(InputStream.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateBlob("test", mock(InputStream.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob(1, mock(Clob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob("test", mock(Clob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob(1, mock(Reader.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob("test", mock(Reader.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob(1, mock(Reader.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateClob("test", mock(Reader.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateArray(1, mock(Array.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateArray("test", mock(Array.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getRowId(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getRowId("test"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateRowId(1, mock(RowId.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateRowId("test", mock(RowId.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNString(1, "value"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNString("test", "value"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob(1, mock(NClob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob("test", mock(NClob.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob(1, mock(Reader.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob("test", mock(Reader.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob(1, mock(Reader.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNClob("test", mock(Reader.class), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getSQLXML(1); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.getSQLXML("test"); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateSQLXML(1, mock(SQLXML.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateSQLXML("test", mock(SQLXML.class)); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNCharacterStream(1, new StringReader("value")); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNCharacterStream("test", new StringReader("value")); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNCharacterStream(1, new StringReader("value"), 1L); - } - }); - assertUnsupported( - new SqlRunnable() { - @Override - public void run() throws SQLException { - rs.updateNCharacterStream("test", new StringReader("value"), 1L); - } - }); - } - - private void assertUnsupported(SqlRunnable runnable) throws SQLException { - try { - runnable.run(); - fail("missing expected SQLFeatureNotSupportedException"); - } catch (SQLFeatureNotSupportedException e) { - // ignore, this is the expected exception. - } catch (Exception e) { - throw JdbcSqlExceptionFactory.of("unexpected exception", Code.INTERNAL, e); - } + public void testUnsupportedFeatures() { + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getCursorName()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.isLast()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.beforeFirst()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.afterLast()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.first()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.last()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.absolute(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.relative(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.previous()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateNull(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateNull("test")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateBoolean(1, Boolean.TRUE)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBoolean("test", Boolean.TRUE)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateByte(1, (byte) 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateByte("test", (byte) 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateShort(1, (short) 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateShort("test", (short) 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateInt(1, 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateInt("test", 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateLong(1, 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateLong("test", 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateFloat(1, 1F)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateFloat("test", 1F)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateDouble(1, 1D)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateDouble("test", 1D)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBigDecimal(1, BigDecimal.ONE)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBigDecimal("test", BigDecimal.ONE)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateString(1, "value")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateString("test", "value")); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBytes(1, "value".getBytes())); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBytes("test", "value".getBytes())); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateDate(1, new Date(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateDate("test", new Date(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateTimestamp(1, new Timestamp(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateTimestamp("test", new Timestamp(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateTime(1, new Time(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateTime("test", new Time(System.currentTimeMillis()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream(1, new ByteArrayInputStream("value".getBytes()), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateAsciiStream("test", new ByteArrayInputStream("value".getBytes()), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream(1, new ByteArrayInputStream("value".getBytes()), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBinaryStream("test", new ByteArrayInputStream("value".getBytes()), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream(1, new StringReader("value"))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream("test", new StringReader("value"))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream(1, new StringReader("value"), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream("test", new StringReader("value"), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream(1, new StringReader("value"), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateCharacterStream("test", new StringReader("value"), 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateObject(1, new Object())); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateObject(1, new Object(), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateObject(1, new Object(), mock(SQLType.class))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateObject(1, new Object(), mock(SQLType.class), 0)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateObject("test", new Object())); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateObject("test", new Object(), 1)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateObject("test", new Object(), mock(SQLType.class))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateObject("test", new Object(), mock(SQLType.class), 1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.insertRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.deleteRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.refreshRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.cancelRowUpdates()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.moveToInsertRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.moveToCurrentRow()); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getRef(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getRef("test")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateRef(1, mock(Ref.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateRef("test", mock(Ref.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateBlob(1, mock(Blob.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBlob("test", mock(Blob.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBlob(1, mock(InputStream.class))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBlob("test", mock(InputStream.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateBlob(1, mock(InputStream.class), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateBlob("test", mock(InputStream.class), 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateClob(1, mock(Clob.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateClob("test", mock(Clob.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateClob(1, mock(Reader.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateClob("test", mock(Reader.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateClob(1, mock(Reader.class), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateClob("test", mock(Reader.class), 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateArray(1, mock(Array.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateArray("test", mock(Array.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getRowId(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getRowId("test")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateRowId(1, mock(RowId.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateRowId("test", mock(RowId.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateNString(1, "value")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateNString("test", "value")); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.updateNClob(1, mock(NClob.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateNClob("test", mock(NClob.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateNClob(1, mock(Reader.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateNClob("test", mock(Reader.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateNClob(1, mock(Reader.class), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateNClob("test", mock(Reader.class), 1L)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getSQLXML(1)); + assertThrows(SQLFeatureNotSupportedException.class, () -> rs.getSQLXML("test")); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateSQLXML(1, mock(SQLXML.class))); + assertThrows( + SQLFeatureNotSupportedException.class, () -> rs.updateSQLXML("test", mock(SQLXML.class))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateNCharacterStream(1, new StringReader("value"))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateNCharacterStream("test", new StringReader("value"))); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateNCharacterStream(1, new StringReader("value"), 1L)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> rs.updateNCharacterStream("test", new StringReader("value"), 1L)); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index cd0f944989fc..ab503d21f8c8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -22,7 +22,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 40ad1ad011cf..8bb6ef4cbeba 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index d1aeeb92d4ee..f1aaeeaca3fc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -23,22 +23,18 @@ import com.google.cloud.spanner.SpannerOptions.SpannerEnvironment; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.base.MoreObjects; import com.google.spanner.v1.ExecuteSqlRequest; import java.sql.DriverManager; import java.sql.SQLException; -import org.junit.Before; +import javax.annotation.Nonnull; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class JdbcQueryOptionsTest extends AbstractMockServerTest { - @Before - public void setup() throws Exception { - stopServer(); - startStaticServer(); - } @Test public void testDefaultOptions() throws SQLException { @@ -202,14 +198,18 @@ public void testUseOptionsFromConnectionUrl() throws SQLException { @Test public void testUseOptionsFromEnvironment() throws SQLException { + // Make sure that all existing connections are closed, so these do not affect this test. + ConnectionOptions.closeSpanner(); try { SpannerOptions.useEnvironment( new SpannerEnvironment() { + @Nonnull @Override public String getOptimizerVersion() { return "20"; } + @Nonnull @Override public String getOptimizerStatisticsPackage() { return "env_package"; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index ee21dda54f15..e5efb773dd19 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; +import static org.mockito.Mockito.anyList; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -42,7 +43,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.Matchers; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -99,7 +99,7 @@ private JdbcStatement createStatement() { SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, "not an update")); - when(spanner.executeBatchUpdate(Matchers.anyListOf(com.google.cloud.spanner.Statement.class))) + when(spanner.executeBatchUpdate(anyList())) .thenAnswer( new Answer() { @SuppressWarnings("unchecked") From 547fe938fc9d1bdfa7556d86bef8f3344b3209e0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 13 Oct 2021 17:30:27 +0200 Subject: [PATCH 0553/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.1.0 (#639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.0.3` -> `1.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.1.0/compatibility-slim/1.0.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.1.0/confidence-slim/1.0.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.1.0`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​110-httpswwwgithubcomgoogleapisjava-shared-configcomparev103v110-2021-10-12) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.0.3...v1.1.0) ##### Features - introduce Maven configuration for GraalVM testing ([#​314](https://www.togithub.com/googleapis/java-shared-config/issues/314)) ([28fbeb8](https://www.github.com/googleapis/java-shared-config/commit/28fbeb86c4466a58a05d6933584564dbf3352e79)) ##### Bug Fixes - update doclet version ([#​332](https://www.togithub.com/googleapis/java-shared-config/issues/332)) ([3fd0350](https://www.github.com/googleapis/java-shared-config/commit/3fd035030e4f0954dd1f62f7b8ea62583685880c)) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v9.0.1 ([#​327](https://www.togithub.com/googleapis/java-shared-config/issues/327)) ([b6c9b65](https://www.github.com/googleapis/java-shared-config/commit/b6c9b657550db2dee6b36edbb9a6084baee125e2)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.6 ([#​330](https://www.togithub.com/googleapis/java-shared-config/issues/330)) ([271ed7d](https://www.github.com/googleapis/java-shared-config/commit/271ed7dba35623e22fc8a7f7d477e6043e772014)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.6 ([#​331](https://www.togithub.com/googleapis/java-shared-config/issues/331)) ([4f9ba15](https://www.github.com/googleapis/java-shared-config/commit/4f9ba1551df0a2d4fc8c9acca8a951afbe8cb78a)) - update dependency org.junit.vintage:junit-vintage-engine to v5.8.1 ([#​329](https://www.togithub.com/googleapis/java-shared-config/issues/329)) ([4a8789e](https://www.github.com/googleapis/java-shared-config/commit/4a8789ee814ba8a3480beecc76c16fd1cb4e5f12)) ##### [1.0.3](https://www.github.com/googleapis/java-shared-config/compare/v1.0.2...v1.0.3) (2021-09-21) ##### Bug Fixes - update java-docfx-doclet version ([#​315](https://www.togithub.com/googleapis/java-shared-config/issues/315)) ([07af07c](https://www.github.com/googleapis/java-shared-config/commit/07af07c188447ea5728ecd2700121ff477d1c58a)) ##### [1.0.2](https://www.github.com/googleapis/java-shared-config/compare/v1.0.1...v1.0.2) (2021-09-13) ##### Bug Fixes - specify animal-sniffer-maven-plugin version ([#​308](https://www.togithub.com/googleapis/java-shared-config/issues/308)) ([378bf43](https://www.github.com/googleapis/java-shared-config/commit/378bf431383306c1cdd0a4f922956c87edf321b5)) - update java docfx doclet version ([#​312](https://www.togithub.com/googleapis/java-shared-config/issues/312)) ([dd7f6e0](https://www.github.com/googleapis/java-shared-config/commit/dd7f6e0c1a7cc73831b74b4475457611a8c097d3)) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v9 ([#​303](https://www.togithub.com/googleapis/java-shared-config/issues/303)) ([71faea3](https://www.github.com/googleapis/java-shared-config/commit/71faea38d4132407598550e2bb4c77f9d4a4d83d)) ##### [1.0.1](https://www.github.com/googleapis/java-shared-config/compare/v1.0.0...v1.0.1) (2021-08-18) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v8.45.1 ([#​292](https://www.togithub.com/googleapis/java-shared-config/issues/292)) ([66bf6e6](https://www.github.com/googleapis/java-shared-config/commit/66bf6e6fb95997b9eb4b34268b8d20c2fbe9ed5a))
    --- ### Configuration 📅 **Schedule**: 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 [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 885612d0c414..c4c1d70fc270 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.0.3 + 1.1.0 From 9e9ddeecb6a758030af76c8a488a3ca9f7e12984 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 16:54:13 +0000 Subject: [PATCH 0554/1979] build(java): Introduce Native Image testing build script changes (#640) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/build.sh | 5 +++ .../.kokoro/presubmit/graalvm-native.cfg | 33 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 227d343e917c..a600ac2299e1 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-java:latest - digest: sha256:e56a9ac49143216f08cd6d5f7f8769b456ce35b576ae14dbbf8d9891bbb859c3 + digest: sha256:d4b2141d65566523dfd523f63c6e6899ab1281463bce182a9f600e74b0511875 diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index a4c46cfcaafb..ecb23d27ea13 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -69,6 +69,11 @@ integration) verify RETURN_CODE=$? ;; +graalvm) + # Run Unit and Integration Tests with Native Image + mvn test -Pnative -Penable-integration-tests + RETURN_CODE=$? + ;; samples) SAMPLES_DIR=samples # only run ITs in snapshot/ on presubmit PRs. run ITs in all 3 samples/ subdirectories otherwise. diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg new file mode 100644 index 000000000000..4c7225ec924e --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -0,0 +1,33 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm" +} + +env_vars: { + key: "JOB_TYPE" + value: "graalvm" +} + +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-it-service-account" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" +} From 3b164aa0e9e012404f36b4ce523af37fd5c9a0b9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 19 Oct 2021 17:30:37 +0200 Subject: [PATCH 0555/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.4.0 (#641) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.3.0` -> `2.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.4.0/compatibility-slim/2.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.4.0/confidence-slim/2.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.4.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​240-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare230v240-2021-10-18) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.3.0...v2.4.0) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.13.0 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.api-client:google-api-client-bom to v1.32.2 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.api:api-common to v2.0.5 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.auth:google-auth-library-bom to v1.2.1 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.guava:guava-bom to v31 ([#​498](https://www.togithub.com/googleapis/java-shared-dependencies/issues/498)) ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.http-client:google-http-client-bom to v1.40.1 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update dependency com.google.protobuf:protobuf-bom to v3.18.1 ([#​494](https://www.togithub.com/googleapis/java-shared-dependencies/issues/494)) ([a30e376](https://www.github.com/googleapis/java-shared-dependencies/commit/a30e3762b5fb0e2d31304d211c12eb2c1320f0c1)) - update dependency io.grpc:grpc-bom to v1.41.0 ([#​482](https://www.togithub.com/googleapis/java-shared-dependencies/issues/482)) ([8a7d227](https://www.github.com/googleapis/java-shared-dependencies/commit/8a7d227f2a1dab9ff23d247a4e6131c817804c36)) - update gax.version to v2.6.1 ([dba11b5](https://www.github.com/googleapis/java-shared-dependencies/commit/dba11b5fe14d39cdd62357e7bb1b82831c481150)) - update iam.version to v1.1.6 ([#​485](https://www.togithub.com/googleapis/java-shared-dependencies/issues/485)) ([cef7e09](https://www.github.com/googleapis/java-shared-dependencies/commit/cef7e090bbc2e3ae775fa83505f98df286ba7d42))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c4c1d70fc270..49d8f35dc2d7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.3.0 + 2.4.0 pom import From 456984587d83cff4cfb2f572355639df3cd0137d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 20 Oct 2021 18:29:39 -0400 Subject: [PATCH 0556/1979] chore: release 2.4.6-SNAPSHOT (#629) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 49d8f35dc2d7..bb0e4a366e26 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.5 + 2.4.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9690dee55eaa..c73cd1bf0f06 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.5 + 2.4.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 20257f9e9849..6c8a416d3f3b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.5:2.4.5 +google-cloud-spanner-jdbc:2.4.5:2.4.6-SNAPSHOT From 08413814c441844fa82a45f30eda169a17abdb89 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:18:11 +0000 Subject: [PATCH 0557/1979] fix(java): java 17 dependency arguments (#1266) (#645) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/dependencies.sh | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index a600ac2299e1..ee664785f083 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-java:latest - digest: sha256:d4b2141d65566523dfd523f63c6e6899ab1281463bce182a9f600e74b0511875 + digest: sha256:a3ac08d167454718ff057b97a1950d3cb5e16fc39fb3f355d90276285a6cac75 diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index 9a5105d7ebf4..d7476cfe9727 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -38,15 +38,13 @@ function determineMavenOpts() { | sed -E 's/^(1\.[0-9]\.0).*$/\1/g' ) - case $javaVersion in - "17") + if [[ $javaVersion == 17* ]] + then # MaxPermSize is no longer supported as of jdk 17 echo -n "-Xmx1024m" - ;; - *) + else echo -n "-Xmx1024m -XX:MaxPermSize=128m" - ;; - esac + fi } export MAVEN_OPTS=$(determineMavenOpts) From 480077121a3dfda84758527f18ff1b4d1afede85 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Mon, 25 Oct 2021 15:14:44 -0400 Subject: [PATCH 0558/1979] chore: update owlbot project (#646) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/.OwlBot.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index ee664785f083..0df65ebe91a6 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: - image: gcr.io/repo-automation-bots/owlbot-java:latest + image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest digest: sha256:a3ac08d167454718ff057b97a1950d3cb5e16fc39fb3f355d90276285a6cac75 diff --git a/java-spanner-jdbc/.github/.OwlBot.yaml b/java-spanner-jdbc/.github/.OwlBot.yaml index eede3d3f6cc0..54aca963f72c 100644 --- a/java-spanner-jdbc/.github/.OwlBot.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: - image: "gcr.io/repo-automation-bots/owlbot-java:latest" \ No newline at end of file + image: "gcr.io/cloud-devrel-public-resources/owlbot-java:latest" \ No newline at end of file From 83a6171f9e72a8506b43e038b7c0dd99a762e508 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 25 Oct 2021 21:20:39 +0200 Subject: [PATCH 0559/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.0 (#644) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bb0e4a366e26..58dcdd554798 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.1.0 + 1.2.0 From 66a2a4d4ce6a8f874f5e9a57c86d6aaba8ea4e7c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 25 Oct 2021 22:21:39 +0200 Subject: [PATCH 0560/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.14.0 (#647) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 58dcdd554798..e1287b2811d3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.13.0 + 6.14.0 pom import From ed2a888fbc86e26c8462b3244e4a36904e57db33 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 25 Oct 2021 20:28:22 +0000 Subject: [PATCH 0561/1979] chore: release 2.5.0 (#643) :robot: I have created a release \*beep\* \*boop\* --- ## [2.5.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.5...v2.5.0) (2021-10-25) ### Features * support VIEW in metadata queries ([#633](https://www.github.com/googleapis/java-spanner-jdbc/issues/633)) ([d3b84e4](https://www.github.com/googleapis/java-spanner-jdbc/commit/d3b84e44dc9671fd754ad311e1264c668207c3f4)), closes [#632](https://www.github.com/googleapis/java-spanner-jdbc/issues/632) ### Bug Fixes * **java:** java 17 dependency arguments ([#1266](https://www.github.com/googleapis/java-spanner-jdbc/issues/1266)) ([#645](https://www.github.com/googleapis/java-spanner-jdbc/issues/645)) ([0841381](https://www.github.com/googleapis/java-spanner-jdbc/commit/08413814c441844fa82a45f30eda169a17abdb89)) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.4.0 ([#641](https://www.github.com/googleapis/java-spanner-jdbc/issues/641)) ([3b164aa](https://www.github.com/googleapis/java-spanner-jdbc/commit/3b164aa0e9e012404f36b4ce523af37fd5c9a0b9)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.13.0 ([#637](https://www.github.com/googleapis/java-spanner-jdbc/issues/637)) ([c9e6214](https://www.github.com/googleapis/java-spanner-jdbc/commit/c9e6214915f47d8b9a554fcdfd06117ed8a48f90)) * update dependency com.google.cloud:google-cloud-spanner-bom to v6.14.0 ([#647](https://www.github.com/googleapis/java-spanner-jdbc/issues/647)) ([66a2a4d](https://www.github.com/googleapis/java-spanner-jdbc/commit/66a2a4d4ce6a8f874f5e9a57c86d6aaba8ea4e7c)) * upgrade Mockito to support Java17 ([#635](https://www.github.com/googleapis/java-spanner-jdbc/issues/635)) ([826b363](https://www.github.com/googleapis/java-spanner-jdbc/commit/826b363209f6424446bc2bbcbf7e20212a628c60)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index f6987230b09d..ac81fe9369a4 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.5.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.5...v2.5.0) (2021-10-25) + + +### Features + +* support VIEW in metadata queries ([#633](https://www.github.com/googleapis/java-spanner-jdbc/issues/633)) ([b929191](https://www.github.com/googleapis/java-spanner-jdbc/commit/b929191a7b6699f9daf9a7c06097e9794c79ff8d)), closes [#632](https://www.github.com/googleapis/java-spanner-jdbc/issues/632) + + +### Bug Fixes + +* **java:** java 17 dependency arguments ([#1266](https://www.github.com/googleapis/java-spanner-jdbc/issues/1266)) ([#645](https://www.github.com/googleapis/java-spanner-jdbc/issues/645)) ([0474502](https://www.github.com/googleapis/java-spanner-jdbc/commit/0474502936ff1a43244fcb830fecfc5f42895899)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.4.0 ([#641](https://www.github.com/googleapis/java-spanner-jdbc/issues/641)) ([ab26010](https://www.github.com/googleapis/java-spanner-jdbc/commit/ab26010ba107d4ba9591d661743ad542ae3b227f)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.13.0 ([#637](https://www.github.com/googleapis/java-spanner-jdbc/issues/637)) ([d981c8c](https://www.github.com/googleapis/java-spanner-jdbc/commit/d981c8c744829aa039b16df0b150caf49a99f1cc)) +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.14.0 ([#647](https://www.github.com/googleapis/java-spanner-jdbc/issues/647)) ([3cda837](https://www.github.com/googleapis/java-spanner-jdbc/commit/3cda83737c25c8878d19bee1727de84e086065b6)) +* upgrade Mockito to support Java17 ([#635](https://www.github.com/googleapis/java-spanner-jdbc/issues/635)) ([d78792f](https://www.github.com/googleapis/java-spanner-jdbc/commit/d78792f7acdd2fdac8a655fba06789ba50457679)) + ### [2.4.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.4...v2.4.5) (2021-09-29) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e1287b2811d3..4177d62604de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.4.6-SNAPSHOT + 2.5.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c73cd1bf0f06..d120e336b378 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.6-SNAPSHOT + 2.5.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6c8a416d3f3b..d3bb0babb2c6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.4.5:2.4.6-SNAPSHOT +google-cloud-spanner-jdbc:2.5.0:2.5.0 From e60ab1ca46df754617255e8f9a44e34a27b37546 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 25 Oct 2021 20:34:24 +0000 Subject: [PATCH 0562/1979] chore: release 2.5.1-SNAPSHOT (#648) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4177d62604de..86f163d1c1b8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.0 + 2.5.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d120e336b378..a0955677e8e7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.0 + 2.5.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d3bb0babb2c6..b7e8c700d88a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.0:2.5.0 +google-cloud-spanner-jdbc:2.5.0:2.5.1-SNAPSHOT From 63f12cc0aec69f0e152b3d4e0ebf1d34ee8a8b03 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 26 Oct 2021 19:11:15 +0200 Subject: [PATCH 0563/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.0 (#649) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index aa924fe72bae..9093208b1aef 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.4.5 + 2.5.0 From d9b6a1bb5537e1cc8e788a1da9039b6bdda1c45d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 27 Oct 2021 18:18:42 +0200 Subject: [PATCH 0564/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24 (#651) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `23.1.0` -> `24.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.0.0/compatibility-slim/23.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.0.0/confidence-slim/23.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d657da5d8b89..de2b4cbd4dba 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 23.1.0 + 24.0.0 pom import From 872d846ef29f3b9b8c90de41f990fc7a46d1d610 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 27 Oct 2021 18:22:37 +0200 Subject: [PATCH 0565/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.1 (#652) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 86f163d1c1b8..2e90ac894c42 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.14.0 + 6.15.1 pom import From c9b307829e11c25c84179e585cfcf839b846492e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 27 Oct 2021 16:48:33 +0000 Subject: [PATCH 0566/1979] chore: release 2.5.1 (#653) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.0...v2.5.1) (2021-10-27) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.1 ([#652](https://www.github.com/googleapis/java-spanner-jdbc/issues/652)) ([872d846](https://www.github.com/googleapis/java-spanner-jdbc/commit/872d846ef29f3b9b8c90de41f990fc7a46d1d610)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ac81fe9369a4..83b7e7d84cb2 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.0...v2.5.1) (2021-10-27) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.1 ([#652](https://www.github.com/googleapis/java-spanner-jdbc/issues/652)) ([37d42d9](https://www.github.com/googleapis/java-spanner-jdbc/commit/37d42d91e49da9d30ca0d06b6a01bbe918fc3ab6)) + ## [2.5.0](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.4.5...v2.5.0) (2021-10-25) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2e90ac894c42..d9b697624604 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.1-SNAPSHOT + 2.5.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a0955677e8e7..3771fd68aec6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.1-SNAPSHOT + 2.5.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b7e8c700d88a..27d308fe0f8a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.0:2.5.1-SNAPSHOT +google-cloud-spanner-jdbc:2.5.1:2.5.1 From 592eb92cd5fa897025eab0f11aeb060a1aae510f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 27 Oct 2021 17:02:36 +0000 Subject: [PATCH 0567/1979] chore: release 2.5.2-SNAPSHOT (#654) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d9b697624604..899673f1fc23 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.1 + 2.5.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3771fd68aec6..6dd2b30336d4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.1 + 2.5.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 27d308fe0f8a..00a2205689b0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.1:2.5.1 +google-cloud-spanner-jdbc:2.5.1:2.5.2-SNAPSHOT From c998f5cc758a103639e71c451ffbfc63436e821a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 1 Nov 2021 03:30:23 +0100 Subject: [PATCH 0568/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.1 (#655) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9093208b1aef..46322c634422 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.0 + 2.5.1 From be2a6f2dcb79b59755332a37f4499e6da042ea3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 1 Nov 2021 08:36:12 +0100 Subject: [PATCH 0569/1979] cleanup: remove warnings (#574) Remove as many warnings as possible. --- .../spanner/jdbc/AbstractJdbcConnection.java | 5 +- .../spanner/jdbc/AbstractJdbcResultSet.java | 20 +- .../spanner/jdbc/AbstractJdbcStatement.java | 19 +- .../spanner/jdbc/AbstractJdbcWrapper.java | 8 +- .../jdbc/CloudSpannerJdbcConnection.java | 34 +- .../google/cloud/spanner/jdbc/JdbcArray.java | 14 +- .../google/cloud/spanner/jdbc/JdbcBlob.java | 10 +- .../google/cloud/spanner/jdbc/JdbcClob.java | 28 +- .../cloud/spanner/jdbc/JdbcConnection.java | 17 +- .../cloud/spanner/jdbc/JdbcConstants.java | 5 +- .../cloud/spanner/jdbc/JdbcDataSource.java | 12 +- .../cloud/spanner/jdbc/JdbcDataType.java | 6 +- .../spanner/jdbc/JdbcDatabaseMetaData.java | 396 +++++++++--------- .../google/cloud/spanner/jdbc/JdbcDriver.java | 4 +- .../spanner/jdbc/JdbcParameterMetaData.java | 59 ++- .../spanner/jdbc/JdbcParameterStore.java | 37 +- .../cloud/spanner/jdbc/JdbcPreconditions.java | 4 +- .../spanner/jdbc/JdbcPreparedStatement.java | 5 +- .../cloud/spanner/jdbc/JdbcResultSet.java | 19 +- .../spanner/jdbc/JdbcResultSetMetaData.java | 50 +-- .../spanner/jdbc/JdbcSqlExceptionFactory.java | 3 +- .../cloud/spanner/jdbc/JdbcStatement.java | 7 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 70 ++-- .../jdbc/TransactionRetryListener.java | 8 +- .../jdbc/AbstractJdbcResultSetTest.java | 10 +- .../spanner/jdbc/AbstractJdbcWrapperTest.java | 62 ++- .../jdbc/JdbcAbortedTransactionTest.java | 13 +- .../cloud/spanner/jdbc/JdbcArrayTest.java | 6 +- .../cloud/spanner/jdbc/JdbcClobTest.java | 11 +- .../JdbcConnectionGeneratedSqlScriptTest.java | 3 +- .../spanner/jdbc/JdbcConnectionTest.java | 16 +- .../spanner/jdbc/JdbcConnectionUrlTest.java | 40 +- .../jdbc/JdbcDatabaseMetaDataTest.java | 7 +- ...cDatabaseMetaDataWithMockedServerTest.java | 12 +- .../cloud/spanner/jdbc/JdbcDriverTest.java | 34 +- .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 9 +- .../spanner/jdbc/JdbcParameterStoreTest.java | 37 +- .../jdbc/JdbcPreparedStatementTest.java | 40 +- ...PreparedStatementWithMockedServerTest.java | 3 +- .../jdbc/JdbcResultSetMetaDataTest.java | 93 ++-- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 93 ++-- .../spanner/jdbc/JdbcSqlScriptVerifier.java | 18 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 65 ++- .../spanner/jdbc/JdbcTimeoutSqlTest.java | 4 +- .../spanner/jdbc/JdbcTypeConverterTest.java | 88 ++-- .../jdbc/SpannerJdbcExceptionMatcher.java | 4 +- .../spanner/jdbc/it/ITJdbcConnectTest.java | 7 +- .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 2 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 49 +-- .../jdbc/it/ITJdbcQueryOptionsTest.java | 5 + .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 34 +- .../it/ITJdbcReadWriteAutocommitTest.java | 2 +- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 2 +- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 2 +- .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 92 ++-- 55 files changed, 792 insertions(+), 911 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 385a46faec91..a666a7490406 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -170,7 +170,7 @@ public SQLXML createSQLXML() throws SQLException { @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { - Properties supported = null; + Properties supported; try { checkClosed(); supported = JdbcDatabaseMetaData.getDefaultClientInfoProperties(); @@ -255,10 +255,9 @@ public int getNetworkTimeout() throws SQLException { void pushWarning(SQLWarning warning) { if (lastWarning == null) { firstWarning = warning; - lastWarning = warning; } else { lastWarning.setNextWarning(warning); - lastWarning = warning; } + lastWarning = warning; } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java index 74d5ccde3c30..652ed0b25e27 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java @@ -47,12 +47,12 @@ abstract class AbstractJdbcResultSet extends AbstractJdbcWrapper implements Resu } @Override - public SQLWarning getWarnings() throws SQLException { + public SQLWarning getWarnings() { return null; } @Override - public void clearWarnings() throws SQLException {} + public void clearWarnings() {} @Override public String getCursorName() throws SQLException { @@ -105,42 +105,42 @@ public void setFetchDirection(int direction) throws SQLException { } @Override - public int getFetchDirection() throws SQLException { + public int getFetchDirection() { return FETCH_FORWARD; } @Override - public void setFetchSize(int rows) throws SQLException { + public void setFetchSize(int rows) { this.fetchSize = rows; } @Override - public int getFetchSize() throws SQLException { + public int getFetchSize() { return fetchSize; } @Override - public int getType() throws SQLException { + public int getType() { return TYPE_FORWARD_ONLY; } @Override - public int getConcurrency() throws SQLException { + public int getConcurrency() { return CONCUR_READ_ONLY; } @Override - public boolean rowUpdated() throws SQLException { + public boolean rowUpdated() { return false; } @Override - public boolean rowInserted() throws SQLException { + public boolean rowInserted() { return false; } @Override - public boolean rowDeleted() throws SQLException { + public boolean rowDeleted() { return false; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 9863f47c0855..9c516609aa14 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -20,6 +20,7 @@ import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.SpannerException; +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; @@ -252,7 +253,7 @@ StatementResult execute(com.google.cloud.spanner.Statement statement) throws SQL 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, result, originalTimeout); + result = rerunShowStatementTimeout(statement, originalTimeout); } return result; } catch (SpannerException e) { @@ -292,9 +293,7 @@ private boolean resultIsShowStatementTimeout(StatementResult result) { } private StatementResult rerunShowStatementTimeout( - com.google.cloud.spanner.Statement statement, - StatementResult result, - StatementTimeout originalTimeout) + com.google.cloud.spanner.Statement statement, StatementTimeout originalTimeout) throws SQLException { resetStatementTimeout(originalTimeout); return connection.getSpannerConnection().execute(statement); @@ -319,12 +318,12 @@ public void cancel() throws SQLException { } @Override - public void close() throws SQLException { + public void close() { this.closed = true; } @Override - public boolean isClosed() throws SQLException { + public boolean isClosed() { return closed; } @@ -414,22 +413,22 @@ public void setFetchDirection(int direction) throws SQLException { } @Override - public int getFetchDirection() throws SQLException { + public int getFetchDirection() { return ResultSet.FETCH_FORWARD; } @Override - public int getResultSetConcurrency() throws SQLException { + public int getResultSetConcurrency() { return ResultSet.CONCUR_READ_ONLY; } @Override - public int getResultSetType() throws SQLException { + public int getResultSetType() { return ResultSet.TYPE_FORWARD_ONLY; } @Override - public int getResultSetHoldability() throws SQLException { + public int getResultSetHoldability() { return ResultSet.CLOSE_CURSORS_AT_COMMIT; } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 5f296731040e..25ff70a6f3f3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -199,7 +199,7 @@ static float checkedCastToFloat(double val) throws SQLException { static long parseLong(String val) throws SQLException { Preconditions.checkNotNull(val); try { - return Long.valueOf(val); + return Long.parseLong(val); } catch (NumberFormatException e) { throw JdbcSqlExceptionFactory.of( String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); @@ -233,7 +233,7 @@ static long checkedCastToLong(BigDecimal val) throws SQLException { static double parseDouble(String val) throws SQLException { Preconditions.checkNotNull(val); try { - return Double.valueOf(val); + return Double.parseDouble(val); } catch (NumberFormatException e) { throw JdbcSqlExceptionFactory.of( String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); @@ -333,7 +333,7 @@ static Timestamp parseTimestamp(String val, Calendar cal) throws SQLException { } /** Should return true if this object has been closed */ - public abstract boolean isClosed() throws SQLException; + public abstract boolean isClosed(); /** Throws a {@link SQLException} if this object is closed */ void checkClosed() throws SQLException { @@ -354,7 +354,7 @@ T checkClosedAndThrowUnsupported(String message) throws SQLException { } @Override - public boolean isWrapperFor(Class iface) throws SQLException { + public boolean isWrapperFor(Class iface) { return iface != null && iface.isAssignableFrom(getClass()); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 50ae71c56046..7801dcfdc680 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.AbortedDueToConcurrentModificationException; import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.CommitStats; @@ -53,12 +54,12 @@ public interface CloudSpannerJdbcConnection extends Connection { */ default void setTransactionTag(String tag) throws SQLException { throw new UnsupportedOperationException(); - }; + } /** @return The transaction tag of the current transaction. */ default String getTransactionTag() throws SQLException { throw new UnsupportedOperationException(); - }; + } /** * Sets the statement tag to use for the next statement that will be executed. The tag is @@ -70,7 +71,7 @@ default String getTransactionTag() throws SQLException { */ default void setStatementTag(String tag) throws SQLException { throw new UnsupportedOperationException(); - }; + } /** * @return The statement tag that will be used with the next statement that is executed on this @@ -78,7 +79,7 @@ default void setStatementTag(String tag) throws SQLException { */ default String getStatementTag() throws SQLException { throw new UnsupportedOperationException(); - }; + } /** * Sets the transaction mode to use for current transaction. This method may only be called when @@ -96,10 +97,10 @@ default String getStatementTag() throws SQLException { * not acquire locks on Cloud Spanner, and read-only transactions never abort. *
  • {@link TransactionMode#READ_WRITE_TRANSACTION} this value is only allowed when the * connection is not in read-only mode and will create a read-write transaction. If - * {@link Connection#isRetryAbortsInternally()} is true, each read/write - * transaction will keep track of a running SHA256 checksum for each {@link ResultSet} - * that is returned in order to be able to retry the transaction in case the transaction - * is aborted by Spanner. + * {@link CloudSpannerJdbcConnection#isRetryAbortsInternally()} is true, + * each read/write transaction will keep track of a running SHA256 checksum for each + * {@link ResultSet} that is returned in order to be able to retry the transaction in + * case the transaction is aborted by Spanner. * */ void setTransactionMode(TransactionMode transactionMode) throws SQLException; @@ -175,9 +176,8 @@ default String getStatementTag() throws SQLException { /** * @return true if this connection has a transaction (that has not necessarily * started). This method will only return false when the {@link Connection} is in autocommit - * mode and no explicit transaction has been started by calling {@link - * Connection#beginTransaction()}. If the {@link Connection} is not in autocommit mode, there - * will always be a transaction. + * mode and no explicit transaction has been started by executing `BEGIN TRANSACTION`. If the + * {@link Connection} is not in autocommit mode, there will always be a transaction. */ boolean isInTransaction() throws SQLException; @@ -323,7 +323,7 @@ default String getStatementTag() throws SQLException { /** * @see - * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(TransactionRetryListener) + * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) * @throws SQLException if the {@link Connection} is closed. */ void addTransactionRetryListener( @@ -331,7 +331,8 @@ void addTransactionRetryListener( /** * Use {@link - * #addTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener)} + * #addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener)} + * instead. */ @Deprecated void addTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener listener) @@ -339,7 +340,7 @@ void addTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryL /** * @see - * com.google.cloud.spanner.connection.Connection#removeTransactionRetryListener(TransactionRetryListener) + * com.google.cloud.spanner.connection.Connection#removeTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) * @throws SQLException if the {@link Connection} is closed. */ boolean removeTransactionRetryListener( @@ -347,13 +348,14 @@ boolean removeTransactionRetryListener( /** * Use {@link - * #removeTransactionRetryListener(com.google.cloud.spanner.jdbc.TransactionRetryListener)} + * #removeTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener)} + * instead. */ @Deprecated boolean removeTransactionRetryListener( com.google.cloud.spanner.jdbc.TransactionRetryListener listener) throws SQLException; - /** Use {@link #getTransactionRetryListenersFromConnection()} */ + /** Use {@link #getTransactionRetryListenersFromConnection()} instead. */ @Deprecated Iterator getTransactionRetryListeners() throws SQLException; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 4367740509be..f712b56ca722 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -67,13 +67,11 @@ static JdbcArray createArray(String typeName, Object[] elements) throws SQLExcep /** * Create a JDBC {@link Array} from the given type name and list. * - * @param typeName The Google Cloud Spanner type name to be used as the base type of the array. + * @param type The Google Cloud Spanner type to be used as the base type of the array. * @param elements The elements to store in the array. * @return the initialized {@link Array}. - * @throws SQLException if the type name is not a valid Cloud Spanner type or if the contents of - * the elements array is not compatible with the base type of the array. */ - static JdbcArray createArray(JdbcDataType type, List elements) { + static JdbcArray createArray(JdbcDataType type, List elements) { return new JdbcArray(type, elements); } @@ -93,7 +91,7 @@ private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException { } } - private JdbcArray(JdbcDataType type, List elements) { + private JdbcArray(JdbcDataType type, List elements) { this.type = type; if (elements != null) { this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.size()); @@ -179,7 +177,7 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { Object value = ((Object[]) data)[index - 1]; ValueBinder binder = Struct.newBuilder().set("INDEX").to(index).set("VALUE"); - Struct.Builder builder = null; + Struct.Builder builder; switch (type.getCode()) { case BOOL: builder = binder.to((Boolean) value); @@ -237,7 +235,7 @@ public ResultSet getResultSet(long index, int count, Map> map) } @Override - public void free() throws SQLException { + public void free() { this.freed = true; this.data = null; } @@ -257,7 +255,7 @@ public String toString() { if (o == null) { builder.append("null"); } else { - builder.append(o.toString()); + builder.append(o); } } builder.append("}"); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java index 071e3258c020..5a1566f7e4f9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcBlob.java @@ -63,7 +63,7 @@ private void checkPositionPlusLength(long pos, long length) { } @Override - public long length() throws SQLException { + public long length() { return value.length; } @@ -84,7 +84,7 @@ public byte[] getBytes(long pos, int length) throws SQLException { } @Override - public InputStream getBinaryStream() throws SQLException { + public InputStream getBinaryStream() { return new ByteArrayInputStream(value); } @@ -119,7 +119,7 @@ public long position(Blob pattern, long start) throws SQLException { int totalSize = 0; List totalBytes = new ArrayList<>(); try (InputStream is = pattern.getBinaryStream()) { - int bytesRead = 0; + int bytesRead; while ((bytesRead = is.read(buffer)) > -1) { if (bytesRead == buffer.length) { totalBytes.add(buffer); @@ -196,7 +196,7 @@ private BlobOutputStream(int pos) { } @Override - public void write(int b) throws IOException { + public void write(int b) { if (currentPos >= buffer.length) { byte[] newBuffer = new byte[buffer.length * 2]; System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); @@ -239,7 +239,7 @@ public void truncate(long len) throws SQLException { } @Override - public void free() throws SQLException { + public void free() { setLength(0); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java index 40e26733a562..2939dee1afb9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcClob.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; @@ -61,17 +62,8 @@ private void checkPositionPlusLength(long pos, long length) { "position+length larger than " + Integer.MAX_VALUE + " is not supported"); } - private StringBuilder repeat(char c, long length) { - checkLength(length); - StringBuilder res = new StringBuilder((int) length); - for (int i = 0; i < length; i++) { - res.append(c); - } - return res; - } - @Override - public long length() throws SQLException { + public long length() { return value.length(); } @@ -92,12 +84,12 @@ public String getSubString(long pos, int length) throws SQLException { } @Override - public Reader getCharacterStream() throws SQLException { + public Reader getCharacterStream() { return new StringReader(value.toString()); } @Override - public InputStream getAsciiStream() throws SQLException { + public InputStream getAsciiStream() { return new ByteArrayInputStream(StandardCharsets.US_ASCII.encode(value.toString()).array()); } @@ -131,10 +123,11 @@ public int setString(long pos, String str) throws SQLException { JdbcPreconditions.checkArgument(str != null, "str is null"); JdbcPreconditions.checkArgument(pos >= 1, "Position must be >= 1"); checkPosition(pos); - if ((pos - 1) > length()) { - value.append(repeat(' ', pos - length() - 1)); + int ipos = (int) pos; + if ((ipos - 1) > value.length()) { + value.append(Strings.repeat(" ", ipos - value.length() - 1)); } - value.replace((int) pos - 1, (int) pos + str.length() - 1, str); + value.replace(ipos - 1, ipos + str.length() - 1, str); return str.length(); } @@ -191,7 +184,7 @@ public void truncate(long len) throws SQLException { } @Override - public void free() throws SQLException { + public void free() { value = new StringBuilder(); } @@ -201,8 +194,7 @@ public Reader getCharacterStream(long pos, long length) throws SQLException { JdbcPreconditions.checkArgument(length >= 0, "length must be >= 0"); checkPosition(pos); checkPositionPlusLength(pos, length); - return new StringReader( - value.substring((int) pos - 1, (int) pos + (int) length - 1).toString()); + return new StringReader(value.substring((int) pos - 1, (int) pos + (int) length - 1)); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 53c1dc096822..9e4623cabe7c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -25,7 +25,6 @@ import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.connection.TransactionMode; -import com.google.common.base.Function; import com.google.common.collect.Iterators; import java.sql.Array; import java.sql.Blob; @@ -222,7 +221,7 @@ public void close() throws SQLException { } @Override - public boolean isClosed() throws SQLException { + public boolean isClosed() { return getSpannerConnection().isClosed(); } @@ -594,17 +593,11 @@ public Iterator getTransactionRetryListeners() throws checkClosed(); return Iterators.transform( getSpannerConnection().getTransactionRetryListeners(), - new Function< - com.google.cloud.spanner.connection.TransactionRetryListener, - TransactionRetryListener>() { - @Override - public TransactionRetryListener apply( - com.google.cloud.spanner.connection.TransactionRetryListener input) { - if (input instanceof JdbcToSpannerTransactionRetryListener) { - return ((JdbcToSpannerTransactionRetryListener) input).delegate; - } - return null; + input -> { + if (input instanceof JdbcToSpannerTransactionRetryListener) { + return ((JdbcToSpannerTransactionRetryListener) input).delegate; } + return null; }); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java index 58c9e5bb3ba3..164aec0ee50c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java @@ -30,8 +30,9 @@ public final class JdbcConstants { /** * Special value that is used to indicate that a statement had no result. The method {@link * Statement#getUpdateCount()} will return this value if the previous statement that was executed - * with {@link Statement#execute(String)} returned {@link ResultType#NO_RESULT}, such as DDL - * statements {@link ResultType}. + * with {@link Statement#execute(String)} returned {@link + * com.google.cloud.spanner.connection.StatementResult.ResultType#NO_RESULT}, such as DDL + * statements. */ public static final int STATEMENT_NO_RESULT = -2; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java index 72a641cc97ff..026406e2b5dc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java @@ -35,7 +35,7 @@ public class JdbcDataSource extends AbstractJdbcWrapper implements DataSource { private Boolean readonly; private Boolean retryAbortsInternally; - /** Make sure the JDBC driver class is loaded. */ + // Make sure the JDBC driver class is loaded. static { try { Class.forName("com.google.cloud.spanner.jdbc.JdbcDriver"); @@ -46,22 +46,22 @@ public class JdbcDataSource extends AbstractJdbcWrapper implements DataSource { } @Override - public PrintWriter getLogWriter() throws SQLException { + public PrintWriter getLogWriter() { return null; } @Override - public void setLogWriter(PrintWriter out) throws SQLException { + public void setLogWriter(PrintWriter out) { // no-op } @Override - public void setLoginTimeout(int seconds) throws SQLException { + public void setLoginTimeout(int seconds) { // no-op } @Override - public int getLoginTimeout() throws SQLException { + public int getLoginTimeout() { return 0; } @@ -110,7 +110,7 @@ private Properties createProperties() { } @Override - public boolean isClosed() throws SQLException { + public boolean isClosed() { return false; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 8da36e4c4bf1..1a62775b7176 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -111,7 +111,7 @@ public Type getSpannerType() { } }, FLOAT64 { - private Set> classes = new HashSet>(Arrays.asList(Float.class, Double.class)); + private final Set> classes = new HashSet<>(Arrays.asList(Float.class, Double.class)); @Override public int getSqlType() { @@ -144,8 +144,8 @@ public Type getSpannerType() { } }, INT64 { - private Set> classes = - new HashSet>(Arrays.asList(Byte.class, Integer.class, Long.class)); + private final Set> classes = + new HashSet<>(Arrays.asList(Byte.class, Integer.class, Long.class)); @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 191d991ea5f9..42828fb5c441 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -57,12 +57,11 @@ static String readSqlFromFile(String filename) { String line = scanner.nextLine(); builder.append(line).append("\n"); } - scanner.close(); } return builder.toString(); } - private JdbcConnection connection; + private final JdbcConnection connection; JdbcDatabaseMetaData(JdbcConnection connection) { this.connection = connection; @@ -74,22 +73,22 @@ public boolean isClosed() { } @Override - public boolean allProceduresAreCallable() throws SQLException { + public boolean allProceduresAreCallable() { return true; } @Override - public boolean allTablesAreSelectable() throws SQLException { + public boolean allTablesAreSelectable() { return true; } @Override - public String getURL() throws SQLException { + public String getURL() { return connection.getConnectionUrl(); } @Override - public String getUserName() throws SQLException { + public String getUserName() { Credentials credentials = connection.getConnectionOptions().getCredentials(); if (credentials != null) { if (credentials instanceof ServiceAccountSigner) { @@ -102,47 +101,47 @@ public String getUserName() throws SQLException { } @Override - public boolean isReadOnly() throws SQLException { + public boolean isReadOnly() { return false; } @Override - public boolean nullsAreSortedHigh() throws SQLException { + public boolean nullsAreSortedHigh() { return false; } @Override - public boolean nullsAreSortedLow() throws SQLException { + public boolean nullsAreSortedLow() { return true; } @Override - public boolean nullsAreSortedAtStart() throws SQLException { + public boolean nullsAreSortedAtStart() { return false; } @Override - public boolean nullsAreSortedAtEnd() throws SQLException { + public boolean nullsAreSortedAtEnd() { return false; } @Override - public String getDatabaseProductName() throws SQLException { + public String getDatabaseProductName() { return PRODUCT_NAME; } @Override - public String getDatabaseProductVersion() throws SQLException { + public String getDatabaseProductVersion() { return getDatabaseMajorVersion() + "." + getDatabaseMinorVersion(); } @Override - public String getDriverName() throws SQLException { + public String getDriverName() { return JdbcDriver.class.getName(); } @Override - public String getDriverVersion() throws SQLException { + public String getDriverVersion() { return getDriverMajorVersion() + "." + getDriverMinorVersion(); } @@ -157,528 +156,530 @@ public int getDriverMinorVersion() { } @Override - public boolean usesLocalFiles() throws SQLException { + public boolean usesLocalFiles() { return false; } @Override - public boolean usesLocalFilePerTable() throws SQLException { + public boolean usesLocalFilePerTable() { return false; } @Override - public boolean supportsMixedCaseIdentifiers() throws SQLException { + public boolean supportsMixedCaseIdentifiers() { return false; } @Override - public boolean storesUpperCaseIdentifiers() throws SQLException { + public boolean storesUpperCaseIdentifiers() { return false; } @Override - public boolean storesLowerCaseIdentifiers() throws SQLException { + public boolean storesLowerCaseIdentifiers() { return false; } @Override - public boolean storesMixedCaseIdentifiers() throws SQLException { + public boolean storesMixedCaseIdentifiers() { return true; } @Override - public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + public boolean supportsMixedCaseQuotedIdentifiers() { return false; } @Override - public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + public boolean storesUpperCaseQuotedIdentifiers() { return false; } @Override - public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + public boolean storesLowerCaseQuotedIdentifiers() { return false; } @Override - public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + public boolean storesMixedCaseQuotedIdentifiers() { return true; } @Override - public String getIdentifierQuoteString() throws SQLException { + public String getIdentifierQuoteString() { return "`"; } @Override - public String getSQLKeywords() throws SQLException { + public String getSQLKeywords() { return "ASSERT_ROWS_MODIFIED,ENUM,GROUPS,HASH,IGNORE,LOOKUP,PROTO,RESPECT,STRUCT,WINDOW"; } @Override - public String getNumericFunctions() throws SQLException { + public String getNumericFunctions() { return "ABS,SIGN,IS_INF,IS_NAN,IEEE_DIVIDE,SQRT,POW,POWER,EXP,LN,LOG,LOG10,GREATEST,LEAST,DIV,MOD,ROUND,TRUNC,CEIL,CEILING,FLOOR,COS,COSH,ACOS,ACOSH,SIN,SINH,ASIN,ASINH,TAN,TANH,ATAN,ATANH,ATAN2,FARM_FINGERPRINT,SHA1,SHA256,SHA512"; } @Override - public String getStringFunctions() throws SQLException { + public String getStringFunctions() { return "BYTE_LENGTH,CHAR_LENGTH,CHARACTER_LENGTH,CODE_POINTS_TO_BYTES,CODE_POINTS_TO_STRING,CONCAT,ENDS_WITH,FORMAT,FROM_BASE64,FROM_HEX,LENGTH,LPAD,LOWER,LTRIM,REGEXP_CONTAINS,REGEXP_EXTRACT,REGEXP_EXTRACT_ALL,REGEXP_REPLACE,REPLACE,REPEAT,REVERSE,RPAD,RTRIM,SAFE_CONVERT_BYTES_TO_STRING,SPLIT,STARTS_WITH,STRPOS,SUBSTR,TO_BASE64,TO_CODE_POINTS,TO_HEX,TRIM,UPPER,JSON_QUERY,JSON_VALUE"; } @Override - public String getSystemFunctions() throws SQLException { + public String getSystemFunctions() { return ""; } @Override - public String getTimeDateFunctions() throws SQLException { + public String getTimeDateFunctions() { return "CURRENT_DATE,EXTRACT,DATE,DATE_ADD,DATE_SUB,DATE_DIFF,DATE_TRUNC,DATE_FROM_UNIX_DATE,FORMAT_DATE,PARSE_DATE,UNIX_DATE,CURRENT_TIMESTAMP,STRING,TIMESTAMP,TIMESTAMP_ADD,TIMESTAMP_SUB,TIMESTAMP_DIFF,TIMESTAMP_TRUNC,FORMAT_TIMESTAMP,PARSE_TIMESTAMP,TIMESTAMP_SECONDS,TIMESTAMP_MILLIS,TIMESTAMP_MICROS,UNIX_SECONDS,UNIX_MILLIS,UNIX_MICROS"; } @Override - public String getSearchStringEscape() throws SQLException { + public String getSearchStringEscape() { return "\\"; } @Override - public String getExtraNameCharacters() throws SQLException { + public String getExtraNameCharacters() { return ""; } @Override - public boolean supportsAlterTableWithAddColumn() throws SQLException { + public boolean supportsAlterTableWithAddColumn() { return true; } @Override - public boolean supportsAlterTableWithDropColumn() throws SQLException { + public boolean supportsAlterTableWithDropColumn() { return true; } @Override - public boolean supportsColumnAliasing() throws SQLException { + public boolean supportsColumnAliasing() { return true; } @Override - public boolean nullPlusNonNullIsNull() throws SQLException { + public boolean nullPlusNonNullIsNull() { return true; } @Override - public boolean supportsConvert() throws SQLException { + public boolean supportsConvert() { return false; } @Override - public boolean supportsConvert(int fromType, int toType) throws SQLException { + public boolean supportsConvert(int fromType, int toType) { return false; } @Override - public boolean supportsTableCorrelationNames() throws SQLException { + public boolean supportsTableCorrelationNames() { return true; } @Override - public boolean supportsDifferentTableCorrelationNames() throws SQLException { + public boolean supportsDifferentTableCorrelationNames() { return false; } @Override - public boolean supportsExpressionsInOrderBy() throws SQLException { + public boolean supportsExpressionsInOrderBy() { return true; } @Override - public boolean supportsOrderByUnrelated() throws SQLException { + public boolean supportsOrderByUnrelated() { return true; } @Override - public boolean supportsGroupBy() throws SQLException { + public boolean supportsGroupBy() { return true; } @Override - public boolean supportsGroupByUnrelated() throws SQLException { + public boolean supportsGroupByUnrelated() { return true; } @Override - public boolean supportsGroupByBeyondSelect() throws SQLException { + public boolean supportsGroupByBeyondSelect() { return true; } @Override - public boolean supportsLikeEscapeClause() throws SQLException { + public boolean supportsLikeEscapeClause() { return true; } @Override - public boolean supportsMultipleResultSets() throws SQLException { + public boolean supportsMultipleResultSets() { return true; } @Override - public boolean supportsMultipleTransactions() throws SQLException { + public boolean supportsMultipleTransactions() { return true; } @Override - public boolean supportsNonNullableColumns() throws SQLException { + public boolean supportsNonNullableColumns() { return true; } @Override - public boolean supportsMinimumSQLGrammar() throws SQLException { + public boolean supportsMinimumSQLGrammar() { return false; } @Override - public boolean supportsCoreSQLGrammar() throws SQLException { + public boolean supportsCoreSQLGrammar() { return false; } @Override - public boolean supportsExtendedSQLGrammar() throws SQLException { + public boolean supportsExtendedSQLGrammar() { return false; } @Override - public boolean supportsANSI92EntryLevelSQL() throws SQLException { + public boolean supportsANSI92EntryLevelSQL() { return false; } @Override - public boolean supportsANSI92IntermediateSQL() throws SQLException { + public boolean supportsANSI92IntermediateSQL() { return false; } @Override - public boolean supportsANSI92FullSQL() throws SQLException { + public boolean supportsANSI92FullSQL() { return false; } @Override - public boolean supportsIntegrityEnhancementFacility() throws SQLException { + public boolean supportsIntegrityEnhancementFacility() { return false; } @Override - public boolean supportsOuterJoins() throws SQLException { + public boolean supportsOuterJoins() { return true; } @Override - public boolean supportsFullOuterJoins() throws SQLException { + public boolean supportsFullOuterJoins() { return true; } @Override - public boolean supportsLimitedOuterJoins() throws SQLException { + public boolean supportsLimitedOuterJoins() { return true; } @Override - public String getSchemaTerm() throws SQLException { + public String getSchemaTerm() { return "SCHEMA"; } @Override - public String getProcedureTerm() throws SQLException { + public String getProcedureTerm() { return "PROCEDURE"; } @Override - public String getCatalogTerm() throws SQLException { + public String getCatalogTerm() { // Spanner does not support catalogs, but the term is included for compatibility with the SQL // standard return "CATALOG"; } @Override - public boolean isCatalogAtStart() throws SQLException { + public boolean isCatalogAtStart() { return false; } @Override - public String getCatalogSeparator() throws SQLException { + public String getCatalogSeparator() { return "."; } @Override - public boolean supportsSchemasInDataManipulation() throws SQLException { + public boolean supportsSchemasInDataManipulation() { return false; } @Override - public boolean supportsSchemasInProcedureCalls() throws SQLException { + public boolean supportsSchemasInProcedureCalls() { return false; } @Override - public boolean supportsSchemasInTableDefinitions() throws SQLException { + public boolean supportsSchemasInTableDefinitions() { return false; } @Override - public boolean supportsSchemasInIndexDefinitions() throws SQLException { + public boolean supportsSchemasInIndexDefinitions() { return false; } @Override - public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + public boolean supportsSchemasInPrivilegeDefinitions() { return false; } @Override - public boolean supportsCatalogsInDataManipulation() throws SQLException { + public boolean supportsCatalogsInDataManipulation() { return false; } @Override - public boolean supportsCatalogsInProcedureCalls() throws SQLException { + public boolean supportsCatalogsInProcedureCalls() { return false; } @Override - public boolean supportsCatalogsInTableDefinitions() throws SQLException { + public boolean supportsCatalogsInTableDefinitions() { return false; } @Override - public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + public boolean supportsCatalogsInIndexDefinitions() { return false; } @Override - public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + public boolean supportsCatalogsInPrivilegeDefinitions() { return false; } @Override - public boolean supportsPositionedDelete() throws SQLException { + public boolean supportsPositionedDelete() { return false; } @Override - public boolean supportsPositionedUpdate() throws SQLException { + public boolean supportsPositionedUpdate() { return false; } @Override - public boolean supportsSelectForUpdate() throws SQLException { + public boolean supportsSelectForUpdate() { return false; } @Override - public boolean supportsStoredProcedures() throws SQLException { + public boolean supportsStoredProcedures() { return false; } @Override - public boolean supportsSubqueriesInComparisons() throws SQLException { + public boolean supportsSubqueriesInComparisons() { return true; } @Override - public boolean supportsSubqueriesInExists() throws SQLException { + public boolean supportsSubqueriesInExists() { return true; } @Override - public boolean supportsSubqueriesInIns() throws SQLException { + public boolean supportsSubqueriesInIns() { return true; } @Override - public boolean supportsSubqueriesInQuantifieds() throws SQLException { + public boolean supportsSubqueriesInQuantifieds() { return true; } @Override - public boolean supportsCorrelatedSubqueries() throws SQLException { + public boolean supportsCorrelatedSubqueries() { return true; } @Override - public boolean supportsUnion() throws SQLException { + public boolean supportsUnion() { // Note that Cloud Spanner requires the user to specify 'UNION DISTINCT' or 'UNION ALL' in a // query. 'UNION DISTINCT' is equal to the SQL operation 'UNION'. return true; } @Override - public boolean supportsUnionAll() throws SQLException { + public boolean supportsUnionAll() { return true; } @Override - public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + public boolean supportsOpenCursorsAcrossCommit() { return false; } @Override - public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + public boolean supportsOpenCursorsAcrossRollback() { return false; } @Override - public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + public boolean supportsOpenStatementsAcrossCommit() { return true; } @Override - public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + public boolean supportsOpenStatementsAcrossRollback() { return true; } @Override - public int getMaxBinaryLiteralLength() throws SQLException { + public int getMaxBinaryLiteralLength() { return 0; } @Override - public int getMaxCharLiteralLength() throws SQLException { + public int getMaxCharLiteralLength() { return 0; } @Override - public int getMaxColumnNameLength() throws SQLException { + public int getMaxColumnNameLength() { return 128; } @Override - public int getMaxColumnsInGroupBy() throws SQLException { + public int getMaxColumnsInGroupBy() { return 1000; } @Override - public int getMaxColumnsInIndex() throws SQLException { + public int getMaxColumnsInIndex() { return 16; } @Override - public int getMaxColumnsInOrderBy() throws SQLException { + public int getMaxColumnsInOrderBy() { return 0; } @Override - public int getMaxColumnsInSelect() throws SQLException { + public int getMaxColumnsInSelect() { return 0; } @Override - public int getMaxColumnsInTable() throws SQLException { + public int getMaxColumnsInTable() { return 1024; } @Override - public int getMaxConnections() throws SQLException { + public int getMaxConnections() { // there is a max number of sessions, but that is not the same as the max number of connections return 0; } @Override - public int getMaxCursorNameLength() throws SQLException { + public int getMaxCursorNameLength() { return 0; } @Override - public int getMaxIndexLength() throws SQLException { + public int getMaxIndexLength() { return 8000; } @Override - public int getMaxSchemaNameLength() throws SQLException { + public int getMaxSchemaNameLength() { return 0; } @Override - public int getMaxProcedureNameLength() throws SQLException { + public int getMaxProcedureNameLength() { return 0; } @Override - public int getMaxCatalogNameLength() throws SQLException { + public int getMaxCatalogNameLength() { return 0; } @Override - public int getMaxRowSize() throws SQLException { - return 1024 * 10000000; + public int getMaxRowSize() { + // The limit is 1024 columns per table * 10MB per column, which is more than fits in an int. + // We therefore return 0 to indicate no limit (or an unknown limit). + return 0; } @Override - public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + public boolean doesMaxRowSizeIncludeBlobs() { return true; } @Override - public int getMaxStatementLength() throws SQLException { + public int getMaxStatementLength() { return 1000000; } @Override - public int getMaxStatements() throws SQLException { + public int getMaxStatements() { return 0; } @Override - public int getMaxTableNameLength() throws SQLException { + public int getMaxTableNameLength() { return 128; } @Override - public int getMaxTablesInSelect() throws SQLException { + public int getMaxTablesInSelect() { return 0; } @Override - public int getMaxUserNameLength() throws SQLException { + public int getMaxUserNameLength() { return 0; } @Override - public int getDefaultTransactionIsolation() throws SQLException { + public int getDefaultTransactionIsolation() { return Connection.TRANSACTION_SERIALIZABLE; } @Override - public boolean supportsTransactions() throws SQLException { + public boolean supportsTransactions() { return true; } @Override - public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + public boolean supportsTransactionIsolationLevel(int level) { return Connection.TRANSACTION_SERIALIZABLE == level; } @Override - public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + public boolean supportsDataDefinitionAndDataManipulationTransactions() { return false; } @Override - public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + public boolean supportsDataManipulationTransactionsOnly() { return true; } @Override - public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + public boolean dataDefinitionCausesTransactionCommit() { return false; } @Override - public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + public boolean dataDefinitionIgnoredInTransactions() { return false; } @Override - public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) - throws SQLException { + public ResultSet getProcedures( + String catalog, String schemaPattern, String procedureNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -691,13 +692,12 @@ public ResultSet getProcedures(String catalog, String schemaPattern, String proc StructField.of("REMARKS", Type.string()), StructField.of("PROCEDURE_TYPE", Type.int64()), StructField.of("SPECIFIC_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override public ResultSet getProcedureColumns( - String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) - throws SQLException { + String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -721,7 +721,7 @@ public ResultSet getProcedureColumns( StructField.of("ORDINAL_POSITION", Type.int64()), StructField.of("IS_NULLABLE", Type.string()), StructField.of("SPECIFIC_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } private JdbcPreparedStatement prepareStatementReplaceNullWithAnyString( @@ -768,15 +768,15 @@ public ResultSet getSchemas() throws SQLException { } @Override - public ResultSet getCatalogs() throws SQLException { + public ResultSet getCatalogs() { return JdbcResultSet.of( ResultSets.forRows( Type.struct(StructField.of("TABLE_CAT", Type.string())), - Arrays.asList(Struct.newBuilder().set("TABLE_CAT").to("").build()))); + Collections.singletonList(Struct.newBuilder().set("TABLE_CAT").to("").build()))); } @Override - public ResultSet getTableTypes() throws SQLException { + public ResultSet getTableTypes() { return JdbcResultSet.of( ResultSets.forRows( Type.struct(StructField.of("TABLE_TYPE", Type.string())), @@ -798,7 +798,7 @@ public ResultSet getColumns( @Override public ResultSet getColumnPrivileges( - String catalog, String schema, String table, String columnNamePattern) throws SQLException { + String catalog, String schema, String table, String columnNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -810,12 +810,12 @@ public ResultSet getColumnPrivileges( StructField.of("GRANTEE", Type.string()), StructField.of("PRIVILEGE", Type.string()), StructField.of("IS_GRANTABLE", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override - public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { + public ResultSet getTablePrivileges( + String catalog, String schemaPattern, String tableNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -826,30 +826,21 @@ public ResultSet getTablePrivileges(String catalog, String schemaPattern, String StructField.of("GRANTEE", Type.string()), StructField.of("PRIVILEGE", Type.string()), StructField.of("IS_GRANTABLE", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override public ResultSet getBestRowIdentifier( - String catalog, String schema, String table, int scope, boolean nullable) - throws SQLException { - return JdbcResultSet.of( - ResultSets.forRows( - Type.struct( - StructField.of("SCOPE", Type.int64()), - StructField.of("COLUMN_NAME", Type.string()), - StructField.of("DATA_TYPE", Type.int64()), - StructField.of("TYPE_NAME", Type.string()), - StructField.of("COLUMN_SIZE", Type.int64()), - StructField.of("BUFFER_LENGTH", Type.int64()), - StructField.of("DECIMAL_DIGITS", Type.int64()), - StructField.of("PSEUDO_COLUMN", Type.int64())), - Collections.emptyList())); + String catalog, String schema, String table, int scope, boolean nullable) { + return getEmptyColumnsResultSet(); } @Override - public ResultSet getVersionColumns(String catalog, String schema, String table) - throws SQLException { + public ResultSet getVersionColumns(String catalog, String schema, String table) { + return getEmptyColumnsResultSet(); + } + + private ResultSet getEmptyColumnsResultSet() { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -861,7 +852,7 @@ public ResultSet getVersionColumns(String catalog, String schema, String table) StructField.of("BUFFER_LENGTH", Type.int64()), StructField.of("DECIMAL_DIGITS", Type.int64()), StructField.of("PSEUDO_COLUMN", Type.int64())), - Collections.emptyList())); + Collections.emptyList())); } @Override @@ -916,7 +907,7 @@ public ResultSet getCrossReference( } @Override - public ResultSet getTypeInfo() throws SQLException { + public ResultSet getTypeInfo() { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1268,69 +1259,68 @@ private ResultSet getIndexInfo( } @Override - public boolean supportsResultSetType(int type) throws SQLException { + public boolean supportsResultSetType(int type) { return type == ResultSet.TYPE_FORWARD_ONLY; } @Override - public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + public boolean supportsResultSetConcurrency(int type, int concurrency) { return type == ResultSet.TYPE_FORWARD_ONLY && concurrency == ResultSet.CONCUR_READ_ONLY; } @Override - public boolean ownUpdatesAreVisible(int type) throws SQLException { + public boolean ownUpdatesAreVisible(int type) { return false; } @Override - public boolean ownDeletesAreVisible(int type) throws SQLException { + public boolean ownDeletesAreVisible(int type) { return false; } @Override - public boolean ownInsertsAreVisible(int type) throws SQLException { + public boolean ownInsertsAreVisible(int type) { return false; } @Override - public boolean othersUpdatesAreVisible(int type) throws SQLException { + public boolean othersUpdatesAreVisible(int type) { return false; } @Override - public boolean othersDeletesAreVisible(int type) throws SQLException { + public boolean othersDeletesAreVisible(int type) { return false; } @Override - public boolean othersInsertsAreVisible(int type) throws SQLException { + public boolean othersInsertsAreVisible(int type) { return false; } @Override - public boolean updatesAreDetected(int type) throws SQLException { + public boolean updatesAreDetected(int type) { return false; } @Override - public boolean deletesAreDetected(int type) throws SQLException { + public boolean deletesAreDetected(int type) { return false; } @Override - public boolean insertsAreDetected(int type) throws SQLException { + public boolean insertsAreDetected(int type) { return false; } @Override - public boolean supportsBatchUpdates() throws SQLException { + public boolean supportsBatchUpdates() { return true; } @Override public ResultSet getUDTs( - String catalog, String schemaPattern, String typeNamePattern, int[] types) - throws SQLException { + String catalog, String schemaPattern, String typeNamePattern, int[] types) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1341,37 +1331,36 @@ public ResultSet getUDTs( StructField.of("DATA_TYPE", Type.int64()), StructField.of("REMARKS", Type.string()), StructField.of("BASE_TYPE", Type.int64())), - Collections.emptyList())); + Collections.emptyList())); } @Override - public Connection getConnection() throws SQLException { + public Connection getConnection() { return connection; } @Override - public boolean supportsSavepoints() throws SQLException { + public boolean supportsSavepoints() { return false; } @Override - public boolean supportsNamedParameters() throws SQLException { + public boolean supportsNamedParameters() { return false; } @Override - public boolean supportsMultipleOpenResults() throws SQLException { + public boolean supportsMultipleOpenResults() { return true; } @Override - public boolean supportsGetGeneratedKeys() throws SQLException { + public boolean supportsGetGeneratedKeys() { return false; } @Override - public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) - throws SQLException { + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1381,12 +1370,11 @@ public ResultSet getSuperTypes(String catalog, String schemaPattern, String type StructField.of("SUPERTYPE_CAT", Type.string()), StructField.of("SUPERTYPE_SCHEM", Type.string()), StructField.of("SUPERTYPE_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override - public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1394,13 +1382,12 @@ public ResultSet getSuperTables(String catalog, String schemaPattern, String tab StructField.of("TABLE_SCHEM", Type.string()), StructField.of("TABLE_NAME", Type.string()), StructField.of("SUPERTABLE_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override public ResultSet getAttributes( - String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) - throws SQLException { + String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1425,56 +1412,56 @@ public ResultSet getAttributes( StructField.of("SCOPE_SCHEMA", Type.string()), StructField.of("SCOPE_TABLE", Type.string()), StructField.of("SOURCE_DATA_TYPE", Type.int64())), - Collections.emptyList())); + Collections.emptyList())); } @Override - public boolean supportsResultSetHoldability(int holdability) throws SQLException { + public boolean supportsResultSetHoldability(int holdability) { return holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT; } @Override - public int getResultSetHoldability() throws SQLException { + public int getResultSetHoldability() { return ResultSet.CLOSE_CURSORS_AT_COMMIT; } @Override - public int getDatabaseMajorVersion() throws SQLException { + public int getDatabaseMajorVersion() { return DATABASE_MAJOR_VERSION; } @Override - public int getDatabaseMinorVersion() throws SQLException { + public int getDatabaseMinorVersion() { return DATABASE_MINOR_VERSION; } @Override - public int getJDBCMajorVersion() throws SQLException { + public int getJDBCMajorVersion() { return JDBC_MAJOR_VERSION; } @Override - public int getJDBCMinorVersion() throws SQLException { + public int getJDBCMinorVersion() { return JDBC_MINOR_VERSION; } @Override - public int getSQLStateType() throws SQLException { + public int getSQLStateType() { return sqlStateSQL; } @Override - public boolean locatorsUpdateCopy() throws SQLException { + public boolean locatorsUpdateCopy() { return true; } @Override - public boolean supportsStatementPooling() throws SQLException { + public boolean supportsStatementPooling() { return false; } @Override - public RowIdLifetime getRowIdLifetime() throws SQLException { + public RowIdLifetime getRowIdLifetime() { return RowIdLifetime.ROWID_UNSUPPORTED; } @@ -1487,12 +1474,12 @@ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLExce } @Override - public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + public boolean supportsStoredFunctionsUsingCallSyntax() { return false; } @Override - public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + public boolean autoCommitFailureClosesAllResultSets() { return false; } @@ -1511,7 +1498,7 @@ static Properties getDefaultClientInfoProperties() throws SQLException { return info; } - private static ResultSet getDefaultClientInfo() throws SQLException { + private static ResultSet getDefaultClientInfo() { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1556,13 +1543,12 @@ private static ResultSet getDefaultClientInfo() throws SQLException { } @Override - public ResultSet getClientInfoProperties() throws SQLException { + public ResultSet getClientInfoProperties() { return getDefaultClientInfo(); } @Override - public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) - throws SQLException { + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) { // TODO: return system functions return JdbcResultSet.of( ResultSets.forRows( @@ -1573,13 +1559,12 @@ public ResultSet getFunctions(String catalog, String schemaPattern, String funct StructField.of("REMARKS", Type.string()), StructField.of("FUNCTION_TYPE", Type.int64()), StructField.of("SPECIFIC_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override public ResultSet getFunctionColumns( - String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) - throws SQLException { + String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) { // TODO: return system functions return JdbcResultSet.of( ResultSets.forRows( @@ -1601,13 +1586,12 @@ public ResultSet getFunctionColumns( StructField.of("ORDINAL_POSITION", Type.int64()), StructField.of("IS_NULLABLE", Type.string()), StructField.of("SPECIFIC_NAME", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override public ResultSet getPseudoColumns( - String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) - throws SQLException { + String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) { return JdbcResultSet.of( ResultSets.forRows( Type.struct( @@ -1623,22 +1607,22 @@ public ResultSet getPseudoColumns( StructField.of("REMARKS", Type.string()), StructField.of("CHAR_OCTET_LENGTH", Type.int64()), StructField.of("IS_NULLABLE", Type.string())), - Collections.emptyList())); + Collections.emptyList())); } @Override - public boolean generatedKeyAlwaysReturned() throws SQLException { + public boolean generatedKeyAlwaysReturned() { return false; } @Override - public long getMaxLogicalLobSize() throws SQLException { + public long getMaxLogicalLobSize() { // BYTES(MAX) return 10485760L; } @Override - public boolean supportsRefCursors() throws SQLException { + public boolean supportsRefCursors() { return false; } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 08dd5fafe9bf..b127e6825335 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -220,12 +220,12 @@ private String appendPropertiesToUrl(String url, Properties info) { } @Override - public boolean acceptsURL(String url) throws SQLException { + public boolean acceptsURL(String url) { return URL_PATTERN.matcher(url).matches(); } @Override - public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { String connectionUri = appendPropertiesToUrl(url.substring(5), info); DriverPropertyInfo[] res = new DriverPropertyInfo[ConnectionOptions.VALID_PROPERTIES.size()]; int i = 0; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java index 59b10b68fd0b..f5188653b3ea 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -40,19 +40,20 @@ public boolean isClosed() { } @Override - public int getParameterCount() throws SQLException { + public int getParameterCount() { ParametersInfo info = statement.getParametersInfo(); return info.numberOfParameters; } @Override - public int isNullable(int param) throws SQLException { + public int isNullable(int param) { Integer nullable = statement.getParameters().getNullable(param); - return nullable == null ? parameterNullableUnknown : nullable.intValue(); + //noinspection MagicConstant + return nullable == null ? parameterNullableUnknown : nullable; } @Override - public boolean isSigned(int param) throws SQLException { + public boolean isSigned(int param) { int type = getParameterType(param); return type == Types.DOUBLE || type == Types.FLOAT @@ -65,20 +66,20 @@ public boolean isSigned(int param) throws SQLException { } @Override - public int getPrecision(int param) throws SQLException { + public int getPrecision(int param) { Integer length = statement.getParameters().getScaleOrLength(param); - return length == null ? 0 : length.intValue(); + return length == null ? 0 : length; } @Override - public int getScale(int param) throws SQLException { + public int getScale(int param) { return 0; } @Override - public int getParameterType(int param) throws SQLException { + public int getParameterType(int param) { Integer type = statement.getParameters().getType(param); - if (type != null) return type.intValue(); + if (type != null) return type; Object value = statement.getParameters().getParameter(param); if (value == null) { @@ -115,45 +116,41 @@ public int getParameterType(int param) throws SQLException { } @Override - public String getParameterTypeName(int param) throws SQLException { + public String getParameterTypeName(int param) { return getSpannerTypeName(getParameterType(param)); } @Override - public String getParameterClassName(int param) throws SQLException { + public String getParameterClassName(int param) { Object value = statement.getParameters().getParameter(param); if (value != null) return value.getClass().getName(); Integer type = statement.getParameters().getType(param); - if (type != null) return getClassName(type.intValue()); + if (type != null) return getClassName(type); return null; } @Override - public int getParameterMode(int param) throws SQLException { + public int getParameterMode(int param) { return parameterModeIn; } @Override public String toString() { StringBuilder res = new StringBuilder(); - try { - res.append("CloudSpannerPreparedStatementParameterMetaData, parameter count: ") - .append(getParameterCount()); - for (int param = 1; param <= getParameterCount(); param++) { - res.append("\nParameter ") - .append(param) - .append(":\n\t Class name: ") - .append(getParameterClassName(param)); - res.append(",\n\t Parameter type name: ").append(getParameterTypeName(param)); - res.append(",\n\t Parameter type: ").append(getParameterType(param)); - res.append(",\n\t Parameter precision: ").append(getPrecision(param)); - res.append(",\n\t Parameter scale: ").append(getScale(param)); - res.append(",\n\t Parameter signed: ").append(isSigned(param)); - res.append(",\n\t Parameter nullable: ").append(isNullable(param)); - res.append(",\n\t Parameter mode: ").append(getParameterMode(param)); - } - } catch (SQLException e) { - res.append("Error while fetching parameter metadata: ").append(e.getMessage()); + res.append("CloudSpannerPreparedStatementParameterMetaData, parameter count: ") + .append(getParameterCount()); + for (int param = 1; param <= getParameterCount(); param++) { + res.append("\nParameter ") + .append(param) + .append(":\n\t Class name: ") + .append(getParameterClassName(param)); + res.append(",\n\t Parameter type name: ").append(getParameterTypeName(param)); + res.append(",\n\t Parameter type: ").append(getParameterType(param)); + res.append(",\n\t Parameter precision: ").append(getPrecision(param)); + res.append(",\n\t Parameter scale: ").append(getScale(param)); + res.append(",\n\t Parameter signed: ").append(isSigned(param)); + res.append(",\n\t Parameter nullable: ").append(isNullable(param)); + res.append(",\n\t Parameter mode: ").append(getParameterMode(param)); } return res.toString(); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 24773cdced80..a475646a64db 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -420,15 +420,13 @@ static ParametersInfo convertPositionalParametersToNamedParameters(String sql) isInQuoted = false; startQuote = 0; } - } else if (c == '\\') { - lastCharWasEscapeChar = true; } else { - lastCharWasEscapeChar = false; + lastCharWasEscapeChar = (c == '\\'); } named.append(c); } else { if (c == POS_PARAM) { - named.append("@p" + paramIndex); + named.append("@p").append(paramIndex); paramIndex++; } else { if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { @@ -487,7 +485,7 @@ Builder setValue(ValueBinder binder, Object value, Integer sqlType) thr } if (res == null && value != null) { throw JdbcSqlExceptionFactory.of( - "Unsupported parameter type: " + value.getClass().getName() + " - " + value.toString(), + "Unsupported parameter type: " + value.getClass().getName() + " - " + value, Code.INVALID_ARGUMENT); } return res; @@ -497,7 +495,7 @@ private Builder setSingleValue(ValueBinder binder, Object value, Intege throws SQLException { if (value == null) { return setNullValue(binder, sqlType); - } else if (sqlType == null || sqlType == Integer.valueOf(Types.OTHER)) { + } else if (sqlType == null || sqlType.equals(Types.OTHER)) { return setParamWithUnknownType(binder, value); } else { return setParamWithKnownType(binder, value, sqlType); @@ -559,7 +557,7 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } else if (value instanceof Reader) { stringValue = getStringFromReader((Reader) value); } else if (value instanceof URL) { - stringValue = ((URL) value).toString(); + stringValue = value.toString(); } else if (value instanceof UUID) { stringValue = ((UUID) value).toString(); } else { @@ -621,7 +619,7 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, case Types.ARRAY: if (value instanceof Array) { Array jdbcArray = (Array) value; - return setArrayValue(binder, sqlType, jdbcArray == null ? null : jdbcArray.getArray()); + return setArrayValue(binder, sqlType, jdbcArray.getArray()); } throw JdbcSqlExceptionFactory.of(value + " is not a valid array", Code.INVALID_ARGUMENT); case Types.BLOB: @@ -719,8 +717,7 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } catch (IOException e) { throw new IllegalArgumentException("Could not read from readable", e); } - } else if (Clob.class.isAssignableFrom(value.getClass()) - || NClob.class.isAssignableFrom(value.getClass())) { + } else if (Clob.class.isAssignableFrom(value.getClass())) { try { Clob clob = (Clob) value; return binder.to(CharStreams.toString(clob.getCharacterStream())); @@ -739,7 +736,7 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } else if (char[].class.isAssignableFrom(value.getClass())) { return binder.to(String.valueOf((char[]) value)); } else if (URL.class.isAssignableFrom(value.getClass())) { - return binder.to(((URL) value).toString()); + return binder.to(value.toString()); } else if (UUID.class.isAssignableFrom(value.getClass())) { return binder.to(((UUID) value).toString()); } else if (byte[].class.isAssignableFrom(value.getClass())) { @@ -761,12 +758,10 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } else if (Array.class.isAssignableFrom(value.getClass())) { try { Array jdbcArray = (Array) value; - if (value != null) { - return setArrayValue(binder, jdbcArray.getBaseType(), jdbcArray.getArray()); - } + return setArrayValue(binder, jdbcArray.getBaseType(), jdbcArray.getArray()); } catch (SQLException e) { throw new IllegalArgumentException( - "Unsupported parameter type: " + value.getClass().getName() + " - " + value.toString()); + "Unsupported parameter type: " + value.getClass().getName() + " - " + value); } } return null; @@ -813,7 +808,7 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.VARBINARY: case Types.LONGVARBINARY: case Types.BLOB: - return binder.toBytesArray((Iterable) null); + return binder.toBytesArray(null); } throw JdbcSqlExceptionFactory.unsupported("Unknown/unsupported array base type: " + type); } @@ -874,16 +869,16 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu private List toLongList(Number[] input) { List res = new ArrayList<>(input.length); - for (int i = 0; i < input.length; i++) { - res.add(input[i] == null ? null : input[i].longValue()); + for (Number number : input) { + res.add(number == null ? null : number.longValue()); } return res; } private List toDoubleList(Number[] input) { List res = new ArrayList<>(input.length); - for (int i = 0; i < input.length; i++) { - res.add(input[i] == null ? null : input[i].doubleValue()); + for (Number number : input) { + res.add(number == null ? null : number.doubleValue()); } return res; } @@ -892,7 +887,7 @@ private List toDoubleList(Number[] input) { * Sets a null value with a specific SQL type. If the sqlType is null, the value will be set as a * String. */ - private Builder setNullValue(ValueBinder binder, Integer sqlType) throws SQLException { + private Builder setNullValue(ValueBinder binder, Integer sqlType) { if (sqlType == null) { return binder.to((String) null); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java index a516e68b7da7..19586efe1637 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreconditions.java @@ -31,7 +31,7 @@ class JdbcPreconditions { * * @param expression the boolean expression that should be true. * @param value the parameter value that is being checked. - * @throws JdbcSqlException with {@link Code#INVALID_ARGUMENT} if {@code expression} is false + * @throws SQLException with {@link Code#INVALID_ARGUMENT} if {@code expression} is false */ static void checkArgument(boolean expression, Object value) throws SQLException { if (!expression) { @@ -46,7 +46,7 @@ static void checkArgument(boolean expression, Object value) throws SQLException * @param expression a boolean expression * @param errorMessage the exception message to use if the check fails; will be converted to a * string using {@link String#valueOf(Object)} - * @throws JdbcSqlException with {@link Code#FAILED_PRECONDITION} if {@code expression} is false + * @throws SQLException with {@link Code#FAILED_PRECONDITION} if {@code expression} is false */ static void checkState(boolean expression, @Nullable Object errorMessage) throws SQLException { if (!expression) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 919aad302cc9..a25b39c0499e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -20,7 +20,6 @@ import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; @@ -45,7 +44,7 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement { JdbcParameterStore.convertPositionalParametersToNamedParameters(sqlWithoutComments); } - ParametersInfo getParametersInfo() throws SQLException { + ParametersInfo getParametersInfo() { return parameters; } @@ -107,7 +106,7 @@ public ResultSetMetaData getMetaData() throws SQLException { // Return metadata for an empty result set as DML statements do not return any results (as a // result set). com.google.cloud.spanner.ResultSet resultSet = - ResultSets.forRows(Type.struct(), ImmutableList.of()); + ResultSets.forRows(Type.struct(), ImmutableList.of()); resultSet.next(); return new JdbcResultSetMetaData(JdbcResultSet.of(resultSet), this); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 489c2d27f045..c06c147f8146 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -99,7 +99,7 @@ public boolean next() throws SQLException { } @Override - public void close() throws SQLException { + public void close() { spanner.close(); this.closed = true; } @@ -161,15 +161,15 @@ public boolean getBoolean(int columnIndex) throws SQLException { Code type = spanner.getColumnType(spannerIndex).getCode(); switch (type) { case BOOL: - return isNull ? false : spanner.getBoolean(spannerIndex); + return !isNull && spanner.getBoolean(spannerIndex); case FLOAT64: - return isNull ? false : spanner.getDouble(spannerIndex) != 0D; + return !isNull && spanner.getDouble(spannerIndex) != 0D; case INT64: - return isNull ? false : spanner.getLong(spannerIndex) != 0L; + return !isNull && spanner.getLong(spannerIndex) != 0L; case NUMERIC: - return isNull ? false : !spanner.getBigDecimal(spannerIndex).equals(BigDecimal.ZERO); + return !isNull && !spanner.getBigDecimal(spannerIndex).equals(BigDecimal.ZERO); case STRING: - return isNull ? false : Boolean.valueOf(spanner.getString(spannerIndex)); + return !isNull && Boolean.parseBoolean(spanner.getString(spannerIndex)); case BYTES: case JSON: case DATE: @@ -591,8 +591,7 @@ private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.json()) return getString(columnIndex); if (type == Type.timestamp()) return getTimestamp(columnIndex); if (type.getCode() == Code.ARRAY) return getArray(columnIndex); - throw JdbcSqlExceptionFactory.of( - "Unknown type: " + type.toString(), com.google.rpc.Code.INVALID_ARGUMENT); + throw JdbcSqlExceptionFactory.of("Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT); } @Override @@ -737,7 +736,7 @@ public Array getArray(int columnIndex) throws SQLException { "Column with index " + columnIndex + " does not contain an array", com.google.rpc.Code.INVALID_ARGUMENT); JdbcDataType dataType = JdbcDataType.getType(type.getArrayElementType().getCode()); - List elements = dataType.getArrayElements(spanner, columnIndex - 1); + List elements = dataType.getArrayElements(spanner, columnIndex - 1); return JdbcArray.createArray(dataType, elements); } @@ -864,7 +863,7 @@ public int getHoldability() throws SQLException { } @Override - public boolean isClosed() throws SQLException { + public boolean isClosed() { return closed; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index a598b109e46d..69162e8077e0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -46,44 +46,44 @@ public boolean isClosed() { } @Override - public int getColumnCount() throws SQLException { + public int getColumnCount() { return spannerResultSet.getColumnCount(); } @Override - public boolean isAutoIncrement(int column) throws SQLException { + public boolean isAutoIncrement(int column) { return false; } @Override - public boolean isCaseSensitive(int column) throws SQLException { + public boolean isCaseSensitive(int column) { int type = getColumnType(column); return type == Types.NVARCHAR || type == Types.BINARY; } @Override - public boolean isSearchable(int column) throws SQLException { + public boolean isSearchable(int column) { return true; } @Override - public boolean isCurrency(int column) throws SQLException { + public boolean isCurrency(int column) { return false; } @Override - public int isNullable(int column) throws SQLException { + public int isNullable(int column) { return columnNullableUnknown; } @Override - public boolean isSigned(int column) throws SQLException { + public boolean isSigned(int column) { int type = getColumnType(column); return type == Types.DOUBLE || type == Types.BIGINT || type == Types.NUMERIC; } @Override - public int getColumnDisplaySize(int column) throws SQLException { + public int getColumnDisplaySize(int column) { int colType = getColumnType(column); switch (colType) { case Types.ARRAY: @@ -112,12 +112,12 @@ public int getColumnDisplaySize(int column) throws SQLException { } @Override - public String getColumnLabel(int column) throws SQLException { + public String getColumnLabel(int column) { return spannerResultSet.getType().getStructFields().get(column - 1).getName(); } @Override - public String getColumnName(int column) throws SQLException { + public String getColumnName(int column) { return spannerResultSet.getType().getStructFields().get(column - 1).getName(); } @@ -127,7 +127,7 @@ public String getSchemaName(int column) throws SQLException { } @Override - public int getPrecision(int column) throws SQLException { + public int getPrecision(int column) { int colType = getColumnType(column); switch (colType) { case Types.BOOLEAN: @@ -152,14 +152,14 @@ public int getPrecision(int column) throws SQLException { } @Override - public int getScale(int column) throws SQLException { + public int getScale(int column) { int colType = getColumnType(column); if (colType == Types.DOUBLE || colType == Types.NUMERIC) return 15; return 0; } @Override - public String getTableName(int column) throws SQLException { + public String getTableName(int column) { return ""; } @@ -169,46 +169,42 @@ public String getCatalogName(int column) throws SQLException { } @Override - public int getColumnType(int column) throws SQLException { + public int getColumnType(int column) { return extractColumnType(spannerResultSet.getColumnType(column - 1)); } @Override - public String getColumnTypeName(int column) throws SQLException { + public String getColumnTypeName(int column) { return spannerResultSet.getColumnType(column - 1).getCode().name(); } @Override - public boolean isReadOnly(int column) throws SQLException { + public boolean isReadOnly(int column) { return false; } @Override - public boolean isWritable(int column) throws SQLException { + public boolean isWritable(int column) { return !isReadOnly(column); } @Override - public boolean isDefinitelyWritable(int column) throws SQLException { + public boolean isDefinitelyWritable(int column) { return false; } @Override - public String getColumnClassName(int column) throws SQLException { + public String getColumnClassName(int column) { return getClassName(spannerResultSet.getColumnType(column - 1)); } @Override public String toString() { StringBuilder res = new StringBuilder(); - try { - for (int col = 1; col <= getColumnCount(); col++) { - res.append("Col ").append(col).append(": "); - res.append(getColumnName(col)).append(" ").append(getColumnTypeName(col)); - res.append("\n"); - } - } catch (SQLException e) { - return "An error occurred while generating string: " + e.getMessage(); + for (int col = 1; col <= getColumnCount(); col++) { + res.append("Col ").append(col).append(": "); + res.append(getColumnName(col)).append(" ").append(getColumnTypeName(col)); + res.append("\n"); } return res.toString(); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java index 33d3bb4223a8..6ddc7d683d8f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlExceptionFactory.java @@ -22,7 +22,6 @@ import com.google.cloud.spanner.SpannerException; import com.google.rpc.Code; import java.sql.BatchUpdateException; -import java.sql.ClientInfoStatus; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; @@ -89,7 +88,7 @@ public static class JdbcSqlClientInfoException extends SQLClientInfoException private final Code code; private JdbcSqlClientInfoException(String message, Code code) { - super(message, Collections.emptyMap()); + super(message, Collections.emptyMap()); this.code = code; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 5a8f69166104..3674ae02b07c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -21,7 +21,6 @@ import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.connection.StatementParser; @@ -41,7 +40,7 @@ class JdbcStatement extends AbstractJdbcStatement { enum BatchType { NONE, DML, - DDL; + DDL } private ResultSet currentResultSet; @@ -332,7 +331,7 @@ int[] convertUpdateCounts(long[] updateCounts) throws SQLException { } @VisibleForTesting - void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, long[] res) throws SQLException { + void convertUpdateCountsToSuccessNoInfo(long[] updateCounts, long[] res) { Preconditions.checkNotNull(updateCounts); Preconditions.checkNotNull(res); Preconditions.checkArgument(res.length >= updateCounts.length); @@ -355,7 +354,7 @@ public ResultSet getGeneratedKeys() throws SQLException { Type.struct( StructField.of("COLUMN_NAME", Type.string()), StructField.of("VALUE", Type.int64())), - Collections.emptyList()); + Collections.emptyList()); return JdbcResultSet.of(rs); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 4b2e4f0f7109..56043b0416be 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -25,6 +25,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.sql.Array; import java.sql.SQLException; import java.sql.Time; @@ -41,7 +42,7 @@ /** Convenience class for converting values between Java, JDBC and Cloud Spanner. */ class JdbcTypeConverter { private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ISO_OFFSET_DATE_TIME; - private static final Charset UTF8 = Charset.forName("UTF8"); + private static final Charset UTF8 = StandardCharsets.UTF_8; /** * Converts the given value from the Google {@link Type} to the Java {@link Class} type. The input @@ -86,10 +87,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx } if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; - if (type.getCode() == Code.INT64) return Boolean.valueOf((Long) value != 0); - if (type.getCode() == Code.FLOAT64) return Boolean.valueOf((Double) value != 0d); - if (type.getCode() == Code.NUMERIC) - return Boolean.valueOf(!((BigDecimal) value).equals(BigDecimal.ZERO)); + if (type.getCode() == Code.INT64) return (Long) value != 0; + if (type.getCode() == Code.FLOAT64) return (Double) value != 0d; + if (type.getCode() == Code.NUMERIC) return !value.equals(BigDecimal.ZERO); } if (targetType.equals(BigDecimal.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; @@ -223,40 +223,31 @@ private static void checkValidTypeAndValueForConvert(Type type, Object value) throws SQLException { if (value == null) return; JdbcPreconditions.checkArgument( - (type.getCode() == Code.ARRAY && Array.class.isAssignableFrom(value.getClass())) - || type.getCode() != Code.ARRAY, + type.getCode() != Code.ARRAY || Array.class.isAssignableFrom(value.getClass()), "input type is array, but input value is not an instance of java.sql.Array"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.BOOL && value.getClass().equals(Boolean.class)) - || type.getCode() != Code.BOOL, + type.getCode() != Code.BOOL || value.getClass().equals(Boolean.class), "input type is bool, but input value is not an instance of Boolean"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.BYTES && value.getClass().equals(byte[].class)) - || type.getCode() != Code.BYTES, + type.getCode() != Code.BYTES || value.getClass().equals(byte[].class), "input type is bytes, but input value is not an instance of byte[]"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.DATE && value.getClass().equals(java.sql.Date.class)) - || type.getCode() != Code.DATE, + type.getCode() != Code.DATE || value.getClass().equals(java.sql.Date.class), "input type is date, but input value is not an instance of java.sql.Date"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.FLOAT64 && value.getClass().equals(Double.class)) - || type.getCode() != Code.FLOAT64, + type.getCode() != Code.FLOAT64 || value.getClass().equals(Double.class), "input type is float64, but input value is not an instance of Double"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.INT64 && value.getClass().equals(Long.class)) - || type.getCode() != Code.INT64, + type.getCode() != Code.INT64 || value.getClass().equals(Long.class), "input type is int64, but input value is not an instance of Long"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.STRING && value.getClass().equals(String.class)) - || type.getCode() != Code.STRING, + type.getCode() != Code.STRING || value.getClass().equals(String.class), "input type is string, but input value is not an instance of String"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.TIMESTAMP && value.getClass().equals(java.sql.Timestamp.class)) - || type.getCode() != Code.TIMESTAMP, + type.getCode() != Code.TIMESTAMP || value.getClass().equals(java.sql.Timestamp.class), "input type is timestamp, but input value is not an instance of java.sql.Timestamp"); JdbcPreconditions.checkArgument( - (type.getCode() == Code.NUMERIC && value.getClass().equals(BigDecimal.class)) - || type.getCode() != Code.NUMERIC, + type.getCode() != Code.NUMERIC || value.getClass().equals(BigDecimal.class), "input type is numeric, but input value is not an instance of BigDecimal"); } @@ -280,7 +271,9 @@ static Date toGoogleDate(java.sql.Timestamp date) { static List toGoogleDates(java.sql.Date[] dates) { List res = new ArrayList<>(dates.length); - for (int index = 0; index < dates.length; index++) res.add(toGoogleDate(dates[index])); + for (java.sql.Date date : dates) { + res.add(toGoogleDate(date)); + } return res; } @@ -290,6 +283,7 @@ static java.sql.Date toSqlDate(Date date) { static java.sql.Date toSqlDate(Date date, Calendar cal) { if (date != null) { + //noinspection MagicConstant cal.set(date.getYear(), date.getMonth() - 1, date.getDayOfMonth(), 0, 0, 0); cal.clear(Calendar.MILLISECOND); return new java.sql.Date(cal.getTimeInMillis()); @@ -329,7 +323,7 @@ static java.sql.Timestamp setTimestampInCalendar(java.sql.Timestamp sqlTs, Calen private enum GetOrSetTimestampInCalendar { GET, - SET; + SET } private static java.sql.Timestamp getOrSetTimestampInCalendar( @@ -363,20 +357,10 @@ static List toSqlTimestamps(List timestamps) { return res; } - static Timestamp toGoogleTimestamp(java.sql.Date ts) { - if (ts != null) { - long milliseconds = ts.getTime(); - long seconds = milliseconds / 1000l; - long nanos = (milliseconds - (seconds * 1000)) * 1000000; - return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, (int) nanos); - } - return null; - } - - static Timestamp toGoogleTimestamp(java.sql.Time ts) { + static Timestamp toGoogleTimestamp(java.util.Date ts) { if (ts != null) { long milliseconds = ts.getTime(); - long seconds = milliseconds / 1000l; + long seconds = milliseconds / 1000L; long nanos = (milliseconds - (seconds * 1000)) * 1000000; return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, (int) nanos); } @@ -386,7 +370,7 @@ static Timestamp toGoogleTimestamp(java.sql.Time ts) { static Timestamp toGoogleTimestamp(java.sql.Timestamp ts) { if (ts != null) { long milliseconds = ts.getTime(); - long seconds = milliseconds / 1000l; + long seconds = milliseconds / 1000L; int nanos = ts.getNanos(); return com.google.cloud.Timestamp.ofTimeSecondsAndNanos(seconds, nanos); } @@ -395,8 +379,8 @@ static Timestamp toGoogleTimestamp(java.sql.Timestamp ts) { static List toGoogleTimestamps(java.sql.Timestamp[] timestamps) { List res = new ArrayList<>(timestamps.length); - for (int index = 0; index < timestamps.length; index++) { - res.add(toGoogleTimestamp(timestamps[index])); + for (java.sql.Timestamp timestamp : timestamps) { + res.add(toGoogleTimestamp(timestamp)); } return res; } @@ -429,7 +413,7 @@ static Time toSqlTime(Timestamp ts, Calendar cal) { static java.sql.Time parseSqlTime(String val, Calendar cal) { if (val != null) { Time time = Time.valueOf(val); - cal.set(1970, 0, 1, time.getHours(), time.getMinutes(), time.getSeconds()); + cal.set(1970, Calendar.JANUARY, 1, time.getHours(), time.getMinutes(), time.getSeconds()); cal.clear(Calendar.MILLISECOND); return new java.sql.Time(cal.getTimeInMillis()); } @@ -438,8 +422,8 @@ static java.sql.Time parseSqlTime(String val, Calendar cal) { static List toGoogleBytes(byte[][] bytes) { List res = new ArrayList<>(bytes.length); - for (int index = 0; index < bytes.length; index++) { - res.add(bytes[index] == null ? null : ByteArray.copyFrom(bytes[index])); + for (byte[] aByte : bytes) { + res.add(aByte == null ? null : ByteArray.copyFrom(aByte)); } return res; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java index 6d85dc7c0c8f..d837e7364dfa 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/TransactionRetryListener.java @@ -28,14 +28,14 @@ public interface TransactionRetryListener { /** Use {@link com.google.cloud.spanner.connection.TransactionRetryListener.RetryResult} */ @InternalApi @Deprecated - public enum RetryResult { + enum RetryResult { /** The retry executed successfully and the transaction will continue. */ RETRY_SUCCESSFUL, /** The retry was aborted by Spanner and another retry attempt will be started. */ RETRY_ABORTED_AND_RESTARTING, /** - * The retry was aborted by the {@link Connection} because of a concurrent modification. The - * transaction cannot continue and will throw an {@link + * The retry was aborted by the {@link java.sql.Connection} because of a concurrent + * modification. The transaction cannot continue and will throw an {@link * AbortedDueToConcurrentModificationException}. */ RETRY_ABORTED_DUE_TO_CONCURRENT_MODIFICATION, @@ -48,7 +48,7 @@ public enum RetryResult { * An unexpected error occurred during transaction retry, the transaction cannot continue and * will throw an exception. */ - RETRY_ERROR; + RETRY_ERROR } /** diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java index 53fd0e6d2b0c..e17f2b49e0ab 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSetTest.java @@ -62,7 +62,7 @@ public void setup() { } @Test - public void testFetchSize() throws SQLException { + public void testFetchSize() { assertEquals(0, rs.getFetchSize()); for (int size : new int[] {0, 1, 10, 100}) { rs.setFetchSize(size); @@ -71,24 +71,24 @@ public void testFetchSize() throws SQLException { } @Test - public void testGetType() throws SQLException { + public void testGetType() { assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType()); } @Test - public void testGetConcurrency() throws SQLException { + public void testGetConcurrency() { assertEquals(ResultSet.CONCUR_READ_ONLY, rs.getConcurrency()); } @Test - public void testRowInsertedUpdatedDeleted() throws SQLException { + public void testRowInsertedUpdatedDeleted() { assertFalse(rs.rowInserted()); assertFalse(rs.rowUpdated()); assertFalse(rs.rowDeleted()); } @Test - public void testGetFetchDirection() throws SQLException { + public void testGetFetchDirection() { assertEquals(ResultSet.FETCH_FORWARD, rs.getFetchDirection()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index 593466f754a2..3569e67c586d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -35,7 +35,7 @@ public class AbstractJdbcWrapperTest { /** Create a concrete sub class to use for testing. */ private static class TestWrapper extends AbstractJdbcWrapper { @Override - public boolean isClosed() throws SQLException { + public boolean isClosed() { return false; } } @@ -44,7 +44,7 @@ public boolean isClosed() throws SQLException { private static class SubTestWrapper extends TestWrapper {} @Test - public void testIsWrapperFor() throws SQLException { + public void testIsWrapperFor() { TestWrapper subject = new TestWrapper(); assertThat(subject.isWrapperFor(TestWrapper.class)).isTrue(); assertThat(subject.isWrapperFor(SubTestWrapper.class)).isFalse(); @@ -59,7 +59,7 @@ public void testIsWrapperFor() throws SQLException { } @Test - public void testUnwrap() throws SQLException { + public void testUnwrap() { TestWrapper subject = new TestWrapper(); assertThat(unwrapSucceeds(subject, TestWrapper.class)).isTrue(); assertThat(unwrapSucceeds(subject, SubTestWrapper.class)).isFalse(); @@ -67,12 +67,7 @@ public void testUnwrap() throws SQLException { assertThat(unwrapSucceeds(subject, getClass())).isFalse(); } - private static interface CheckedCastChecker { - boolean cast(V val); - } - - private static final class CheckedCastToByteChecker implements CheckedCastChecker { - @Override + private static final class CheckedCastToByteChecker { public boolean cast(Long val) { try { AbstractJdbcWrapper.checkedCastToByte(val); @@ -84,21 +79,20 @@ public boolean cast(Long val) { } @Test - public void testCheckedCastToByte() throws SQLException { + public void testCheckedCastToByte() { CheckedCastToByteChecker checker = new CheckedCastToByteChecker(); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Byte.MAX_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Byte.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast((long) Byte.MAX_VALUE)).isTrue(); + assertThat(checker.cast((long) Byte.MAX_VALUE + 1L)).isFalse(); assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); assertThat(checker.cast(-1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Byte.MIN_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Byte.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast((long) Byte.MIN_VALUE)).isTrue(); + assertThat(checker.cast((long) Byte.MIN_VALUE - 1L)).isFalse(); assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToShortChecker implements CheckedCastChecker { - @Override + private static final class CheckedCastToShortChecker { public boolean cast(Long val) { try { AbstractJdbcWrapper.checkedCastToShort(val); @@ -110,21 +104,20 @@ public boolean cast(Long val) { } @Test - public void testCheckedCastToShort() throws SQLException { + public void testCheckedCastToShort() { CheckedCastToShortChecker checker = new CheckedCastToShortChecker(); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Short.MAX_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Short.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast((long) Short.MAX_VALUE)).isTrue(); + assertThat(checker.cast((long) Short.MAX_VALUE + 1L)).isFalse(); assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); assertThat(checker.cast(-1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Short.MIN_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Short.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast((long) Short.MIN_VALUE)).isTrue(); + assertThat(checker.cast((long) Short.MIN_VALUE - 1L)).isFalse(); assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToIntChecker implements CheckedCastChecker { - @Override + private static final class CheckedCastToIntChecker { public boolean cast(Long val) { try { AbstractJdbcWrapper.checkedCastToInt(val); @@ -136,21 +129,20 @@ public boolean cast(Long val) { } @Test - public void testCheckedCastToInt() throws SQLException { + public void testCheckedCastToInt() { CheckedCastToIntChecker checker = new CheckedCastToIntChecker(); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Integer.MAX_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Integer.MAX_VALUE) + 1L)).isFalse(); + assertThat(checker.cast((long) Integer.MAX_VALUE)).isTrue(); + assertThat(checker.cast((long) Integer.MAX_VALUE + 1L)).isFalse(); assertThat(checker.cast(Long.MAX_VALUE)).isFalse(); assertThat(checker.cast(-1L)).isTrue(); - assertThat(checker.cast(Long.valueOf(Integer.MIN_VALUE))).isTrue(); - assertThat(checker.cast(Long.valueOf(Integer.MIN_VALUE) - 1L)).isFalse(); + assertThat(checker.cast((long) Integer.MIN_VALUE)).isTrue(); + assertThat(checker.cast((long) Integer.MIN_VALUE - 1L)).isFalse(); assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToFloatChecker implements CheckedCastChecker { - @Override + private static final class CheckedCastToFloatChecker { public boolean cast(Double val) { try { AbstractJdbcWrapper.checkedCastToFloat(val); @@ -162,16 +154,16 @@ public boolean cast(Double val) { } @Test - public void testCheckedCastToFloat() throws SQLException { + public void testCheckedCastToFloat() { CheckedCastToFloatChecker checker = new CheckedCastToFloatChecker(); assertThat(checker.cast(0D)).isTrue(); assertThat(checker.cast(1D)).isTrue(); - assertThat(checker.cast(Double.valueOf(Float.MAX_VALUE))).isTrue(); - assertThat(checker.cast(Double.valueOf(Float.MAX_VALUE) * 2.0D)).isFalse(); + assertThat(checker.cast((double) Float.MAX_VALUE)).isTrue(); + assertThat(checker.cast((double) Float.MAX_VALUE * 2.0D)).isFalse(); assertThat(checker.cast(Double.MAX_VALUE)).isFalse(); assertThat(checker.cast(-1D)).isTrue(); - assertThat(checker.cast(Double.valueOf(Float.MIN_VALUE))).isTrue(); - assertThat(checker.cast(Double.valueOf(-Float.MAX_VALUE * 2))).isFalse(); + assertThat(checker.cast((double) Float.MIN_VALUE)).isTrue(); + assertThat(checker.cast(-Float.MAX_VALUE * 2d)).isFalse(); assertThat(checker.cast(-Double.MAX_VALUE)).isFalse(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java index 9c5628399b88..b7253df82741 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcAbortedTransactionTest.java @@ -99,13 +99,9 @@ public void retryFinished( private static final int UPDATE_COUNT = 1; private static MockSpannerServiceImpl mockSpanner; - private static MockInstanceAdminImpl mockInstanceAdmin; - private static MockDatabaseAdminImpl mockDatabaseAdmin; private static Server server; - private static InetSocketAddress address; - @Parameter(0) - public boolean retryAbortsInternally; + @Parameter public boolean retryAbortsInternally; @Parameters(name = "retryAbortsInternally = {0}") public static Collection data() { @@ -121,9 +117,9 @@ public static void startStaticServer() throws IOException { mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. mockSpanner.putStatementResult(StatementResult.query(SELECT1, SELECT1_RESULTSET)); mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT)); - mockInstanceAdmin = new MockInstanceAdminImpl(); - mockDatabaseAdmin = new MockDatabaseAdminImpl(); - address = new InetSocketAddress("localhost", 0); + MockInstanceAdminImpl mockInstanceAdmin = new MockInstanceAdminImpl(); + MockDatabaseAdminImpl mockDatabaseAdmin = new MockDatabaseAdminImpl(); + InetSocketAddress address = new InetSocketAddress("localhost", 0); server = NettyServerBuilder.forAddress(address) .addService(mockSpanner) @@ -267,6 +263,7 @@ public void testTransactionalUpdateWithConcurrentModificationsAborted() throws S mockSpanner.putStatementResult( StatementResult.query(SELECT_RANDOM, new RandomResultSetGenerator(25).generate())); try (ResultSet rs = connection.createStatement().executeQuery(SELECT_RANDOM.getSql())) { + //noinspection StatementWithEmptyBody while (rs.next()) {} } // Set a new random answer that will be returned during the retry. diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 74b8354ebc4f..5888b3b40081 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -97,7 +97,7 @@ public void testCreateArrayTypeName() throws SQLException { array = JdbcArray.createArray("FLOAT64", new Double[] {1.1D, 2.2D, Math.PI}); assertThat(array.getBaseType()).isEqualTo(Types.DOUBLE); - assertThat(((Double[]) array.getArray(1, 3))[2]).isEqualTo(Double.valueOf(Math.PI)); + assertThat(((Double[]) array.getArray(1, 3))[2]).isEqualTo(Math.PI); try (ResultSet rs = array.getResultSet()) { assertThat(rs.next()).isTrue(); assertThat(rs.getDouble(2)).isEqualTo(1.1D); @@ -110,7 +110,7 @@ public void testCreateArrayTypeName() throws SQLException { array = JdbcArray.createArray("INT64", new Long[] {1L, 2L, 3L}); assertThat(array.getBaseType()).isEqualTo(Types.BIGINT); - assertThat(((Long[]) array.getArray(1, 1))[0]).isEqualTo(Long.valueOf(1L)); + assertThat(((Long[]) array.getArray(1, 1))[0]).isEqualTo(1L); try (ResultSet rs = array.getResultSet()) { assertThat(rs.next()).isTrue(); assertThat(rs.getLong(2)).isEqualTo(1L); @@ -210,7 +210,7 @@ public void testCreateArrayOfStruct() throws SQLException { .asList() .containsExactly(Struct.newBuilder().set("f1").to("v1").set("f2").to(1L).build(), null) .inOrder(); - assertThrows(SQLFeatureNotSupportedException.class, () -> array.getResultSet()); + assertThrows(SQLFeatureNotSupportedException.class, array::getResultSet); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java index 87011ab4180d..b195229180da 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; import com.google.rpc.Code; import java.io.IOException; @@ -113,20 +114,20 @@ public void testGetCharacterStream() throws SQLException, IOException { clob.setString(1L, "test"); char[] cbuf = new char[4]; try (Reader reader = clob.getCharacterStream()) { - reader.read(cbuf, 0, 4); + assertEquals(4, reader.read(cbuf, 0, 4)); } assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); try (Reader reader = clob.getCharacterStream()) { - reader.read(cbuf, 0, 2); - reader.read(cbuf, 2, 2); + assertEquals(2, reader.read(cbuf, 0, 2)); + assertEquals(2, reader.read(cbuf, 2, 2)); } assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); try (Reader reader = clob.getCharacterStream()) { - reader.read(cbuf, 0, 2); + assertEquals(2, reader.read(cbuf, 0, 2)); // changing the value of the clob will not change a character stream that has already been // opened clob.setString(1L, "foobar"); - reader.read(cbuf, 2, 2); + assertEquals(2, reader.read(cbuf, 2, 2)); } assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index b818c63fe4ea..2ec3f1b08c3c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.when; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.connection.AbstractConnectionImplTest; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.connection.ConnectionImplTest; @@ -66,6 +67,6 @@ public GenericConnection getConnection() { public void testGeneratedScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); verifier.verifyStatementsInFile( - "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class); + "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class, false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index ab503d21f8c8..3205cbb5e569 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -47,7 +47,6 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLWarning; import java.sql.Savepoint; -import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Properties; @@ -62,7 +61,7 @@ public class JdbcConnectionTest { private static final com.google.cloud.spanner.ResultSet SELECT1_RESULTSET = ResultSets.forRows( Type.struct(StructField.of("", Type.int64())), - Arrays.asList(Struct.newBuilder().set("").to(1L).build())); + Collections.singletonList(Struct.newBuilder().set("").to(1L).build())); private JdbcConnection createConnection(ConnectionOptions options) throws SQLException { com.google.cloud.spanner.connection.Connection spannerConnection = @@ -90,7 +89,7 @@ public void testAutoCommit() throws SQLException { } @Test - public void testReadOnly() throws SQLException { + public void testReadOnly() { ConnectionOptions options = mock(ConnectionOptions.class); when(options.isAutocommit()).thenReturn(true); when(options.isReadOnly()).thenReturn(true); @@ -150,11 +149,6 @@ public void testRollback() throws SQLException { } } - @Test - public void testClosedAbstractJdbcConnection() - throws SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, - IllegalArgumentException {} - @Test public void testClosedJdbcConnection() throws SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, @@ -729,7 +723,7 @@ public void testIsReturnCommitStats() throws SQLException { } @Test - public void testIsReturnCommitStats_throwsSqlException() throws SQLException { + public void testIsReturnCommitStats_throwsSqlException() { ConnectionOptions options = mock(ConnectionOptions.class); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); @@ -751,7 +745,7 @@ public void testIsReturnCommitStats_throwsSqlException() throws SQLException { } @Test - public void testSetReturnCommitStats_throwsSqlException() throws SQLException { + public void testSetReturnCommitStats_throwsSqlException() { ConnectionOptions options = mock(ConnectionOptions.class); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); @@ -774,7 +768,7 @@ public void testSetReturnCommitStats_throwsSqlException() throws SQLException { } @Test - public void testGetCommitResponse_throwsSqlException() throws SQLException { + public void testGetCommitResponse_throwsSqlException() { ConnectionOptions options = mock(ConnectionOptions.class); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java index 64ebe95562a2..c0f9473bf9a2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java @@ -17,14 +17,12 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.connection.AbstractMockServerTest; -import com.google.common.base.Predicate; -import com.google.protobuf.AbstractMessage; import com.google.spanner.v1.BatchCreateSessionsRequest; import java.sql.Connection; import java.sql.SQLException; -import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -54,13 +52,9 @@ protected String getBaseUrl() { public void testMinSessions() throws InterruptedException, TimeoutException, SQLException { try (Connection connection = createJdbcConnection()) { mockSpanner.waitForRequestsToContain( - new Predicate() { - @Override - public boolean apply(AbstractMessage input) { - return input instanceof BatchCreateSessionsRequest - && ((BatchCreateSessionsRequest) input).getSessionCount() == 1; - } - }, + input -> + input instanceof BatchCreateSessionsRequest + && ((BatchCreateSessionsRequest) input).getSessionCount() == 1, 5000L); } } @@ -88,25 +82,19 @@ public void testMaxSessions() final CountDownLatch latch = new CountDownLatch(1); Future fut1 = executor1.submit( - new Callable() { - @Override - public Void call() throws SQLException, InterruptedException { - latch.await(5L, TimeUnit.SECONDS); - connection1.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection1.commit(); - return null; - } + () -> { + assertTrue(latch.await(5L, TimeUnit.SECONDS)); + connection1.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection1.commit(); + return null; }); Future fut2 = executor2.submit( - new Callable() { - @Override - public Void call() throws SQLException { - latch.countDown(); - connection2.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection2.commit(); - return null; - } + () -> { + latch.countDown(); + connection2.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection2.commit(); + return null; }); // Wait until both finishes. fut1.get(5L, TimeUnit.SECONDS); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index e7e634a2eb0c..0d977c9959bf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -36,6 +36,7 @@ import java.sql.RowIdLifetime; import java.sql.SQLException; import java.sql.Types; +import java.util.Objects; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -105,7 +106,7 @@ public void testTrivialMethods() throws SQLException { assertThat(meta.getMaxCursorNameLength(), is(equalTo(0))); assertThat(meta.getMaxIndexLength(), is(equalTo(8000))); assertThat(meta.getMaxProcedureNameLength(), is(equalTo(0))); - assertThat(meta.getMaxRowSize(), is(equalTo(1024 * 10000000))); + assertThat(meta.getMaxRowSize(), is(equalTo(0))); assertThat(meta.getMaxSchemaNameLength(), is(equalTo(0))); assertThat(meta.getMaxStatementLength(), is(equalTo(1000000))); assertThat(meta.getMaxStatements(), is(equalTo(0))); @@ -344,6 +345,7 @@ public void testGetClientInfoProperties() throws SQLException { } } + @Test public void testGetColumnPrivileges() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); @@ -511,7 +513,8 @@ public void testGetVersionColumns() throws SQLException { public void testGetUserName() throws SQLException, IOException { GoogleCredentials credentials = GoogleCredentials.fromStream( - ConnectionOptionsTest.class.getResource("test-key.json").openStream()); + Objects.requireNonNull(ConnectionOptionsTest.class.getResource("test-key.json")) + .openStream()); JdbcConnection connection = mock(JdbcConnection.class); ConnectionOptions options = mock(ConnectionOptions.class); when(options.getCredentials()).thenReturn(credentials); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java index 0b8cd64c32aa..af7b8942b05c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java @@ -68,13 +68,12 @@ public class JdbcDatabaseMetaDataWithMockedServerTest { private static MockSpannerServiceImpl mockSpanner; private static Server server; - private static InetSocketAddress address; @BeforeClass public static void startStaticServer() throws IOException { mockSpanner = new MockSpannerServiceImpl(); mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. - address = new InetSocketAddress("localhost", 0); + InetSocketAddress address = new InetSocketAddress("localhost", 0); server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); } @@ -130,6 +129,7 @@ public void getTablesInDdlBatch() throws SQLException { // Executing an internal metadata query should be allowed during a DDL batch. // This query will be executed on a single use read-only transaction. try (ResultSet tables = connection.getMetaData().getTables("CAT", "SCH", "TAB", null)) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); @@ -159,6 +159,7 @@ public void getColumnsInDdlBatch() throws SQLException { try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("START BATCH DDL"); try (ResultSet tables = connection.getMetaData().getColumns("CAT", "SCH", "TAB", null)) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); @@ -192,12 +193,15 @@ public void getKeysInDdlBatch() throws SQLException { try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("START BATCH DDL"); try (ResultSet tables = connection.getMetaData().getPrimaryKeys("CAT", "SCH", "TAB")) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } try (ResultSet tables = connection.getMetaData().getImportedKeys("CAT", "SCH", "TAB")) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } try (ResultSet tables = connection.getMetaData().getExportedKeys("CAT", "SCH", "TAB")) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); @@ -232,6 +236,7 @@ public void getCrossReferencesInDdlBatch() throws SQLException { connection.createStatement().execute("START BATCH DDL"); try (ResultSet tables = connection.getMetaData().getCrossReference("CAT", "SCH", "TAB", "CAT2", "SCH2", "TAB2")) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); @@ -264,6 +269,7 @@ public void getIndexInfoInDdlBatch() throws SQLException { connection.createStatement().execute("START BATCH DDL"); try (ResultSet tables = connection.getMetaData().getIndexInfo("CAT", "SCH", "TAB", true, false)) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); @@ -289,9 +295,11 @@ public void getSchemasInDdlBatch() throws SQLException { try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("START BATCH DDL"); try (ResultSet tables = connection.getMetaData().getSchemas()) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } try (ResultSet tables = connection.getMetaData().getSchemas(null, null)) { + //noinspection StatementWithEmptyBody while (tables.next()) {} } connection.createStatement().execute("CREATE TABLE FOO"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index c6709b348d89..dd988ca7107d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -24,7 +24,6 @@ import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; import com.google.cloud.spanner.connection.SpannerPool; -import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.rpc.Code; @@ -37,6 +36,7 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Collection; +import java.util.Objects; import java.util.Properties; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -46,9 +46,7 @@ @RunWith(JUnit4.class) public class JdbcDriverTest { - /** - * Make sure the JDBC driver class is loaded. This is needed when running the test using Maven. - */ + // Make sure the JDBC driver class is loaded. This is needed when running the test using Maven. static { try { Class.forName("com.google.cloud.spanner.jdbc.JdbcDriver"); @@ -58,16 +56,14 @@ public class JdbcDriverTest { } } - private static MockSpannerServiceImpl mockSpanner; private static Server server; - private static InetSocketAddress address; private static final String TEST_KEY_PATH = - JdbcDriverTest.class.getResource("test-key.json").getFile(); + Objects.requireNonNull(JdbcDriverTest.class.getResource("test-key.json")).getFile(); @BeforeClass public static void startStaticServer() throws IOException { - mockSpanner = new MockSpannerServiceImpl(); - address = new InetSocketAddress("localhost", 0); + MockSpannerServiceImpl mockSpanner = new MockSpannerServiceImpl(); + InetSocketAddress address = new InetSocketAddress("localhost", 0); server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); } @@ -128,7 +124,7 @@ public void testInvalidConnect() throws SQLException { } @Test - public void testConnectWithCredentialsAndOAuthToken() throws SQLException { + public void testConnectWithCredentialsAndOAuthToken() { try (Connection connection = DriverManager.getConnection( String.format( @@ -149,23 +145,9 @@ public void testGetPropertyInfo() throws SQLException { assertThat(props).hasLength(ConnectionOptions.VALID_PROPERTIES.size()); Collection validConnectionPropertyNames = - Collections2.transform( - ConnectionOptions.VALID_PROPERTIES, - new Function() { - @Override - public String apply(ConnectionProperty input) { - return input.getName(); - } - }); + Collections2.transform(ConnectionOptions.VALID_PROPERTIES, ConnectionProperty::getName); Collection driverPropertyNames = - Collections2.transform( - ImmutableList.copyOf(props), - new Function() { - @Override - public String apply(DriverPropertyInfo input) { - return input.name; - } - }); + Collections2.transform(ImmutableList.copyOf(props), input -> input.name); assertThat(driverPropertyNames).containsExactlyElementsIn(validConnectionPropertyNames); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 51e9ab07bbcb..0668f88fa9b0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -80,10 +80,7 @@ public class JdbcGrpcErrorTest { Statement.of("UPDATE NON_EXISING_TABLE SET FOO=1 WHERE BAR=2"); private static MockSpannerServiceImpl mockSpanner; - private static MockInstanceAdminImpl mockInstanceAdmin; - private static MockDatabaseAdminImpl mockDatabaseAdmin; private static Server server; - private static InetSocketAddress address; // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. private final Exception serverException = @@ -102,9 +99,9 @@ public static void startStaticServer() throws IOException { StatementResult.exception( INVALID_UPDATE_STATEMENT, Status.NOT_FOUND.withDescription("Unknown table name").asRuntimeException())); - mockInstanceAdmin = new MockInstanceAdminImpl(); - mockDatabaseAdmin = new MockDatabaseAdminImpl(); - address = new InetSocketAddress("localhost", 0); + MockInstanceAdminImpl mockInstanceAdmin = new MockInstanceAdminImpl(); + MockDatabaseAdminImpl mockDatabaseAdmin = new MockDatabaseAdminImpl(); + InetSocketAddress address = new InetSocketAddress("localhost", 0); server = NettyServerBuilder.forAddress(address) .addService(mockSpanner) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 9d12b1b05a05..89f4ae4cf8d6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -53,11 +53,7 @@ @RunWith(JUnit4.class) public class JdbcParameterStoreTest { - /** - * Tests setting a {@link Value} as a parameter value. - * - * @throws SQLException - */ + /** Tests setting a {@link Value} as a parameter value. */ @Test public void testSetValueAsParameter() throws SQLException { JdbcParameterStore params = new JdbcParameterStore(); @@ -130,10 +126,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, Types.FLOAT); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, Types.DOUBLE); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, new Date(1970 - 1900, 0, 1), Types.DATE); assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); @@ -208,10 +204,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, type); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.int64(1)); params.setParameter(1, (double) 1, type); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.int64(1)); params.setParameter(1, BigDecimal.ONE, type); assertEquals(BigDecimal.ONE, params.getParameter(1)); @@ -233,10 +229,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.float64(1)); params.setParameter(1, (float) 1, type); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, type); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, BigDecimal.ONE, type); assertEquals(BigDecimal.ONE, params.getParameter(1)); @@ -332,10 +328,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.bool(true)); params.setParameter(1, (float) 1, type); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.bool(true)); params.setParameter(1, (double) 1, type); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.bool(true)); params.setParameter(1, BigDecimal.ZERO, type); assertEquals(BigDecimal.ZERO, params.getParameter(1)); @@ -361,10 +357,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.numeric(BigDecimal.ONE)); params.setParameter(1, (float) 1, type); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); params.setParameter(1, (double) 1, type); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); } } @@ -502,10 +498,10 @@ public void testSetParameterWithoutType() throws SQLException { assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); params.setParameter(1, (float) 1, (Integer) null); - assertEquals(1.0f, ((Float) params.getParameter(1)).floatValue(), 0.0f); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); verifyParameter(params, Value.float64(1)); params.setParameter(1, (double) 1, (Integer) null); - assertEquals(1.0d, ((Double) params.getParameter(1)).doubleValue(), 0.0d); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.float64(1)); params.setParameter(1, new Date(1970 - 1900, 0, 1), (Integer) null); assertEquals(new Date(1970 - 1900, 0, 1), params.getParameter(1)); @@ -618,7 +614,8 @@ public void testSetArrayParameter() throws SQLException { assertEquals(JdbcArray.createArray("DATE", new Date[] {sqlDate}), params.getParameter(1)); verifyParameter( params, - Value.dateArray(Arrays.asList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14)))); + Value.dateArray( + Collections.singletonList(com.google.cloud.Date.fromYearMonthDay(2018, 12, 14)))); params.setParameter(1, JdbcArray.createArray("DATE", new Date[] {sqlDate, null}), Types.ARRAY); assertEquals(JdbcArray.createArray("DATE", new Date[] {sqlDate, null}), params.getParameter(1)); @@ -636,7 +633,9 @@ public void testSetArrayParameter() throws SQLException { assertEquals( JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp}), params.getParameter(1)); verifyParameter( - params, Value.timestampArray(Arrays.asList(com.google.cloud.Timestamp.of(sqlTimestamp)))); + params, + Value.timestampArray( + Collections.singletonList(com.google.cloud.Timestamp.of(sqlTimestamp)))); params.setParameter( 1, JdbcArray.createArray("TIMESTAMP", new Timestamp[] {sqlTimestamp, null}), Types.ARRAY); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 8bb6ef4cbeba..fdc9969cb409 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -44,15 +44,11 @@ import java.sql.Date; import java.sql.JDBCType; import java.sql.PreparedStatement; -import java.sql.Ref; import java.sql.ResultSetMetaData; -import java.sql.RowId; import java.sql.SQLException; -import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; -import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.TimeZone; @@ -149,33 +145,33 @@ public void testParameters() throws SQLException, MalformedURLException { 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); - ps.setAsciiStream(4, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setAsciiStream(4, new ByteArrayInputStream("TEST".getBytes()), 4L); ps.setBinaryStream(6, new ByteArrayInputStream("TEST".getBytes())); ps.setBinaryStream(7, new ByteArrayInputStream("TEST".getBytes()), 4); - ps.setBinaryStream(8, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setBinaryStream(8, new ByteArrayInputStream("TEST".getBytes()), 4L); ps.setBlob(9, connection.createBlob()); ps.setBlob(10, new ByteArrayInputStream("TEST".getBytes())); - ps.setBlob(11, new ByteArrayInputStream("TEST".getBytes()), 4l); + ps.setBlob(11, new ByteArrayInputStream("TEST".getBytes()), 4L); ps.setBoolean(12, Boolean.TRUE); ps.setByte(13, (byte) 1); ps.setBytes(14, "TEST".getBytes()); ps.setCharacterStream(15, new StringReader("TEST")); ps.setCharacterStream(16, new StringReader("TEST"), 4); - ps.setCharacterStream(17, new StringReader("TEST"), 4l); + ps.setCharacterStream(17, new StringReader("TEST"), 4L); ps.setClob(18, connection.createClob()); ps.setClob(19, new StringReader("TEST")); - ps.setClob(20, new StringReader("TEST"), 4l); - ps.setDate(21, new Date(1000l)); - ps.setDate(22, new Date(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setClob(20, new StringReader("TEST"), 4L); + ps.setDate(21, new Date(1000L)); + ps.setDate(22, new Date(1000L), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); ps.setDouble(23, 1d); ps.setFloat(24, 1f); ps.setInt(25, 1); - ps.setLong(26, 1l); + ps.setLong(26, 1L); ps.setNCharacterStream(27, new StringReader("TEST")); - ps.setNCharacterStream(28, new StringReader("TEST"), 4l); + ps.setNCharacterStream(28, new StringReader("TEST"), 4L); ps.setNClob(29, connection.createNClob()); ps.setNClob(30, new StringReader("TEST")); - ps.setNClob(31, new StringReader("TEST"), 4l); + ps.setNClob(31, new StringReader("TEST"), 4L); ps.setNString(32, "TEST"); ps.setNull(33, Types.BIGINT); ps.setNull(34, Types.BIGINT, "INT64"); @@ -184,10 +180,10 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setObject(37, "TEST", Types.NVARCHAR, 20); ps.setShort(40, (short) 1); ps.setString(42, "TEST"); - ps.setTime(43, new Time(1000l)); - ps.setTime(44, new Time(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); - ps.setTimestamp(45, new Timestamp(1000l)); - ps.setTimestamp(46, new Timestamp(1000l), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setTime(43, new Time(1000L)); + ps.setTime(44, new Time(1000L), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); + ps.setTimestamp(45, new Timestamp(1000L)); + ps.setTimestamp(46, new Timestamp(1000L), Calendar.getInstance(TimeZone.getTimeZone("GMT"))); ps.setUnicodeStream(47, new ByteArrayInputStream("TEST".getBytes()), 4); ps.setURL(48, new URL("https://spanner.google.com")); ps.setObject(49, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e")); @@ -257,21 +253,21 @@ public void testParameters() throws SQLException, MalformedURLException { private void testSetUnsupportedTypes(PreparedStatement ps) { try { - ps.setRef(38, (Ref) null); + 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, (RowId) null); + 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, (SQLXML) null); + ps.setSQLXML(41, null); fail("missing expected exception"); } catch (SQLException e) { assertTrue(e instanceof JdbcSqlException); @@ -334,7 +330,7 @@ public void testGetResultSetMetadata() throws SQLException { StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string()), StructField.of("AMOUNT", Type.float64())), - Arrays.asList( + Collections.singletonList( Struct.newBuilder() .set("ID") .to(1L) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java index 3f36f0001420..9da17d7dbec3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java @@ -51,7 +51,6 @@ public class JdbcPreparedStatementWithMockedServerTest { private static MockSpannerServiceImpl mockSpanner; private static Server server; - private static InetSocketAddress address; @Parameter public boolean executeLarge; @@ -64,7 +63,7 @@ public static Collection data() { public static void startStaticServer() throws IOException { mockSpanner = new MockSpannerServiceImpl(); mockSpanner.setAbortProbability(0.0D); - address = new InetSocketAddress("localhost", 0); + InetSocketAddress address = new InetSocketAddress("localhost", 0); server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java index b3fcffcf1fa8..559ad2935888 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -49,7 +49,6 @@ @RunWith(JUnit4.class) public class JdbcResultSetMetaDataTest { private JdbcResultSetMetaData subject; - private java.sql.Connection connection; private static class TestColumn { private final Type type; @@ -57,7 +56,7 @@ private static class TestColumn { private final int defaultSize; private final boolean calculated; - private TestColumn(Type type, String name, Integer nulls, int size, boolean calculated) { + private TestColumn(Type type, String name, Integer nulls, boolean calculated) { Preconditions.checkNotNull(type); Preconditions.checkNotNull(name); Preconditions.checkNotNull(nulls); @@ -87,7 +86,6 @@ private static class Builder { private Type type; private String name; private Integer nulls; - private int size = 0; private boolean calculated = false; public static Builder getBuilder() { @@ -95,7 +93,7 @@ public static Builder getBuilder() { } private TestColumn build() { - return new TestColumn(type, name, nulls, size, calculated); + return new TestColumn(type, name, nulls, calculated); } private Builder withType(Type type) { @@ -123,13 +121,8 @@ private Builder withNullableUnknown() { return this; } - private Builder withSize(int size) { - this.size = size; - return this; - } - - private Builder withCalculated(boolean calculated) { - this.calculated = calculated; + private Builder withCalculated() { + this.calculated = true; return this; } } @@ -139,7 +132,7 @@ private Builder withCalculated(boolean calculated) { @Before public void setup() throws SQLException { - connection = mock(java.sql.Connection.class); + java.sql.Connection connection = mock(java.sql.Connection.class); Statement statement = mock(Statement.class); JdbcResultSet resultSet = getFooTestResultSet(statement); when(connection.getSchema()).thenReturn(""); @@ -154,27 +147,27 @@ private static List createTestColumns() { int index = 1; for (Type type : getAllTypes()) { TestColumn.Builder builder = TestColumn.Builder.getBuilder(); - builder.withName("COL" + index).withType(type).withSize(getDefaultSize(type)); - if (index % 2 == 1) builder.withNotNull(); - else builder.withNullable(); + builder.withName("COL" + index).withType(type); + if (index % 2 == 1) { + builder.withNotNull(); + } else { + builder.withNullable(); + } res.add(builder.build()); index++; } TestColumn.Builder builder = TestColumn.Builder.getBuilder(); - builder - .withName("CALCULATED") - .withType(Type.int64()) - .withNullableUnknown() - .withCalculated(true); - res.add(builder.build()); + TestColumn column = + builder + .withName("CALCULATED") + .withType(Type.int64()) + .withNullableUnknown() + .withCalculated() + .build(); + res.add(column); return res; } - private static int getDefaultSize(Type type) { - if (type == Type.string()) return 100; - return 0; - } - private static List getAllTypes() { List types = new ArrayList<>(); types.add(Type.bool()); @@ -194,7 +187,7 @@ private static List getAllTypes() { return types; } - private JdbcResultSet getFooTestResultSet(Statement statement) throws SQLException { + private JdbcResultSet getFooTestResultSet(Statement statement) { List rows = new ArrayList<>(4); for (int row = 1; row <= 4; row++) { Struct.Builder builder = Struct.newBuilder(); @@ -254,19 +247,19 @@ private Value getDefaultValue(Type type, int row) { } @Test - public void testGetColumnCount() throws SQLException { + public void testGetColumnCount() { assertEquals(TEST_COLUMNS.size(), subject.getColumnCount()); } @Test - public void testIsAutoIncrement() throws SQLException { + public void testIsAutoIncrement() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { - assertEquals(false, subject.isAutoIncrement(i)); + assertFalse(subject.isAutoIncrement(i)); } } @Test - public void testIsCaseSensitive() throws SQLException { + public void testIsCaseSensitive() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { Type type = TEST_COLUMNS.get(i - 1).type; assertEquals( @@ -276,28 +269,28 @@ public void testIsCaseSensitive() throws SQLException { } @Test - public void testIsSearchable() throws SQLException { + public void testIsSearchable() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { - assertEquals(true, subject.isSearchable(i)); + assertTrue(subject.isSearchable(i)); } } @Test - public void testIsCurrency() throws SQLException { + public void testIsCurrency() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { - assertEquals(false, subject.isCurrency(i)); + assertFalse(subject.isCurrency(i)); } } @Test - public void testIsNullable() throws SQLException { + public void testIsNullable() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(ResultSetMetaData.columnNullableUnknown, subject.isNullable(i)); } } @Test - public void testIsSigned() throws SQLException { + public void testIsSigned() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { Type type = TEST_COLUMNS.get(i - 1).type; if (type == Type.int64() || type == Type.float64()) { @@ -309,14 +302,14 @@ public void testIsSigned() throws SQLException { } @Test - public void testGetColumnDisplaySize() throws SQLException { + public void testGetColumnDisplaySize() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals( getDefaultDisplaySize(TEST_COLUMNS.get(i - 1).type, i), subject.getColumnDisplaySize(i)); } } - private int getDefaultDisplaySize(Type type, int column) throws SQLException { + private int getDefaultDisplaySize(Type type, int column) { if (type.getCode() == Code.ARRAY) return 50; if (type == Type.bool()) return 5; if (type == Type.bytes()) return 50; @@ -333,14 +326,14 @@ private int getDefaultDisplaySize(Type type, int column) throws SQLException { } @Test - public void testGetColumnLabel() throws SQLException { + public void testGetColumnLabel() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(TEST_COLUMNS.get(i - 1).name, subject.getColumnLabel(i)); } } @Test - public void testGetColumnName() throws SQLException { + public void testGetColumnName() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(TEST_COLUMNS.get(i - 1).name, subject.getColumnName(i)); } @@ -352,7 +345,7 @@ public void testGetSchemaName() throws SQLException { } @Test - public void testGetPrecision() throws SQLException { + public void testGetPrecision() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(getPrecision(TEST_COLUMNS.get(i - 1)), subject.getPrecision(i)); } @@ -369,7 +362,7 @@ private int getPrecision(TestColumn col) { } @Test - public void testGetScale() throws SQLException { + public void testGetScale() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(getScale(TEST_COLUMNS.get(i - 1)), subject.getScale(i)); } @@ -381,7 +374,7 @@ private int getScale(TestColumn col) { } @Test - public void testGetTableName() throws SQLException { + public void testGetTableName() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals("", subject.getTableName(i)); } @@ -393,7 +386,7 @@ public void testGetCatalogName() throws SQLException { } @Test - public void testGetColumnType() throws SQLException { + public void testGetColumnType() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(getSqlType(TEST_COLUMNS.get(i - 1).type), subject.getColumnType(i)); } @@ -413,7 +406,7 @@ private int getSqlType(Type type) { } @Test - public void getColumnTypeName() throws SQLException { + public void getColumnTypeName() { int index = 1; for (TestColumn col : TEST_COLUMNS) { assertEquals(col.type.getCode().name(), subject.getColumnTypeName(index)); @@ -422,28 +415,28 @@ public void getColumnTypeName() throws SQLException { } @Test - public void testIsReadOnly() throws SQLException { + public void testIsReadOnly() { for (int i = 0; i < TEST_COLUMNS.size(); i++) { assertFalse(subject.isReadOnly(i)); } } @Test - public void testIsWritable() throws SQLException { + public void testIsWritable() { for (int i = 0; i < TEST_COLUMNS.size(); i++) { assertTrue(subject.isWritable(i)); } } @Test - public void testIsDefinitelyWritable() throws SQLException { + public void testIsDefinitelyWritable() { for (int i = 0; i < TEST_COLUMNS.size(); i++) { assertFalse(subject.isDefinitelyWritable(i)); } } @Test - public void testGetColumnClassName() throws SQLException { + public void testGetColumnClassName() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals(getTypeClassName(TEST_COLUMNS.get(i - 1).type), subject.getColumnClassName(i)); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 506992c47309..7ed85ef89ccc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -157,7 +157,7 @@ public class JdbcResultSetTest { private static final String JSON_ARRAY_COL = "JSON_ARRAY"; private static final List JSON_ARRAY_VALUE = Arrays.asList(JSON_VALUE, null); - private JdbcResultSet subject; + private final JdbcResultSet subject; static ResultSet getMockResultSet() { return ResultSets.forRows( @@ -199,7 +199,7 @@ static ResultSet getMockResultSet() { StructField.of(JSON_ARRAY_COL, Type.array(Type.json())), StructField.of(STRING_ARRAY_COL, Type.array(Type.string())), StructField.of(TIMESTAMP_ARRAY_COL, Type.array(Type.timestamp()))), - Arrays.asList( + Collections.singletonList( Struct.newBuilder() .set(STRING_COL_NULL) .to((String) null) @@ -402,7 +402,7 @@ public void testGetStringIndexForTimestamp() throws SQLException { } @Test - public void testGetStringIndexForArray() throws SQLException { + public void testGetStringIndexForArray() { try { subject.getString(ARRAY_COLINDEX_NOTNULL); fail("missing SQLException"); @@ -414,7 +414,7 @@ public void testGetStringIndexForArray() throws SQLException { } @Test - public void testGetStringIndexForNullArray() throws SQLException { + public void testGetStringIndexForNullArray() { try { subject.getString(ARRAY_COLINDEX_NULL); fail("missing SQLException"); @@ -461,7 +461,7 @@ public void testGetURLIndexInvalid() throws SQLException { @Test public void testGetBooleanIndex() throws SQLException { - assertNotNull(subject.getBoolean(BOOLEAN_COLINDEX_NOTNULL)); + assertTrue(subject.getBoolean(BOOLEAN_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertFalse(subject.getBoolean(BOOLEAN_COLINDEX_NULL)); assertTrue(subject.wasNull()); @@ -469,7 +469,7 @@ public void testGetBooleanIndex() throws SQLException { @Test public void testGetBooleanIndexForLong() throws SQLException { - assertNotNull(subject.getBoolean(LONG_COLINDEX_NOTNULL)); + assertTrue(subject.getBoolean(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertFalse(subject.getBoolean(LONG_COLINDEX_NULL)); assertTrue(subject.wasNull()); @@ -477,7 +477,7 @@ public void testGetBooleanIndexForLong() throws SQLException { @Test public void testGetBooleanIndexForDouble() throws SQLException { - assertNotNull(subject.getBoolean(DOUBLE_COLINDEX_NOTNULL)); + assertTrue(subject.getBoolean(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertFalse(subject.getBoolean(DOUBLE_COLINDEX_NULL)); assertTrue(subject.wasNull()); @@ -485,14 +485,14 @@ public void testGetBooleanIndexForDouble() throws SQLException { @Test public void testGetBooleanIndexForString() throws SQLException { - assertNotNull(subject.getBoolean(STRING_COLINDEX_NOTNULL)); + assertFalse(subject.getBoolean(STRING_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertFalse(subject.getBoolean(STRING_COLINDEX_NULL)); assertTrue(subject.wasNull()); } @Test - public void testGetBooleanIndexForDate() throws SQLException { + public void testGetBooleanIndexForDate() { try { subject.getBoolean(DATE_COLINDEX_NOTNULL); fail("missing expected SQLException"); @@ -521,7 +521,7 @@ public void testGetNullBooleanIndex() throws SQLException { @Test public void testGetLongIndex() throws SQLException { - assertNotNull(subject.getLong(LONG_COLINDEX_NOTNULL)); + assertEquals(1L, subject.getLong(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getLong(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertEquals(0L, subject.getLong(LONG_COLINDEX_NULL)); @@ -530,7 +530,7 @@ public void testGetLongIndex() throws SQLException { @Test public void testGetLongIndexForBool() throws SQLException { - assertNotNull(subject.getLong(BOOLEAN_COLINDEX_NOTNULL)); + assertEquals(1L, subject.getLong(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1L : 0L, subject.getLong(BOOLEAN_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertEquals(0L, subject.getLong(BOOLEAN_COLINDEX_NULL)); @@ -539,7 +539,7 @@ public void testGetLongIndexForBool() throws SQLException { @Test public void testGetLongIndexForFloat64() throws SQLException { - assertNotNull(subject.getLong(DOUBLE_COLINDEX_NOTNULL)); + assertEquals(3L, subject.getLong(DOUBLE_COLINDEX_NOTNULL)); assertEquals((long) DOUBLE_VALUE, subject.getLong(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertEquals(0L, subject.getLong(DOUBLE_COLINDEX_NULL)); @@ -547,7 +547,7 @@ public void testGetLongIndexForFloat64() throws SQLException { } @Test - public void testGetLongIndexForString() throws SQLException { + public void testGetLongIndexForString() { try { subject.getLong(STRING_COLINDEX_NOTNULL); fail("missing expected SQLException"); @@ -571,7 +571,7 @@ public void testGetLongIndexForNullString() throws SQLException { } @Test - public void testGetLongIndexForTimestamp() throws SQLException { + public void testGetLongIndexForTimestamp() { try { subject.getLong(TIMESTAMP_COLINDEX_NOTNULL); fail("missing expected SQLException"); @@ -583,7 +583,6 @@ public void testGetLongIndexForTimestamp() throws SQLException { @Test public void testGetDoubleIndex() throws SQLException { - assertNotNull(subject.getDouble(DOUBLE_COLINDEX_NOTNULL)); assertEquals(DOUBLE_VALUE, subject.getDouble(DOUBLE_COLINDEX_NOTNULL), 0d); assertFalse(subject.wasNull()); assertEquals(0d, subject.getDouble(DOUBLE_COLINDEX_NULL), 0d); @@ -592,11 +591,8 @@ public void testGetDoubleIndex() throws SQLException { @Test public void testGetDoubleIndexFromString() throws SQLException { - assertNotNull(subject.getDouble(STRING_COLINDEX_NUMBER)); assertEquals( - Double.valueOf(STRING_NUMBER_VALUE).doubleValue(), - subject.getDouble(STRING_COLINDEX_NUMBER), - 0d); + Double.parseDouble(STRING_NUMBER_VALUE), subject.getDouble(STRING_COLINDEX_NUMBER), 0d); assertFalse(subject.wasNull()); assertEquals(0d, subject.getDouble(STRING_COLINDEX_NULL), 0d); assertTrue(subject.wasNull()); @@ -604,7 +600,6 @@ public void testGetDoubleIndexFromString() throws SQLException { @Test public void testGetDoubleIndexFromBool() throws SQLException { - assertNotNull(subject.getDouble(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1d : 0d, subject.getDouble(BOOLEAN_COLINDEX_NOTNULL), 0d); assertFalse(subject.wasNull()); assertEquals(0d, subject.getDouble(BOOLEAN_COLINDEX_NULL), 0d); @@ -613,7 +608,6 @@ public void testGetDoubleIndexFromBool() throws SQLException { @Test public void testGetDoubleIndexFromInt64() throws SQLException { - assertNotNull(subject.getDouble(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getDouble(LONG_COLINDEX_NOTNULL), 0d); assertFalse(subject.wasNull()); assertEquals(0d, subject.getDouble(LONG_COLINDEX_NULL), 0d); @@ -621,7 +615,7 @@ public void testGetDoubleIndexFromInt64() throws SQLException { } @Test - public void testGetDoubleIndexFromTimestamp() throws SQLException { + public void testGetDoubleIndexFromTimestamp() { try { subject.getDouble(TIMESTAMP_COLINDEX_NULL); fail("missing expected SQLException"); @@ -800,7 +794,7 @@ public void testGetURLLabelInvalid() throws SQLException { @Test public void testGetBooleanLabel() throws SQLException { - assertNotNull(subject.getBoolean(BOOLEAN_COL_NOT_NULL)); + assertTrue(subject.getBoolean(BOOLEAN_COL_NOT_NULL)); assertFalse(subject.wasNull()); assertFalse(subject.getBoolean(BOOLEAN_COL_NULL)); assertTrue(subject.wasNull()); @@ -808,16 +802,14 @@ public void testGetBooleanLabel() throws SQLException { @Test public void testGetLongLabel() throws SQLException { - assertNotNull(subject.getLong(LONG_COL_NOT_NULL)); - assertEquals(1l, subject.getLong(LONG_COL_NOT_NULL)); + assertEquals(1L, subject.getLong(LONG_COL_NOT_NULL)); assertFalse(subject.wasNull()); - assertEquals(0l, subject.getLong(LONG_COL_NULL)); + assertEquals(0L, subject.getLong(LONG_COL_NULL)); assertTrue(subject.wasNull()); } @Test public void testGetDoubleLabel() throws SQLException { - assertNotNull(subject.getDouble(DOUBLE_COL_NOT_NULL)); assertEquals(DOUBLE_VALUE, subject.getDouble(DOUBLE_COL_NOT_NULL), 0d); assertFalse(subject.wasNull()); assertEquals(0d, subject.getDouble(DOUBLE_COL_NULL), 0d); @@ -970,6 +962,7 @@ public void testGetDateIndexCalendar() throws SQLException { Calendar calGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT")); Calendar expectedCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); expectedCal.clear(); + //noinspection MagicConstant expectedCal.set(DATE_VALUE.getYear(), DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()); java.sql.Date expected = new java.sql.Date(expectedCal.getTimeInMillis()); assertEquals(expected, subject.getDate(DATE_COLINDEX_NOTNULL, calGMT)); @@ -990,6 +983,7 @@ public void testGetDateLabelCalendar() throws SQLException { Calendar calGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT")); Calendar expected = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + //noinspection MagicConstant expected.set( DATE_VALUE.getYear(), DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth(), 0, 0, 0); expected.clear(Calendar.MILLISECOND); @@ -1053,8 +1047,7 @@ public void testGetTimestampIndexCalendarFromDate() throws SQLException { assertNotNull(subject.getTimestamp(DATE_COLINDEX_NOTNULL, cal)); assertEquals( - Timestamp.parseTimestamp(String.format("%sT00:00:00-08:00", DATE_VALUE.toString())) - .toSqlTimestamp(), + Timestamp.parseTimestamp(String.format("%sT00:00:00-08:00", DATE_VALUE)).toSqlTimestamp(), subject.getTimestamp(DATE_COLINDEX_NOTNULL, cal)); assertFalse(subject.wasNull()); assertNull(subject.getTimestamp(DATE_COLINDEX_NULL, cal)); @@ -1074,7 +1067,7 @@ public void testGetTimestampLabelCalendar() throws SQLException { } @Test - public void testIsClosed() throws SQLException { + public void testIsClosed() { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { assertFalse(rs.isClosed()); rs.close(); @@ -1084,7 +1077,6 @@ public void testIsClosed() throws SQLException { @Test public void testGetByteIndex() throws SQLException { - assertNotNull(subject.getByte(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getByte(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertEquals(0, subject.getByte(LONG_COLINDEX_NULL)); @@ -1093,7 +1085,6 @@ public void testGetByteIndex() throws SQLException { @Test public void testGetByteIndexFromString() throws SQLException { - assertNotNull(subject.getByte(STRING_COLINDEX_NUMBER)); assertEquals( Byte.valueOf(STRING_NUMBER_VALUE).byteValue(), subject.getByte(STRING_COLINDEX_NUMBER)); assertFalse(subject.wasNull()); @@ -1101,14 +1092,12 @@ public void testGetByteIndexFromString() throws SQLException { @Test public void testGetByteIndexFromDouble() throws SQLException { - assertNotNull(subject.getByte(DOUBLE_COLINDEX_NOTNULL)); assertEquals((byte) DOUBLE_VALUE, subject.getByte(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @Test public void testGetByteIndexFromBoolean() throws SQLException { - assertNotNull(subject.getByte(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getByte(BOOLEAN_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @@ -1134,7 +1123,6 @@ public void testGetNullByteIndex() throws SQLException { @Test public void testGetShortIndex() throws SQLException { - assertNotNull(subject.getShort(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getShort(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); assertEquals(0, subject.getShort(LONG_COLINDEX_NULL)); @@ -1143,7 +1131,6 @@ public void testGetShortIndex() throws SQLException { @Test public void testGetShortIndexFromString() throws SQLException { - assertNotNull(subject.getShort(STRING_COLINDEX_NUMBER)); assertEquals( Short.valueOf(STRING_NUMBER_VALUE).shortValue(), subject.getShort(STRING_COLINDEX_NUMBER)); assertFalse(subject.wasNull()); @@ -1151,20 +1138,18 @@ public void testGetShortIndexFromString() throws SQLException { @Test public void testGetShortIndexFromDouble() throws SQLException { - assertNotNull(subject.getShort(DOUBLE_COLINDEX_NOTNULL)); assertEquals((short) DOUBLE_VALUE, subject.getShort(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @Test public void testGetShortIndexFromBoolean() throws SQLException { - assertNotNull(subject.getShort(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getShort(BOOLEAN_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @Test - public void testGetShortIndexFromBytes() throws SQLException { + public void testGetShortIndexFromBytes() { try { subject.getShort(BYTES_COL_NULL); fail("missing expected SQLException"); @@ -1195,7 +1180,6 @@ public void testGetNullShortIndex() throws SQLException { @Test public void testGetIntIndex() throws SQLException { - assertNotNull(subject.getInt(LONG_COLINDEX_NOTNULL)); int expected = (int) LONG_VALUE; assertEquals(expected, subject.getInt(LONG_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); @@ -1205,7 +1189,6 @@ public void testGetIntIndex() throws SQLException { @Test public void testGetIntIndexFromString() throws SQLException { - assertNotNull(subject.getInt(STRING_COLINDEX_NUMBER)); assertEquals( Integer.valueOf(STRING_NUMBER_VALUE).intValue(), subject.getInt(STRING_COLINDEX_NUMBER)); assertFalse(subject.wasNull()); @@ -1213,20 +1196,18 @@ public void testGetIntIndexFromString() throws SQLException { @Test public void testGetIntIndexFromDouble() throws SQLException { - assertNotNull(subject.getInt(DOUBLE_COLINDEX_NOTNULL)); assertEquals((int) DOUBLE_VALUE, subject.getInt(DOUBLE_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @Test public void testGetIntIndexFromBoolean() throws SQLException { - assertNotNull(subject.getInt(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1 : 0, subject.getInt(BOOLEAN_COLINDEX_NOTNULL)); assertFalse(subject.wasNull()); } @Test - public void testGetIntIndexFromTimestamp() throws SQLException { + public void testGetIntIndexFromTimestamp() { try { subject.getInt(TIMESTAMP_COL_NULL); fail("missing expected SQLException"); @@ -1257,7 +1238,6 @@ public void testGetNullIntIndex() throws SQLException { @Test public void testGetFloatIndex() throws SQLException { - assertNotNull(subject.getFloat(DOUBLE_COLINDEX_NOTNULL)); float expected = (float) DOUBLE_VALUE; assertEquals(expected, subject.getFloat(DOUBLE_COLINDEX_NOTNULL), 0f); assertFalse(subject.wasNull()); @@ -1267,11 +1247,8 @@ public void testGetFloatIndex() throws SQLException { @Test public void testGetFloatIndexFromString() throws SQLException { - assertNotNull(subject.getFloat(STRING_COLINDEX_NUMBER)); assertEquals( - Float.valueOf(STRING_NUMBER_VALUE).floatValue(), - subject.getFloat(STRING_COLINDEX_NUMBER), - 0f); + Float.parseFloat(STRING_NUMBER_VALUE), subject.getFloat(STRING_COLINDEX_NUMBER), 0f); assertFalse(subject.wasNull()); assertEquals(0f, subject.getFloat(STRING_COLINDEX_NULL), 0f); assertTrue(subject.wasNull()); @@ -1279,7 +1256,6 @@ public void testGetFloatIndexFromString() throws SQLException { @Test public void testGetFloatIndexFromBool() throws SQLException { - assertNotNull(subject.getFloat(BOOLEAN_COLINDEX_NOTNULL)); assertEquals(BOOLEAN_VALUE ? 1f : 0f, subject.getFloat(BOOLEAN_COLINDEX_NOTNULL), 0f); assertFalse(subject.wasNull()); assertEquals(0f, subject.getFloat(BOOLEAN_COLINDEX_NULL), 0f); @@ -1288,7 +1264,6 @@ public void testGetFloatIndexFromBool() throws SQLException { @Test public void testGetFloatIndexFromInt64() throws SQLException { - assertNotNull(subject.getFloat(LONG_COLINDEX_NOTNULL)); assertEquals(LONG_VALUE, subject.getFloat(LONG_COLINDEX_NOTNULL), 0f); assertFalse(subject.wasNull()); assertEquals(0f, subject.getFloat(LONG_COLINDEX_NULL), 0f); @@ -1296,7 +1271,7 @@ public void testGetFloatIndexFromInt64() throws SQLException { } @Test - public void testGetFloatIndexFromTimestamp() throws SQLException { + public void testGetFloatIndexFromTimestamp() { try { subject.getFloat(TIMESTAMP_COLINDEX_NULL); fail("missing expected SQLException"); @@ -1308,7 +1283,6 @@ public void testGetFloatIndexFromTimestamp() throws SQLException { @Test public void testGetByteLabel() throws SQLException { - assertNotNull(subject.getByte(LONG_COL_NOT_NULL)); assertEquals(1, subject.getByte(LONG_COL_NOT_NULL)); assertFalse(subject.wasNull()); assertEquals(0, subject.getByte(LONG_COL_NULL)); @@ -1317,7 +1291,6 @@ public void testGetByteLabel() throws SQLException { @Test public void testGetShortLabel() throws SQLException { - assertNotNull(subject.getShort(LONG_COL_NOT_NULL)); assertEquals(1, subject.getShort(LONG_COL_NOT_NULL)); assertFalse(subject.wasNull()); assertEquals(0, subject.getShort(LONG_COL_NULL)); @@ -1326,7 +1299,6 @@ public void testGetShortLabel() throws SQLException { @Test public void testGetIntLabel() throws SQLException { - assertNotNull(subject.getInt(LONG_COL_NOT_NULL)); assertEquals(1, subject.getInt(LONG_COL_NOT_NULL)); assertFalse(subject.wasNull()); assertEquals(0, subject.getInt(LONG_COL_NULL)); @@ -1335,7 +1307,6 @@ public void testGetIntLabel() throws SQLException { @Test public void testGetFloatLabel() throws SQLException { - assertNotNull(subject.getFloat(DOUBLE_COL_NOT_NULL)); float expected = (float) DOUBLE_VALUE; assertEquals(expected, subject.getFloat(DOUBLE_COL_NOT_NULL), 0f); assertFalse(subject.wasNull()); @@ -1429,12 +1400,12 @@ public void testGetArrayIndex() throws SQLException { } @Test - public void testGetWarnings() throws SQLException { + public void testGetWarnings() { assertNull(subject.getWarnings()); } @Test - public void testClearWarnings() throws SQLException { + public void testClearWarnings() { subject.clearWarnings(); } @@ -1452,7 +1423,7 @@ public void testIsAfterLast() throws SQLException { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { assertFalse(rs.isAfterLast()); while (rs.next()) { - // do nothing + assertFalse(rs.isAfterLast()); } assertTrue(rs.isAfterLast()); } @@ -1677,7 +1648,7 @@ public void testGetBeforeNext() { public void testGetAfterLast() { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { while (rs.next()) { - // do nothing + assertNotNull(rs.getBigDecimal(LONG_COLINDEX_NOTNULL)); } rs.getBigDecimal(LONG_COLINDEX_NOTNULL); fail("missing expected exception"); @@ -1693,7 +1664,7 @@ public void testGetAfterLast() { } @Test - public void testFindIllegalColumnName() throws SQLException { + public void testFindIllegalColumnName() { try { subject.findColumn(UNKNOWN_COLUMN); fail("missing expected exception"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java index 4f41771eb900..3143d5ac1db3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -31,6 +31,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** SQL Script verifier for JDBC connections */ @@ -93,18 +94,13 @@ protected Object getValue(String col) throws SQLException { return com.google.cloud.Timestamp.of((Timestamp) value); } else if (value instanceof Array) { Array array = (Array) value; - switch (array.getBaseType()) { - case Types.BIGINT: - Long[] longs = (Long[]) array.getArray(); - List res = new ArrayList<>(); - for (Long l : longs) { - res.add(l); - } - return res; - default: - throw new IllegalArgumentException( - "Unsupported array base type: " + array.getBaseType()); + if (array.getBaseType() == Types.BIGINT) { + Long[] longs = (Long[]) array.getArray(); + List res = new ArrayList<>(); + Collections.addAll(res, longs); + return res; } + throw new IllegalArgumentException("Unsupported array base type: " + array.getBaseType()); } return value; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index e5efb773dd19..e73be4ef7479 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -43,7 +43,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @RunWith(JUnit4.class) @@ -53,6 +52,7 @@ public class JdbcStatementTest { private static final String LARGE_UPDATE = "UPDATE FOO SET BAR=1 WHERE 1=1"; private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; + @SuppressWarnings("unchecked") private JdbcStatement createStatement() { Connection spanner = mock(Connection.class); @@ -101,24 +101,21 @@ private JdbcStatement createStatement() { when(spanner.executeBatchUpdate(anyList())) .thenAnswer( - new Answer() { - @SuppressWarnings("unchecked") - @Override - public long[] answer(InvocationOnMock invocation) throws Throwable { - List statements = - (List) invocation.getArguments()[0]; - if (statements.isEmpty() - || StatementParser.INSTANCE.isDdlStatement(statements.get(0).getSql())) { - return new long[0]; - } - long[] res = - new long - [((List) invocation.getArguments()[0]) - .size()]; - Arrays.fill(res, 1L); - return res; - } - }); + (Answer) + invocation -> { + List statements = + (List) invocation.getArguments()[0]; + if (statements.isEmpty() + || StatementParser.INSTANCE.isDdlStatement(statements.get(0).getSql())) { + return new long[0]; + } + long[] res = + new long + [((List) invocation.getArguments()[0]) + .size()]; + Arrays.fill(res, 1L); + return res; + }); JdbcConnection connection = mock(JdbcConnection.class); when(connection.getSpannerConnection()).thenReturn(spanner); @@ -331,7 +328,7 @@ public void testExecuteLargeUpdate() throws SQLException { } @Test - public void testExecuteUpdateWithSelectStatement() throws SQLException { + public void testExecuteUpdateWithSelectStatement() { Statement statement = createStatement(); try { statement.executeUpdate(SELECT); @@ -438,7 +435,7 @@ public void testLargeDmlBatch() throws SQLException { } @Test - public void testConvertUpdateCounts() throws SQLException { + public void testConvertUpdateCounts() { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { int[] updateCounts = statement.convertUpdateCounts(new long[] {1L, 2L, 3L}); assertThat(updateCounts).asList().containsExactly(1, 2, 3); @@ -453,41 +450,41 @@ public void testConvertUpdateCounts() throws SQLException { } @Test - public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException { + public void testConvertUpdateCountsToSuccessNoInfo() { try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { long[] updateCounts = new long[3]; statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 2L, 3L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Long.valueOf(Statement.SUCCESS_NO_INFO), - Long.valueOf(Statement.SUCCESS_NO_INFO), - Long.valueOf(Statement.SUCCESS_NO_INFO)); + (long) Statement.SUCCESS_NO_INFO, + (long) Statement.SUCCESS_NO_INFO, + (long) Statement.SUCCESS_NO_INFO); statement.convertUpdateCountsToSuccessNoInfo(new long[] {0L, 0L, 0L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Long.valueOf(Statement.EXECUTE_FAILED), - Long.valueOf(Statement.EXECUTE_FAILED), - Long.valueOf(Statement.EXECUTE_FAILED)); + (long) Statement.EXECUTE_FAILED, + (long) Statement.EXECUTE_FAILED, + (long) Statement.EXECUTE_FAILED); statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 0L, 2L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Long.valueOf(Statement.SUCCESS_NO_INFO), - Long.valueOf(Statement.EXECUTE_FAILED), - Long.valueOf(Statement.SUCCESS_NO_INFO)); + (long) Statement.SUCCESS_NO_INFO, + (long) Statement.EXECUTE_FAILED, + (long) Statement.SUCCESS_NO_INFO); statement.convertUpdateCountsToSuccessNoInfo( new long[] {1L, Integer.MAX_VALUE + 1L, 2L}, updateCounts); assertThat(updateCounts) .asList() .containsExactly( - Long.valueOf(Statement.SUCCESS_NO_INFO), - Long.valueOf(Statement.SUCCESS_NO_INFO), - Long.valueOf(Statement.SUCCESS_NO_INFO)); + (long) Statement.SUCCESS_NO_INFO, + (long) Statement.SUCCESS_NO_INFO, + (long) Statement.SUCCESS_NO_INFO); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java index 6d743d147c21..8e36a7db10f8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java @@ -27,7 +27,7 @@ * As JDBC connections store the statement timeout on {@link Statement} objects instead of on the * {@link Connection}, the JDBC driver needs to set and reset the connection timeout on the * underlying connection after each statement execution. JDBC also uses seconds as the time unit for - * timeouts, while the underlying {@link com.google.cloud.spanner.jdbc.Connection}s use + * timeouts, while the underlying {@link com.google.cloud.spanner.connection.Connection}s use * milliseconds. This test script tests a number of special cases regarding this. */ @RunWith(JUnit4.class) @@ -35,6 +35,6 @@ public class JdbcTimeoutSqlTest { @Test public void testTimeoutScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); - verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass()); + verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass(), false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 1bb0e374ed02..f1ed83303e98 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -40,6 +40,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.sql.Array; import java.sql.Date; import java.sql.SQLException; @@ -57,7 +58,7 @@ @RunWith(JUnit4.class) public class JdbcTypeConverterTest { - private static final Charset UTF8 = Charset.forName("UTF8"); + private static final Charset UTF8 = StandardCharsets.UTF_8; @Test public void testConvertArray() throws SQLException { @@ -94,14 +95,12 @@ public void testConvertBool() throws SQLException { Boolean[] testValues = new Boolean[] {Boolean.TRUE, Boolean.FALSE}; for (Boolean b : testValues) { assertThat(convert(b, Type.bool(), Boolean.class)).isEqualTo(b); - assertThat(convert(b, Type.bool(), Byte.class)) - .isEqualTo(Byte.valueOf(b ? (byte) 1 : (byte) 0)); - assertThat(convert(b, Type.bool(), Short.class)) - .isEqualTo(Short.valueOf(b ? (short) 1 : (short) 0)); - assertThat(convert(b, Type.bool(), Integer.class)).isEqualTo(Integer.valueOf(b ? 1 : 0)); - assertThat(convert(b, Type.bool(), Long.class)).isEqualTo(Long.valueOf(b ? 1L : 0L)); - assertThat(convert(b, Type.bool(), Float.class)).isEqualTo(Float.valueOf(b ? 1F : 0F)); - assertThat(convert(b, Type.bool(), Double.class)).isEqualTo(Double.valueOf(b ? 1D : 0D)); + assertThat(convert(b, Type.bool(), Byte.class)).isEqualTo(b ? (byte) 1 : (byte) 0); + assertThat(convert(b, Type.bool(), Short.class)).isEqualTo(b ? (short) 1 : (short) 0); + assertThat(convert(b, Type.bool(), Integer.class)).isEqualTo(b ? 1 : 0); + assertThat(convert(b, Type.bool(), Long.class)).isEqualTo(b ? 1L : 0L); + assertThat(convert(b, Type.bool(), Float.class)).isEqualTo(b ? 1F : 0F); + assertThat(convert(b, Type.bool(), Double.class)).isEqualTo(b ? 1D : 0D); assertThat(convert(b, Type.bool(), BigInteger.class)) .isEqualTo(b ? BigInteger.ONE : BigInteger.ZERO); assertThat(convert(b, Type.bool(), BigDecimal.class)) @@ -238,18 +237,18 @@ public void testConvertInt64() throws SQLException { 1L, Long.MIN_VALUE, Long.MAX_VALUE, - Long.valueOf(Integer.MIN_VALUE), - Long.valueOf(Integer.MAX_VALUE), - Long.valueOf(Integer.MIN_VALUE - 1), - Long.valueOf(Integer.MAX_VALUE + 1), - Long.valueOf(Short.MIN_VALUE), - Long.valueOf(Short.MAX_VALUE), - Long.valueOf(Short.MIN_VALUE - 1), - Long.valueOf(Short.MAX_VALUE + 1), - Long.valueOf(Byte.MIN_VALUE), - Long.valueOf(Byte.MAX_VALUE), - Long.valueOf(Byte.MIN_VALUE - 1), - Long.valueOf(Byte.MAX_VALUE + 1) + (long) Integer.MIN_VALUE, + (long) Integer.MAX_VALUE, + ((long) Integer.MIN_VALUE - 1), + ((long) Integer.MAX_VALUE + 1), + (long) Short.MIN_VALUE, + (long) Short.MAX_VALUE, + (long) (Short.MIN_VALUE - 1), + (long) (Short.MAX_VALUE + 1), + (long) Byte.MIN_VALUE, + (long) Byte.MAX_VALUE, + (long) (Byte.MIN_VALUE - 1), + (long) (Byte.MAX_VALUE + 1) }; testConvertInt64ToNumber(testValues, Long.class, Long.MIN_VALUE, Long.MAX_VALUE); testConvertInt64ToNumber(testValues, Integer.class, Integer.MIN_VALUE, Integer.MAX_VALUE); @@ -260,7 +259,7 @@ public void testConvertInt64() throws SQLException { for (Long l : testValues) { assertThat(convert(l, Type.int64(), String.class)).isEqualTo(String.valueOf(l)); - assertThat(convert(l, Type.int64(), Boolean.class)).isEqualTo(Boolean.valueOf(l != 0L)); + assertThat(convert(l, Type.int64(), Boolean.class)).isEqualTo(l != 0L); assertConvertThrows(l, Type.int64(), Double.class, Code.INVALID_ARGUMENT); assertConvertThrows(l, Type.int64(), Float.class, Code.INVALID_ARGUMENT); } @@ -288,19 +287,19 @@ public void testConvertFloat64() throws SQLException { 1D, Double.MIN_VALUE, Double.MAX_VALUE, - Double.valueOf(Float.MIN_VALUE), - Double.valueOf(Float.MAX_VALUE), - Double.valueOf(Float.MAX_VALUE + 1D) + (double) Float.MIN_VALUE, + (double) Float.MAX_VALUE, + Float.MAX_VALUE + 1D }; for (Double d : testValues) { assertThat(convert(d, Type.float64(), Double.class)).isEqualTo(d); - if (d > Float.MAX_VALUE || d < -Float.MAX_VALUE) { + if (Math.abs(d) > Math.abs(Float.MAX_VALUE)) { assertConvertThrows(d, Type.float64(), Float.class, Code.OUT_OF_RANGE); } else { assertThat(convert(d, Type.float64(), Float.class)).isEqualTo(d.floatValue()); } assertThat(convert(d, Type.float64(), String.class)).isEqualTo(String.valueOf(d)); - assertThat(convert(d, Type.float64(), Boolean.class)).isEqualTo(Boolean.valueOf(d != 0D)); + assertThat(convert(d, Type.float64(), Boolean.class)).isEqualTo(d != 0D); assertConvertThrows(d, Type.float64(), Long.class, Code.INVALID_ARGUMENT); assertConvertThrows(d, Type.float64(), Integer.class, Code.INVALID_ARGUMENT); assertConvertThrows(d, Type.float64(), Short.class, Code.INVALID_ARGUMENT); @@ -328,8 +327,7 @@ public void testConvertNumeric() throws SQLException { assertThat(convert(d, Type.numeric(), Double.class)).isEqualTo(d.doubleValue()); assertThat(convert(d, Type.numeric(), Float.class)).isEqualTo(d.floatValue()); assertThat(convert(d, Type.numeric(), String.class)).isEqualTo(String.valueOf(d)); - assertThat(convert(d, Type.numeric(), Boolean.class)) - .isEqualTo(Boolean.valueOf(!d.equals(BigDecimal.ZERO))); + assertThat(convert(d, Type.numeric(), Boolean.class)).isEqualTo(!d.equals(BigDecimal.ZERO)); if (d.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0 || d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0 || d.scale() > 0) { @@ -446,35 +444,35 @@ public void testToSqlDate() { public void testToSqlDateWithCalendar() { for (TimeZone zone : getTestTimeZones()) { Calendar cal = Calendar.getInstance(zone); - cal.set(2019, 7, 24, 0, 0, 0); + cal.set(2019, Calendar.AUGUST, 24, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); assertThat( toSqlDate( com.google.cloud.Date.fromYearMonthDay(2019, 8, 24), Calendar.getInstance(zone))) .isEqualTo(new Date(cal.getTimeInMillis())); - cal.set(2019, 0, 1, 0, 0, 0); + cal.set(2019, Calendar.JANUARY, 1, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); assertThat( toSqlDate( com.google.cloud.Date.fromYearMonthDay(2019, 1, 1), Calendar.getInstance(zone))) .isEqualTo(new Date(cal.getTimeInMillis())); - cal.set(2019, 11, 31, 0, 0, 0); + cal.set(2019, Calendar.DECEMBER, 31, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); assertThat( toSqlDate( com.google.cloud.Date.fromYearMonthDay(2019, 12, 31), Calendar.getInstance(zone))) .isEqualTo(new Date(cal.getTimeInMillis())); - cal.set(2016, 1, 29, 0, 0, 0); + cal.set(2016, Calendar.FEBRUARY, 29, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); assertThat( toSqlDate( com.google.cloud.Date.fromYearMonthDay(2016, 2, 29), Calendar.getInstance(zone))) .isEqualTo(new Date(cal.getTimeInMillis())); - cal.set(2000, 1, 29, 0, 0, 0); + cal.set(2000, Calendar.FEBRUARY, 29, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); assertThat( toSqlDate( @@ -513,7 +511,7 @@ public void testToSqlDates() { @SuppressWarnings("deprecation") @Test - public void testToSqlTimestamp() throws SQLException { + public void testToSqlTimestamp() { TimeZone initialDefault = TimeZone.getDefault(); try { for (TimeZone zone : getTestTimeZones()) { @@ -564,12 +562,12 @@ public void testToSqlTimestamp() throws SQLException { } @Test - public void testGetAsSqlTimestamp() throws SQLException { + public void testGetAsSqlTimestamp() { for (TimeZone zone : getTestTimeZones()) { com.google.cloud.Timestamp gts = ReadOnlyStalenessUtil.parseRfc3339("2019-08-24T11:23:01.1998+03:00"); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+03:00")); - cal.set(2019, 7, 24, 11, 23, 1); + cal.set(2019, Calendar.AUGUST, 24, 11, 23, 1); cal.set(Calendar.MILLISECOND, 0); Timestamp ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); ts.setNanos(199800000); @@ -577,7 +575,7 @@ public void testGetAsSqlTimestamp() throws SQLException { gts = ReadOnlyStalenessUtil.parseRfc3339("2019-12-31T23:59:59.999999999-03:00"); cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-03:00")); - cal.set(2019, 11, 31, 23, 59, 59); + cal.set(2019, Calendar.DECEMBER, 31, 23, 59, 59); cal.set(Calendar.MILLISECOND, 0); ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); ts.setNanos(999999999); @@ -585,14 +583,14 @@ public void testGetAsSqlTimestamp() throws SQLException { gts = ReadOnlyStalenessUtil.parseRfc3339("2016-02-29T12:00:00Z"); cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - cal.set(2016, 1, 29, 12, 0, 0); + cal.set(2016, Calendar.FEBRUARY, 29, 12, 0, 0); cal.set(Calendar.MILLISECOND, 0); ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); gts = ReadOnlyStalenessUtil.parseRfc3339("2000-02-29T00:00:00.000000000-10:00"); cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-10:00")); - cal.set(2000, 1, 29, 0, 0, 0); + cal.set(2000, Calendar.FEBRUARY, 29, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); ts = new Timestamp(cal.getTimeInMillis() + zone.getRawOffset()); assertThat(getAsSqlTimestamp(gts, Calendar.getInstance(zone))).isEqualTo(ts); @@ -601,10 +599,10 @@ public void testGetAsSqlTimestamp() throws SQLException { @SuppressWarnings("deprecation") @Test - public void testSetTimestampInCalendar() throws SQLException { + public void testSetTimestampInCalendar() { for (TimeZone zone : getTestTimeZones()) { Calendar cal = Calendar.getInstance(zone); - cal.set(2019, 7, 24, 11, 23, 1); + cal.set(2019, Calendar.AUGUST, 24, 11, 23, 1); cal.set(Calendar.MILLISECOND, 0); Timestamp ts = new Timestamp(2019 - 1900, 7, 24, 11, 23, 1, 0); Timestamp tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); @@ -612,7 +610,7 @@ public void testSetTimestampInCalendar() throws SQLException { .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); cal = Calendar.getInstance(zone); - cal.set(2019, 11, 31, 23, 59, 59); + cal.set(2019, Calendar.DECEMBER, 31, 23, 59, 59); cal.set(Calendar.MILLISECOND, 999); ts = new Timestamp(2019 - 1900, 11, 31, 23, 59, 59, 999000000); tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); @@ -620,7 +618,7 @@ public void testSetTimestampInCalendar() throws SQLException { .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); cal = Calendar.getInstance(zone); - cal.set(2016, 1, 29, 12, 0, 0); + cal.set(2016, Calendar.FEBRUARY, 29, 12, 0, 0); cal.set(Calendar.MILLISECOND, 0); ts = new Timestamp(2016 - 1900, 1, 29, 12, 0, 0, 0); tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); @@ -628,7 +626,7 @@ public void testSetTimestampInCalendar() throws SQLException { .isEqualTo(cal.getTimeInMillis() - TimeZone.getDefault().getOffset(ts.getTime())); cal = Calendar.getInstance(zone); - cal.set(2000, 1, 29, 0, 0, 0); + cal.set(2000, Calendar.FEBRUARY, 29, 0, 0, 0); cal.set(Calendar.MILLISECOND, 0); ts = new Timestamp(2000 - 1900, 1, 29, 0, 0, 0, 0); tsInCal = setTimestampInCalendar(ts, Calendar.getInstance(zone)); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java index be5fed233dea..062a5ac42da7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java @@ -30,7 +30,7 @@ public static SpannerJdbcExceptionMatcher matchC Class exceptionClass, Code errorCode) { Preconditions.checkNotNull(exceptionClass); Preconditions.checkNotNull(errorCode); - return new SpannerJdbcExceptionMatcher(exceptionClass, errorCode, null); + return new SpannerJdbcExceptionMatcher<>(exceptionClass, errorCode, null); } public static SpannerJdbcExceptionMatcher matchCodeAndMessage( @@ -38,7 +38,7 @@ public static SpannerJdbcExceptionMatcher matchC Preconditions.checkNotNull(exceptionClass); Preconditions.checkNotNull(errorCode); Preconditions.checkNotNull(message); - return new SpannerJdbcExceptionMatcher(exceptionClass, errorCode, message); + return new SpannerJdbcExceptionMatcher<>(exceptionClass, errorCode, message); } private SpannerJdbcExceptionMatcher(Class exceptionClass, Code errorCode, String message) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 6d7cd0622cca..3626e4594087 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcDataSource; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.io.FileInputStream; import java.io.IOException; import java.sql.Connection; @@ -55,11 +56,11 @@ public class ITJdbcConnectTest extends ITAbstractJdbcTest { private String createBaseUrl() { StringBuilder url = new StringBuilder("jdbc:cloudspanner:"); - if (env.getTestHelper().isEmulator()) { + if (EmulatorSpannerHelper.isUsingEmulator()) { url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST")); } url.append("/").append(getDatabase().getId().getName()); - if (env.getTestHelper().isEmulator()) { + if (EmulatorSpannerHelper.isUsingEmulator()) { url.append(";usePlainText=true"); } return url.toString(); @@ -174,7 +175,7 @@ public void testConnectWithDataSourceWithDefaultValues() throws SQLException { public void testConnectWithDataSourceWithNonDefaultValues() throws SQLException { JdbcDataSource ds = new JdbcDataSource(); ds.setUrl(createBaseUrl()); - if (hasValidKeyFile() && !env.getTestHelper().isEmulator()) { + if (hasValidKeyFile() && !EmulatorSpannerHelper.isUsingEmulator()) { ds.setCredentials(getKeyFile()); } ds.setAutocommit(false); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index c559bb3fc2f5..abc14e35da3a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -33,6 +33,6 @@ public class ITJdbcDdlTest extends ITAbstractJdbcTest { @Test public void testSqlScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); - verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class); + verifier.verifyStatementsInFile("ITDdlTest.sql", SqlScriptVerifier.class, false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 24a9e01f4fc3..bdc35b079737 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -53,6 +53,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.List; +import java.util.Objects; import java.util.Scanner; import java.util.TimeZone; import java.util.UUID; @@ -81,7 +82,7 @@ private static Singer of(String values) { throw new IllegalArgumentException(values); } return new Singer( - Long.valueOf(array[0]), // singer id + Long.parseLong(array[0]), // singer id array[1].substring(1, array[1].length() - 1), // first name array[2].substring(1, array[2].length() - 1), // last name parseBytes(array[3].substring(13, array[3].length() - 2)), // singer info @@ -111,10 +112,10 @@ private static Album of(String values) { throw new IllegalArgumentException(values); } return new Album( - Long.valueOf(array[0]), // singer id - Long.valueOf(array[1]), // album id + Long.parseLong(array[0]), // singer id + Long.parseLong(array[1]), // album id array[2].substring(1, array[2].length() - 1), // album title - Long.valueOf(array[3]) // marketing budget + Long.parseLong(array[3]) // marketing budget ); } @@ -140,11 +141,11 @@ private static Song of(String values) { throw new IllegalArgumentException(values); } return new Song( - Long.valueOf(array[0]), // singer id - Long.valueOf(array[1]), // album id - Long.valueOf(array[2]), // song id + Long.parseLong(array[0]), // singer id + Long.parseLong(array[1]), // album id + Long.parseLong(array[2]), // song id array[3].substring(1, array[3].length() - 1), // song name - Long.valueOf(array[4]), // duration + Long.parseLong(array[4]), // duration array[5].substring(1, array[5].length() - 1)); } @@ -173,14 +174,14 @@ private static final class Concert { private final Long[] ticketPrices; private static Concert of(String values) { - values = values.replaceAll("\\[(\\d+),(\\d+),(\\d+),(\\d+)\\]", "[$1;$2;$3;$4]"); + values = values.replaceAll("\\[(\\d+),(\\d+),(\\d+),(\\d+)]", "[$1;$2;$3;$4]"); String[] array = values.split(","); if (array.length != 6) { throw new IllegalArgumentException(values); } return new Concert( - Long.valueOf(array[0]), // venue id - Long.valueOf(array[1]), // singer id + Long.parseLong(array[0]), // venue id + Long.parseLong(array[1]), // singer id parseDate(array[2].substring(6, array[2].length() - 1)), // concert date parseTimestamp(array[3].substring(11, array[3].length() - 1)), // begin time parseTimestamp(array[4].substring(11, array[4].length() - 1)), // end time @@ -421,17 +422,17 @@ public void test03_Dates() throws SQLException { // requested timezone) should be returned. Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.clear(); - cal.set(2015, 10, 15, 10, 0, 0); + cal.set(2015, Calendar.NOVEMBER, 15, 10, 0, 0); testDates.add(new Date(cal.getTimeInMillis())); cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); cal.clear(); - cal.set(2015, 10, 15, 10, 0, 0); + cal.set(2015, Calendar.NOVEMBER, 15, 10, 0, 0); testDates.add(new Date(cal.getTimeInMillis())); cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); cal.clear(); - cal.set(2015, 10, 15, 10, 0, 0); + cal.set(2015, Calendar.NOVEMBER, 15, 10, 0, 0); testDates.add(new Date(cal.getTimeInMillis())); List calendars = new ArrayList<>(); @@ -503,17 +504,6 @@ public void test04_Timestamps() throws SQLException { expectedValues.add("2015-11-15 10:00:00"); expectedValues.add("2015-11-15 10:00:00"); - List timezones = new ArrayList<>(); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getDefault()); - timezones.add(TimeZone.getTimeZone("UTC")); - timezones.add(TimeZone.getTimeZone("CET")); - timezones.add(TimeZone.getTimeZone("PST")); - List testTimestamps = new ArrayList<>(); testTimestamps.add(Timestamp.valueOf(expectedValues.get(0))); testTimestamps.add(Timestamp.valueOf(expectedValues.get(1))); @@ -526,17 +516,17 @@ public void test04_Timestamps() throws SQLException { // format. Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.clear(); - cal.set(2015, 10, 15); + cal.set(2015, Calendar.NOVEMBER, 15); testTimestamps.add(new Timestamp(cal.getTimeInMillis())); cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); cal.clear(); - cal.set(2015, 10, 15); + cal.set(2015, Calendar.NOVEMBER, 15); testTimestamps.add(new Timestamp(cal.getTimeInMillis())); cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); cal.clear(); - cal.set(2015, 10, 15); + cal.set(2015, Calendar.NOVEMBER, 15); testTimestamps.add(new Timestamp(cal.getTimeInMillis())); List calendars = new ArrayList<>(); @@ -1063,14 +1053,13 @@ private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedP } private List readValuesFromFile(String filename) { - File file = new File(getClass().getResource(filename).getFile()); + File file = new File(Objects.requireNonNull(getClass().getResource(filename)).getFile()); StringBuilder builder = new StringBuilder(); try (Scanner scanner = new Scanner(file)) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); builder.append(line).append("\n"); } - scanner.close(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 990331074ea2..1c01ce2fae37 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -34,6 +34,7 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import javax.annotation.Nonnull; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -187,11 +188,13 @@ public void testOptionsInEnvironment() throws SQLException { try { SpannerOptions.useEnvironment( new SpannerOptions.SpannerEnvironment() { + @Nonnull @Override public String getOptimizerVersion() { return "1"; } + @Nonnull @Override public String getOptimizerStatisticsPackage() { return "latest"; @@ -212,11 +215,13 @@ public String getOptimizerStatisticsPackage() { // Now set an invalid version on the environment. The query will now fail. SpannerOptions.useEnvironment( new SpannerOptions.SpannerEnvironment() { + @Nonnull @Override public String getOptimizerVersion() { return "9999999"; } + @Nonnull @Override public String getOptimizerStatisticsPackage() { return "latest"; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 0e5a2f91a45d..5fef9dbf1590 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc.it; +import static org.junit.Assert.assertTrue; + import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.ConnectionOptions; @@ -54,7 +56,7 @@ public void createTestTables() throws Exception { // create tables JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class); + "ITReadOnlySpannerTest_CreateTables.sql", SqlScriptVerifier.class, false); // fill tables with data connection.setAutoCommit(false); @@ -94,7 +96,7 @@ public void testSqlScript() throws Exception { // Wait 100ms to ensure that staleness tests in the script succeed. Thread.sleep(100L); JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); - verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class); + verifier.verifyStatementsInFile("ITReadOnlySpannerTest.sql", SqlScriptVerifier.class, false); } @Test @@ -106,29 +108,27 @@ public void testMultipleOpenResultSets() throws InterruptedException, SQLExcepti connection.createStatement().executeQuery("SELECT * FROM NUMBERS"); ExecutorService exec = Executors.newFixedThreadPool(2); exec.submit( - new Runnable() { - @Override - public void run() { - try { - while (rs1.next()) {} - } catch (SQLException e) { - throw new RuntimeException(e); + () -> { + try { + while (rs1.next()) { + assertTrue(rs1.getInt(1) > 0); } + } catch (SQLException e) { + throw new RuntimeException(e); } }); exec.submit( - new Runnable() { - @Override - public void run() { - try { - while (rs2.next()) {} - } catch (SQLException e) { - throw new RuntimeException(e); + () -> { + try { + while (rs2.next()) { + assertTrue(rs2.getInt(1) > 0); } + } catch (SQLException e) { + throw new RuntimeException(e); } }); exec.shutdown(); - exec.awaitTermination(1000L, TimeUnit.SECONDS); + assertTrue(exec.awaitTermination(1000L, TimeUnit.SECONDS)); rs1.close(); rs2.close(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index d72992aec0ca..b620f5a7fe02 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -52,7 +52,7 @@ public boolean doCreateDefaultTestTable() { public void test01_SqlScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); verifier.verifyStatementsInFile( - "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class); + "ITReadWriteAutocommitSpannerTest.sql", SqlScriptVerifier.class, false); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index 0793849344bc..4a8dab592962 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -186,7 +186,7 @@ public void testSelectArrayOfStructs() throws SQLException { Struct.newBuilder().set("point").to(Value.int64Array(new long[] {5L, 7L})).build()); // Getting a result set from an array of structs is not supported, as structs are not // supported as a valid column type in a result set. - assertThrows(SQLFeatureNotSupportedException.class, () -> array.getResultSet()); + assertThrows(SQLFeatureNotSupportedException.class, array::getResultSet); assertFalse(resultSet.next()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 31b8394ad9b1..f3dfb8489187 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -37,7 +37,7 @@ public void testRunScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(); try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), SCRIPT_FILE, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), SCRIPT_FILE, SqlScriptVerifier.class, false); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java index fdb752965b23..344177c602c7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java @@ -28,6 +28,7 @@ import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -76,7 +77,7 @@ public class ITJdbcSqlScriptTest extends ITAbstractJdbcTest { public void test01_CreateTables() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), CREATE_TABLES_FILE, SqlScriptVerifier.class, false); } } @@ -87,17 +88,21 @@ public void test02_InsertTestData() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), INSERT_AND_VERIFY_TEST_DATA, - SqlScriptVerifier.class); + SqlScriptVerifier.class, + false); } catch (SQLException e) { - if (env.getTestHelper().isEmulator() - && e.getErrorCode() == ErrorCode.ALREADY_EXISTS.getGrpcStatusCode().value()) { - // Ignore, this is expected as errors during a read/write transaction are sticky on the - // emulator. + // Ignore these errors on the emulator, as they are sticky during a read/write transaction on + // the emulator. + if (!(EmulatorSpannerHelper.isUsingEmulator() + && e.getErrorCode() == ErrorCode.ALREADY_EXISTS.getGrpcStatusCode().value())) { + throw e; } } catch (SpannerException e) { - if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) { - // Ignore, this is expected as errors during a read/write transaction are sticky on the - // emulator. + // Ignore these errors on the emulator, as they are sticky during a read/write transaction on + // the emulator. + if (!(EmulatorSpannerHelper.isUsingEmulator() + && e.getErrorCode() == ErrorCode.ALREADY_EXISTS)) { + throw e; } } } @@ -106,7 +111,10 @@ public void test02_InsertTestData() throws Exception { public void test03_TestGetReadTimestamp() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_GET_READ_TIMESTAMP, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_GET_READ_TIMESTAMP, + SqlScriptVerifier.class, + false); } } @@ -114,16 +122,23 @@ public void test03_TestGetReadTimestamp() throws Exception { public void test04_TestGetCommitTimestamp() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_GET_COMMIT_TIMESTAMP, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_GET_COMMIT_TIMESTAMP, + SqlScriptVerifier.class, + false); } catch (SQLException e) { - if (env.getTestHelper().isEmulator() - && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()) { - // Ignore as errors during read/write transactions are sticky on the emulator. + // Ignore these errors on the emulator, as they are sticky during a read/write transaction on + // the emulator. + if (!(EmulatorSpannerHelper.isUsingEmulator() + && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value())) { + throw e; } } catch (SpannerException e) { - if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) { - // Ignore, this is expected as errors during a read/write transaction are sticky on the - // emulator. + // Ignore these errors on the emulator, as they are sticky during a read/write transaction on + // the emulator. + if (!(EmulatorSpannerHelper.isUsingEmulator() + && e.getErrorCode() == ErrorCode.ALREADY_EXISTS)) { + throw e; } } } @@ -134,7 +149,8 @@ public void test05_TestTemporaryTransactions() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), TEST_TEMPORARY_TRANSACTIONS, - SqlScriptVerifier.class); + SqlScriptVerifier.class, + false); } } @@ -142,7 +158,10 @@ public void test05_TestTemporaryTransactions() throws Exception { public void test06_TestTransactionMode() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_TRANSACTION_MODE, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_TRANSACTION_MODE, + SqlScriptVerifier.class, + false); } } @@ -152,7 +171,8 @@ public void test07_TestTransactionModeReadOnly() throws Exception { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), TEST_TRANSACTION_MODE_READ_ONLY, - SqlScriptVerifier.class); + SqlScriptVerifier.class, + false); } } @@ -160,7 +180,10 @@ public void test07_TestTransactionModeReadOnly() throws Exception { public void test08_TestReadOnlyStaleness() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_READ_ONLY_STALENESS, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_READ_ONLY_STALENESS, + SqlScriptVerifier.class, + false); } } @@ -168,7 +191,10 @@ public void test08_TestReadOnlyStaleness() throws Exception { public void test09_TestAutocommitDmlMode() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_AUTOCOMMIT_DML_MODE, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_AUTOCOMMIT_DML_MODE, + SqlScriptVerifier.class, + false); } } @@ -176,7 +202,10 @@ public void test09_TestAutocommitDmlMode() throws Exception { public void test10_TestAutocommitReadOnly() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_AUTOCOMMIT_READ_ONLY, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_AUTOCOMMIT_READ_ONLY, + SqlScriptVerifier.class, + false); } } @@ -184,7 +213,10 @@ public void test10_TestAutocommitReadOnly() throws Exception { public void test11_TestStatementTimeout() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_STATEMENT_TIMEOUT, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_STATEMENT_TIMEOUT, + SqlScriptVerifier.class, + false); } try (Connection connection = createConnection()) { // Create a statement with a query timeout, but do not set a statement timeout on the @@ -222,7 +254,10 @@ public void test11_TestStatementTimeout() throws Exception { public void test12_TestSetStatements() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_SET_STATEMENTS, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_SET_STATEMENTS, + SqlScriptVerifier.class, + false); } } @@ -230,7 +265,10 @@ public void test12_TestSetStatements() throws Exception { public void test13_TestInvalidStatements() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_INVALID_STATEMENTS, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), + TEST_INVALID_STATEMENTS, + SqlScriptVerifier.class, + false); } } @@ -238,7 +276,7 @@ public void test13_TestInvalidStatements() throws Exception { public void test14_TestQueryOptions() throws Exception { try (Connection connection = createConnection()) { verifier.verifyStatementsInFile( - JdbcGenericConnection.of(connection), TEST_QUERY_OPTIONS, SqlScriptVerifier.class); + JdbcGenericConnection.of(connection), TEST_QUERY_OPTIONS, SqlScriptVerifier.class, false); } } } From b8a238c579b7de72d9f3130c56d7478af135fedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 4 Nov 2021 12:07:30 +0100 Subject: [PATCH 0570/1979] test(deps): update dependency org.mockito:mockito-core to v4 (#658) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 899673f1fc23..ac3142a2c6d2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 3.12.4 + 4.0.0 2.2 From ea431f834d9a634774b30ef675b8904fc7c3d74e Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:16:17 +0000 Subject: [PATCH 0571/1979] chore(java): remove pin on Apache Maven 3.8.1 from github actions (#1268) (#659) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 0df65ebe91a6..5a79fcd57b79 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:a3ac08d167454718ff057b97a1950d3cb5e16fc39fb3f355d90276285a6cac75 + digest: sha256:ed012741acaae5d03e011244585a1f0625a596d31568967d77772aa5a0a51d5e diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 2425d7234f42..d95a11a26273 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -12,9 +12,6 @@ jobs: java: [8, 11, 17] steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v2 with: distribution: zulu @@ -27,9 +24,6 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v2 with: distribution: zulu @@ -45,9 +39,6 @@ jobs: java: [8, 11, 17] steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v2 with: distribution: zulu @@ -58,9 +49,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v2 with: distribution: zulu @@ -73,9 +61,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: stCarolas/setup-maven@v4 - with: - maven-version: 3.8.1 - uses: actions/setup-java@v2 with: distribution: zulu @@ -83,4 +68,4 @@ jobs: - run: java -version - run: .kokoro/build.sh env: - JOB_TYPE: clirr + JOB_TYPE: clirr \ No newline at end of file From 860825d1ed6d2fb0314fb32a02469d3720f3b925 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:34:16 +0000 Subject: [PATCH 0572/1979] Update ci.yaml (#1275) (#660) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 5a79fcd57b79..994dd04bfe64 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:ed012741acaae5d03e011244585a1f0625a596d31568967d77772aa5a0a51d5e + digest: sha256:fecf6bd85f19eb046d913982ea36f6d434f9a49ab0545d25e31186aa64367c0c diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index d95a11a26273..93b337c62839 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -8,6 +8,7 @@ jobs: units: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: java: [8, 11, 17] steps: @@ -68,4 +69,4 @@ jobs: - run: java -version - run: .kokoro/build.sh env: - JOB_TYPE: clirr \ No newline at end of file + JOB_TYPE: clirr From 2912ec9a0502c5e85a6d890e223dbdcb32a6a3d8 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 8 Nov 2021 21:52:19 +0000 Subject: [PATCH 0573/1979] chore: cleanup cloud RAD generation (#1269) (#661) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 994dd04bfe64..325daaa4b5a2 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:fecf6bd85f19eb046d913982ea36f6d434f9a49ab0545d25e31186aa64367c0c + digest: sha256:204b7af96e6d481f19b0ff377aa379d46bc56dd06e1cc7c523f361dd9cbfeeaa diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 3b65375ef7dc..49678864cc3d 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -36,13 +36,9 @@ mvn clean install -B -q -DskipTests=true export NAME=google-cloud-spanner-jdbc export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) -# V3 generates docfx yml from javadoc -# generate yml -mvn clean site -B -q -P docFX - -# copy README to docfx-yml dir and rename index.md -cp README.md target/docfx-yml/index.md -# copy CHANGELOG to docfx-yml dir and rename history.md +# cloud RAD generation +mvn clean javadoc:aggregate -B -q -P docFX +# include CHANGELOG cp CHANGELOG.md target/docfx-yml/history.md pushd target/docfx-yml From 1b0ff2b9358ff5d71b1a71c83349dbdb837ddce5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 9 Nov 2021 00:22:25 +0100 Subject: [PATCH 0574/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.1 (#662) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.0` -> `1.2.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.1/compatibility-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.1/confidence-slim/1.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.1`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​121-httpswwwgithubcomgoogleapisjava-shared-configcomparev120v121-2021-11-08) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.0...v1.2.1)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ac3142a2c6d2..40bbbab637a0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.0 + 1.2.1 From b4b83fd67f44e8257f0995b2ea3184baced1c839 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 9 Nov 2021 14:46:21 +0000 Subject: [PATCH 0575/1979] chore: update jre to 11 for linter (#1278) (#663) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 325daaa4b5a2..886d09496d14 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:204b7af96e6d481f19b0ff377aa379d46bc56dd06e1cc7c523f361dd9cbfeeaa + digest: sha256:14ecf64ec36f67c7bf04e3dc0f68eafcc01df3955121c38862b695e2ae7515d8 diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 93b337c62839..05de1f60dcf0 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -53,7 +53,7 @@ jobs: - uses: actions/setup-java@v2 with: distribution: zulu - java-version: 8 + java-version: 11 - run: java -version - run: .kokoro/build.sh env: From b03eec9985eeb050328c30f19c03483fdde8be1e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 11 Nov 2021 04:01:43 +0100 Subject: [PATCH 0576/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.2 (#664) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 40bbbab637a0..a1d0fc23ed15 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.15.1 + 6.15.2 pom import From 6d189ee5a59d4c0076ce71d8041506ddc39ff190 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 11 Nov 2021 03:08:18 +0000 Subject: [PATCH 0577/1979] chore: release 2.5.2 (#665) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.1...v2.5.2) (2021-11-11) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.2 ([#664](https://www.github.com/googleapis/java-spanner-jdbc/issues/664)) ([b03eec9](https://www.github.com/googleapis/java-spanner-jdbc/commit/b03eec9985eeb050328c30f19c03483fdde8be1e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 83b7e7d84cb2..c884c7f4d12d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.1...v2.5.2) (2021-11-11) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.2 ([#664](https://www.github.com/googleapis/java-spanner-jdbc/issues/664)) ([9f22c33](https://www.github.com/googleapis/java-spanner-jdbc/commit/9f22c331ee4c7340ed6f1b9f91a44ce1e4c5b792)) + ### [2.5.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.0...v2.5.1) (2021-10-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a1d0fc23ed15..8df06d8115d8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.2-SNAPSHOT + 2.5.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6dd2b30336d4..2a3757e2ec21 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.2-SNAPSHOT + 2.5.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 00a2205689b0..bf290eb991de 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.1:2.5.2-SNAPSHOT +google-cloud-spanner-jdbc:2.5.2:2.5.2 From 6e9bcdcb2650be968b0f8edb24e4ee66aa10df2a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 11 Nov 2021 03:18:28 +0000 Subject: [PATCH 0578/1979] chore: release 2.5.3-SNAPSHOT (#666) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8df06d8115d8..30c091d160f6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.2 + 2.5.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2a3757e2ec21..51f9ad5b1c42 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.2 + 2.5.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bf290eb991de..7b2d5215fb5d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.2:2.5.2 +google-cloud-spanner-jdbc:2.5.2:2.5.3-SNAPSHOT From 5228db2b1c18c61715eae439cd94116da2a0b444 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 15 Nov 2021 07:07:36 +0100 Subject: [PATCH 0579/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.0 (#668) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 30c091d160f6..4f70cc987138 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.4.0 + 2.5.0 pom import From 82505a9c30e7ce4e1258865ed704eb9c22b7d8f4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 15 Nov 2021 07:07:56 +0100 Subject: [PATCH 0580/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.2 (#667) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 46322c634422..3a7e101ce83f 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.1 + 2.5.2 From 0ac8dcce867e85e64177c4568443fd67243a852d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 06:14:16 +0000 Subject: [PATCH 0581/1979] chore: release 2.5.3 (#669) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.2...v2.5.3) (2021-11-15) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.0 ([#668](https://www.github.com/googleapis/java-spanner-jdbc/issues/668)) ([5228db2](https://www.github.com/googleapis/java-spanner-jdbc/commit/5228db2b1c18c61715eae439cd94116da2a0b444)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c884c7f4d12d..c59230d1ce67 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.2...v2.5.3) (2021-11-15) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.0 ([#668](https://www.github.com/googleapis/java-spanner-jdbc/issues/668)) ([d453234](https://www.github.com/googleapis/java-spanner-jdbc/commit/d45323445d3e4a0753bed6cfe858fa891bca468e)) + ### [2.5.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.1...v2.5.2) (2021-11-11) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4f70cc987138..e9d595082273 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.3-SNAPSHOT + 2.5.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 51f9ad5b1c42..c8eefe24fa80 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.3-SNAPSHOT + 2.5.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7b2d5215fb5d..194cca1d6bdb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.2:2.5.3-SNAPSHOT +google-cloud-spanner-jdbc:2.5.3:2.5.3 From 27ee6faee6bd4c438a5460edf1f5618046a599a2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 Nov 2021 06:20:16 +0000 Subject: [PATCH 0582/1979] chore: release 2.5.4-SNAPSHOT (#670) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e9d595082273..ffcebe4f56c6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.3 + 2.5.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c8eefe24fa80..243af5cd0287 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.3 + 2.5.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 194cca1d6bdb..e0d7cfd7f226 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.3:2.5.3 +google-cloud-spanner-jdbc:2.5.3:2.5.4-SNAPSHOT From 7db44302b2ffd5091c40cd8f4a24e0ea5072330f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 15 Nov 2021 17:02:10 +0100 Subject: [PATCH 0583/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.3 (#671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.2` -> `2.5.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.3/compatibility-slim/2.5.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.3/confidence-slim/2.5.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.3`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​253-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev252v253-2021-11-15) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.2...v2.5.3)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3a7e101ce83f..0b99fb77665a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.2 + 2.5.3 From ca094660b26ce851f981303db8ca830761f492d8 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Nov 2021 18:54:52 +0100 Subject: [PATCH 0584/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.16.0 (#673) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ffcebe4f56c6..fdb6a861377f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.15.2 + 6.16.0 pom import From dfd40cfd42cf895894df3d2162687320c120aec8 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Wed, 17 Nov 2021 12:18:55 +0530 Subject: [PATCH 0585/1979] chore: add tests for rpcPriority (#672) --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 2 + .../spanner/jdbc/JdbcQueryOptionsTest.java | 49 +++++++++++++++++-- .../spanner/jdbc/it/ITJdbcConnectTest.java | 6 ++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index b127e6825335..5df6cf63844d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -108,6 +108,8 @@ *
  • maxSessions (int): Sets the maximum number of sessions in the backing session pool. * Defaults to 400. *
  • numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. + *
  • rpcPriority (String): Sets the priority for all RPC invocations from this connection. + * Defaults to HIGH. * */ public class JdbcDriver implements Driver { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index f1aaeeaca3fc..44a95e3dc9a2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -51,6 +51,12 @@ public void testDefaultOptions() throws SQLException { assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo(""); assertThat(rs.next()).isFalse(); } + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("PRIORITY_UNSPECIFIED"); + assertThat(rs.next()).isFalse(); + } } } @@ -59,8 +65,8 @@ public void testOptionsInConnectionUrl() throws SQLException { try (java.sql.Connection connection = DriverManager.getConnection( String.format( - "jdbc:%s;optimizerVersion=%s;optimizerStatisticsPackage=%s", - getBaseUrl(), "100", "url_package"))) { + "jdbc:%s;optimizerVersion=%s;optimizerStatisticsPackage=%s;rpcPriority=%s", + getBaseUrl(), "100", "url_package", "LOW"))) { try (java.sql.ResultSet rs = connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { assertThat(rs.next()).isTrue(); @@ -73,6 +79,12 @@ public void testOptionsInConnectionUrl() throws SQLException { assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo("url_package"); assertThat(rs.next()).isFalse(); } + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("LOW"); + assertThat(rs.next()).isFalse(); + } } } @@ -122,6 +134,28 @@ public void testSetOptions() throws SQLException { assertThat(rs.getString("OPTIMIZER_STATISTICS_PACKAGE")).isEqualTo(""); assertThat(rs.next()).isFalse(); } + + connection.createStatement().execute("SET RPC_PRIORITY='LOW'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("LOW"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET RPC_PRIORITY='MEDIUM'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("MEDIUM"); + assertThat(rs.next()).isFalse(); + } + connection.createStatement().execute("SET RPC_PRIORITY='NULL'"); + try (java.sql.ResultSet rs = + connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("PRIORITY_UNSPECIFIED"); + assertThat(rs.next()).isFalse(); + } } } @@ -130,6 +164,7 @@ public void testSetAndUseOptions() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { connection.createStatement().execute("SET OPTIMIZER_VERSION='20'"); connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='20210609'"); + connection.createStatement().execute("SET RPC_PRIORITY='LOW'"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); @@ -140,10 +175,12 @@ public void testSetAndUseOptions() throws SQLException { ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("20"); assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()).isEqualTo("20210609"); + assertThat(request.getRequestOptions().getPriority().toString()).isEqualTo("PRIORITY_LOW"); } connection.createStatement().execute("SET OPTIMIZER_VERSION='latest'"); connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE='latest'"); + connection.createStatement().execute("SET RPC_PRIORITY='MEDIUM'"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); @@ -152,12 +189,15 @@ public void testSetAndUseOptions() throws SQLException { ExecuteSqlRequest request = getLastExecuteSqlRequest(); assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("latest"); assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()).isEqualTo("latest"); + assertThat(request.getRequestOptions().getPriority().toString()) + .isEqualTo("PRIORITY_MEDIUM"); } // Set the options to ''. This will do a fallback to the default, meaning that it will be read // from the environment variables as we have nothing set on the connection URL. connection.createStatement().execute("SET OPTIMIZER_VERSION=''"); connection.createStatement().execute("SET OPTIMIZER_STATISTICS_PACKAGE=''"); + connection.createStatement().execute("SET RPC_PRIORITY='NULL'"); try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT_COUNT_STATEMENT.getSql())) { assertThat(rs.next()).isTrue(); @@ -170,6 +210,8 @@ public void testSetAndUseOptions() throws SQLException { .isEqualTo(MoreObjects.firstNonNull(System.getenv("SPANNER_OPTIMIZER_VERSION"), "")); assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) .isEqualTo(MoreObjects.firstNonNull(System.getenv("OPTIMIZER_STATISTICS_PACKAGE"), "")); + assertThat(request.getRequestOptions().getPriority().toString()) + .isEqualTo("PRIORITY_UNSPECIFIED"); } } } @@ -179,7 +221,7 @@ public void testUseOptionsFromConnectionUrl() throws SQLException { try (java.sql.Connection connection = DriverManager.getConnection( String.format( - "jdbc:%s;optimizerVersion=10;optimizerStatisticsPackage=20210609_10_00_00", + "jdbc:%s;optimizerVersion=10;optimizerStatisticsPackage=20210609_10_00_00;rpcPriority=LOW", getBaseUrl()))) { // Do a query and verify that the version from the connection URL is used. try (java.sql.ResultSet rs = @@ -192,6 +234,7 @@ public void testUseOptionsFromConnectionUrl() throws SQLException { assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("10"); assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) .isEqualTo("20210609_10_00_00"); + assertThat(request.getRequestOptions().getPriority().toString()).isEqualTo("PRIORITY_LOW"); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 3626e4594087..90a7ea8a1c87 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -107,7 +107,7 @@ public void testConnectWithURLWithDefaultValues() throws SQLException { @Test public void testConnectWithURLWithNonDefaultValues() throws SQLException { String url = createBaseUrl(); - url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false"; + url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false;rpcPriority=LOW"; if (hasValidKeyFile()) { url = url + ";credentials=" + getKeyFile(); } @@ -138,6 +138,7 @@ public void testConnectWithPropertiesWithNonDefaultValues() throws SQLException properties.setProperty("autocommit", "false"); properties.setProperty("readonly", "true"); properties.setProperty("retryAbortsInternally", "false"); + properties.setProperty("rpcPriority", "LOW"); try (Connection connection = DriverManager.getConnection(url, properties)) { testNonDefaultConnection(connection); } @@ -146,7 +147,7 @@ public void testConnectWithPropertiesWithNonDefaultValues() throws SQLException @Test public void testConnectWithPropertiesWithConflictingValues() throws SQLException { String url = createBaseUrl(); - url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false"; + url = url + ";autocommit=false;readonly=true;retryAbortsInternally=false;rpcPriority=LOW"; if (hasValidKeyFile()) { url = url + ";credentials=" + getKeyFile(); } @@ -154,6 +155,7 @@ public void testConnectWithPropertiesWithConflictingValues() throws SQLException properties.setProperty("autocommit", "true"); properties.setProperty("readonly", "false"); properties.setProperty("retryAbortsInternally", "true"); + properties.setProperty("rpcPriority", "MEDIUM"); try (Connection connection = DriverManager.getConnection(url, properties)) { testNonDefaultConnection(connection); } From abfcf90db716f74e349ed94778e862d72b497078 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 06:56:34 +0000 Subject: [PATCH 0586/1979] chore: release 2.5.4 (#674) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.3...v2.5.4) (2021-11-17) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.16.0 ([#673](https://www.github.com/googleapis/java-spanner-jdbc/issues/673)) ([ca09466](https://www.github.com/googleapis/java-spanner-jdbc/commit/ca094660b26ce851f981303db8ca830761f492d8)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c59230d1ce67..59dc697888d8 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.3...v2.5.4) (2021-11-17) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.16.0 ([#673](https://www.github.com/googleapis/java-spanner-jdbc/issues/673)) ([b4cc056](https://www.github.com/googleapis/java-spanner-jdbc/commit/b4cc0568e440b6a377cb4d8224c46057cd3ce1ee)) + ### [2.5.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.2...v2.5.3) (2021-11-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fdb6a861377f..cba37838f639 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.4-SNAPSHOT + 2.5.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 243af5cd0287..0f33f2028104 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.4-SNAPSHOT + 2.5.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e0d7cfd7f226..e00c5fc20ced 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.3:2.5.4-SNAPSHOT +google-cloud-spanner-jdbc:2.5.4:2.5.4 From b592003adb7555d721b6bbde2d81c6962c48e8bc Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 07:02:21 +0000 Subject: [PATCH 0587/1979] chore: release 2.5.5-SNAPSHOT (#675) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cba37838f639..97d73f861e1f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.4 + 2.5.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0f33f2028104..bbb8842649aa 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.4 + 2.5.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e00c5fc20ced..096d8e918938 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.4:2.5.4 +google-cloud-spanner-jdbc:2.5.4:2.5.5-SNAPSHOT From 859c6705af62c1082c831f9df1d0419ed5063844 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Nov 2021 18:50:10 +0100 Subject: [PATCH 0588/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.2 (#676) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.1` -> `1.2.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.2/compatibility-slim/1.2.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.2/confidence-slim/1.2.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.2`](https://togithub.com/googleapis/java-shared-config/blob/master/CHANGELOG.md#​122-httpswwwgithubcomgoogleapisjava-shared-configcomparev121v122-2021-11-16) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.1...v1.2.2)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97d73f861e1f..3e5b1af1f368 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.1 + 1.2.2 From 9d7241dbe52a2c8147e056db030872e686fb9d90 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 17 Nov 2021 23:14:32 +0100 Subject: [PATCH 0589/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.4 (#677) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.3` -> `2.5.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.4/compatibility-slim/2.5.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.4/confidence-slim/2.5.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.4`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​254-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev253v254-2021-11-17) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.3...v2.5.4)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0b99fb77665a..91c5a9662668 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.3 + 2.5.4 From f2f4650dec669ac20939a88ccca245e53be6534a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 19 Nov 2021 20:48:15 +0100 Subject: [PATCH 0590/1979] test(deps): update dependency org.mockito:mockito-core to v4.1.0 (#679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.0.0` -> `4.1.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.1.0/compatibility-slim/4.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.1.0/confidence-slim/4.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.1.0`](https://togithub.com/mockito/mockito/releases/v4.1.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.0.0...v4.1.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.1.0 - 2021-11-19 - [20 commit(s)](https://togithub.com/mockito/mockito/compare/v4.0.0...v4.1.0) by Lars Vogel, Mikaël Francoeur, S.YAMAMOTO, Tim van der Lippe, dependabot\[bot] - Disable memory test [(#​2480)](https://togithub.com/mockito/mockito/pull/2480) - Bump appcompat from 1.3.1 to 1.4.0 [(#​2477)](https://togithub.com/mockito/mockito/pull/2477) - Bump kotlinVersion from 1.5.31 to 1.6.0 [(#​2474)](https://togithub.com/mockito/mockito/pull/2474) - Bump versions.bytebuddy from 1.12.0 to 1.12.1 [(#​2472)](https://togithub.com/mockito/mockito/pull/2472) - Bump com.diffplug.gradle.spotless from 4.5.1 to 6.0.0 [(#​2471)](https://togithub.com/mockito/mockito/pull/2471) - Bump versions.bytebuddy from 1.11.22 to 1.12.0 [(#​2469)](https://togithub.com/mockito/mockito/pull/2469) - Bump versions.errorprone from 2.9.0 to 2.10.0 [(#​2466)](https://togithub.com/mockito/mockito/pull/2466) - Bump auto-service from 1.0 to 1.0.1 [(#​2463)](https://togithub.com/mockito/mockito/pull/2463) - Bump actions/checkout from 2.3.5 to 2.4.0 [(#​2462)](https://togithub.com/mockito/mockito/pull/2462) - Fixes [#​2460](https://togithub.com/mockito/mockito/issues/2460): Remove a sentence commits to a particular version [(#​2461)](https://togithub.com/mockito/mockito/pull/2461) - Clarify Javadoc of RETURNS_SMART_NULLS, default answer in Mockito 4.0.0? [(#​2460)](https://togithub.com/mockito/mockito/issues/2460) - Bump versions.bytebuddy from 1.11.21 to 1.11.22 [(#​2458)](https://togithub.com/mockito/mockito/pull/2458) - Updated readme with the latest Mockito version [(#​2456)](https://togithub.com/mockito/mockito/pull/2456) - Bump core-ktx from 1.6.0 to 1.7.0 [(#​2454)](https://togithub.com/mockito/mockito/pull/2454) - Bump google-java-format from 1.11.0 to 1.12.0 [(#​2450)](https://togithub.com/mockito/mockito/pull/2450) - Bump versions.bytebuddy from 1.11.20 to 1.11.21 [(#​2448)](https://togithub.com/mockito/mockito/pull/2448) - Use new CodeCov uploader [(#​2447)](https://togithub.com/mockito/mockito/pull/2447) - Bump actions/checkout from 2.3.4 to 2.3.5 [(#​2445)](https://togithub.com/mockito/mockito/pull/2445) - Fixes [#​2389](https://togithub.com/mockito/mockito/issues/2389) : Parallel use of mocks with deep stubbing may lead to ConcurrentModificationException [(#​2444)](https://togithub.com/mockito/mockito/pull/2444) - Bump versions.bytebuddy from 1.11.19 to 1.11.20 [(#​2443)](https://togithub.com/mockito/mockito/pull/2443) - Parallel use of mocks with deep stubbing may lead to ConcurrentModificationException [(#​2389)](https://togithub.com/mockito/mockito/issues/2389) - Add annotation to mark a type as DoNotMock [(#​1833)](https://togithub.com/mockito/mockito/pull/1833) - Cannot mock this class: class java.io.InputStream with Java 13 [(#​1827)](https://togithub.com/mockito/mockito/issues/1827) - Cannot mock wrapper types, String.class or Class.class [(#​1734)](https://togithub.com/mockito/mockito/issues/1734)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3e5b1af1f368..e80a509314d5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 4.0.0 + 4.1.0 2.2 From 35ce35285f621c3c1c04ecb91bcdcac95f23800f Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 18:36:31 +0000 Subject: [PATCH 0591/1979] chore: remove enable-samples profile (#1284) (#680) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/build.sh | 1 - java-spanner-jdbc/CONTRIBUTING.md | 61 +++------------------ 3 files changed, 8 insertions(+), 56 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 886d09496d14..88d9b926c155 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:14ecf64ec36f67c7bf04e3dc0f68eafcc01df3955121c38862b695e2ae7515d8 + digest: sha256:5b8c790f57cca57e6b37ba25f79291265c218cea3e6ba9714b001910ab3f1419 diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index ecb23d27ea13..23c2c493814a 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -91,7 +91,6 @@ samples) pushd ${SAMPLES_DIR} mvn -B \ - -Penable-samples \ -ntp \ -DtrimStackTrace=false \ -Dclirr.skip=true \ diff --git a/java-spanner-jdbc/CONTRIBUTING.md b/java-spanner-jdbc/CONTRIBUTING.md index f2dbdee06bc3..b65dd279c946 100644 --- a/java-spanner-jdbc/CONTRIBUTING.md +++ b/java-spanner-jdbc/CONTRIBUTING.md @@ -53,12 +53,12 @@ mvn -Penable-integration-tests clean verify ## Code Samples -Code Samples must be bundled in separate Maven modules, and guarded by a -Maven profile with the name `enable-samples`. +All code samples must be in compliance with the [java sample formatting guide][3]. +Code Samples must be bundled in separate Maven modules. The samples must be separate from the primary project for a few reasons: -1. Primary projects have a minimum Java version of Java 7 whereas samples have - a minimum Java version of Java 8. Due to this we need the ability to +1. Primary projects have a minimum Java version of Java 8 whereas samples can have + Java version of Java 11. Due to this we need the ability to selectively exclude samples from a build run. 2. Many code samples depend on external GCP services and need credentials to access the service. @@ -68,39 +68,16 @@ The samples must be separate from the primary project for a few reasons: ### Building ```bash -mvn -Penable-samples clean verify +mvn clean verify ``` Some samples require access to GCP services and require a service account: ```bash export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json -mvn -Penable-samples clean verify +mvn clean verify ``` -### Profile Config - -1. To add samples in a profile to your Maven project, add the following to your -`pom.xml` - - ```xml - - [...] - - - enable-samples - - sample - - - - [...] - - ``` - -2. [Activate](#profile-activation) the profile. -3. Define your samples in a normal Maven project in the `samples/` directory. - ### Code Formatting Code in this repo is formatted with @@ -110,30 +87,6 @@ To run formatting on your project, you can run: mvn com.coveo:fmt-maven-plugin:format ``` -### Profile Activation - -To include code samples when building and testing the project, enable the -`enable-samples` Maven profile. - -#### Command line - -To activate the Maven profile on the command line add `-Penable-samples` to your -Maven command. - -#### Maven `settings.xml` - -To activate the Maven profile in your `~/.m2/settings.xml` add an entry of -`enable-samples` following the instructions in [Active Profiles][2]. - -This method has the benefit of applying to all projects you build (and is -respected by IntelliJ IDEA) and is recommended if you are going to be -contributing samples to several projects. - -#### IntelliJ IDEA - -To activate the Maven Profile inside IntelliJ IDEA, follow the instructions in -[Activate Maven profiles][3] to activate `enable-samples`. - [1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account [2]: https://maven.apache.org/settings.html#Active_Profiles -[3]: https://www.jetbrains.com/help/idea/work-with-maven-profiles.html#activate_maven_profiles +[3]: https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md \ No newline at end of file From bf37ebf8c7880a95ac2f8102ee77d445f125f783 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 3 Dec 2021 17:14:33 +0100 Subject: [PATCH 0592/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.1 (#684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.5.0` -> `2.5.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.5.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.5.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.5.1/compatibility-slim/2.5.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.5.1/confidence-slim/2.5.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.5.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/master/CHANGELOG.md#​251-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare250v251-2021-12-03) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.5.0...v2.5.1)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e80a509314d5..e7b10dddb416 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.5.0 + 2.5.1 pom import From a41ef4a6417222c4d7ee468d858e833e80f64cb1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 3 Dec 2021 16:24:24 +0000 Subject: [PATCH 0593/1979] chore: release 2.5.5 (#685) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.4...v2.5.5) (2021-12-03) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.1 ([#684](https://www.github.com/googleapis/java-spanner-jdbc/issues/684)) ([bf37ebf](https://www.github.com/googleapis/java-spanner-jdbc/commit/bf37ebf8c7880a95ac2f8102ee77d445f125f783)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 59dc697888d8..399eeca8ca00 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.4...v2.5.5) (2021-12-03) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.1 ([#684](https://www.github.com/googleapis/java-spanner-jdbc/issues/684)) ([a2582d3](https://www.github.com/googleapis/java-spanner-jdbc/commit/a2582d3fbd3f0ea093477914e3a09af235e76595)) + ### [2.5.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.3...v2.5.4) (2021-11-17) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e7b10dddb416..471304befe42 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.5-SNAPSHOT + 2.5.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index bbb8842649aa..cc6d576c0f76 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.5-SNAPSHOT + 2.5.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 096d8e918938..93de39f6203f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.4:2.5.5-SNAPSHOT +google-cloud-spanner-jdbc:2.5.5:2.5.5 From cbdd8ee4f3b51cc7107283de41bc3738f2f5dc35 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 3 Dec 2021 16:30:24 +0000 Subject: [PATCH 0594/1979] chore: release 2.5.6-SNAPSHOT (#686) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 471304befe42..e1e8a461b189 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.5 + 2.5.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index cc6d576c0f76..1da3a663f3b9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.5 + 2.5.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 93de39f6203f..6d2b55dca955 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.5:2.5.5 +google-cloud-spanner-jdbc:2.5.5:2.5.6-SNAPSHOT From f03ebc6560239a27907620b32bab3bf5e5d85f80 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 6 Dec 2021 18:12:15 +0000 Subject: [PATCH 0595/1979] fix(java): add -ntp flag to native image testing command (#1299) (#688) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 88d9b926c155..3d2f8282468e 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:5b8c790f57cca57e6b37ba25f79291265c218cea3e6ba9714b001910ab3f1419 + digest: sha256:a4d7b2cfc6a9d6b378a6b2458740eae15fcab28854bd23dad3a15102d2e47c87 diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 23c2c493814a..583b1f994c4c 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -71,7 +71,7 @@ integration) ;; graalvm) # Run Unit and Integration Tests with Native Image - mvn test -Pnative -Penable-integration-tests + mvn -ntp -Pnative -Penable-integration-tests test RETURN_CODE=$? ;; samples) From 5fe8d73aaa3b691bf8a2ef00917dbe71cdc27646 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 6 Dec 2021 23:28:24 +0100 Subject: [PATCH 0596/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.5 (#687) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.4` -> `2.5.5` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.5/compatibility-slim/2.5.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.5/confidence-slim/2.5.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.5`](https://togithub.com/googleapis/java-spanner-jdbc/blob/master/CHANGELOG.md#​255-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev254v255-2021-12-03) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.4...v2.5.5)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 91c5a9662668..a89f49d98216 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.4 + 2.5.5 From ebb3bc8ae0b2f889e92c72213384dc377108bd0e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 7 Dec 2021 00:24:18 +0100 Subject: [PATCH 0597/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.2.0 (#683) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.samples:shared-configuration](https://togithub.com/GoogleCloudPlatform/java-repo-tools) | `1.0.23` -> `1.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud.samples:shared-configuration/1.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud.samples:shared-configuration/1.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud.samples:shared-configuration/1.2.0/compatibility-slim/1.0.23)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud.samples:shared-configuration/1.2.0/confidence-slim/1.0.23)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    GoogleCloudPlatform/java-repo-tools ### [`v1.2.0`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.24...v1.2.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.24...v1.2.0) ### [`v1.0.24`](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.23...v1.0.24) [Compare Source](https://togithub.com/GoogleCloudPlatform/java-repo-tools/compare/v1.0.23...v1.0.24)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a89f49d98216..ab7953e5a6a8 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.23 + 1.2.0 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index b50770aaecc9..87a742b88074 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.0.23 + 1.2.0 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1da3a663f3b9..238f56f32f07 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.23 + 1.2.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index de2b4cbd4dba..fcc51d5f2d1b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.23 + 1.2.0 From a48aeaa8bd49cbd3e87e4a0dd5c85ebdcec743b9 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Tue, 7 Dec 2021 12:24:15 -0500 Subject: [PATCH 0598/1979] chore: make owlbot check required (#691) --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index c6354959c2f8..f9649fb057e9 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -37,6 +37,7 @@ branchProtectionRules: - "units (11)" - "Kokoro - Test: Integration" - "cla/google" + - OwlBot Post Processor # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `main` From d580afba8397f70c0a55c173ff4afc79f89e6e40 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 9 Dec 2021 00:06:21 +0100 Subject: [PATCH 0599/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24.1.0 (#692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `24.0.0` -> `24.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.0/compatibility-slim/24.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.0/confidence-slim/24.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fcc51d5f2d1b..5e0eab46f5e7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.0.0 + 24.1.0 pom import From 947b9c58b7d6846905b7e56710c366fe5d059a5f Mon Sep 17 00:00:00 2001 From: skuruppu Date: Tue, 14 Dec 2021 11:16:40 +1100 Subject: [PATCH 0600/1979] chore: auto-assign issues to new repo owner (#682) --- java-spanner-jdbc/.github/blunderbuss.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml index ff884f2733ff..4ad6c6606496 100644 --- a/java-spanner-jdbc/.github/blunderbuss.yml +++ b/java-spanner-jdbc/.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: - - thiagotnunes + - ansh0l assign_prs_by: - labels: - samples From 9f6ca487f6a0a27d21a67808e062358418d88d09 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 17 Dec 2021 06:32:58 +0100 Subject: [PATCH 0601/1979] test(deps): update dependency org.mockito:mockito-core to v4.2.0 (#693) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e1e8a461b189..e559a7157c96 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 4.1.0 + 4.2.0 2.2 From 62d51f13b37963e6abdf5c52968b481f5c23c749 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Fri, 17 Dec 2021 18:12:04 +1100 Subject: [PATCH 0602/1979] deps: update OpenCensus API to 0.30.0 (#694) --- java-spanner-jdbc/pom.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e559a7157c96..3c7719d40fd0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -55,6 +55,7 @@ 1.1.3 4.2.0 2.2 + 0.30.0 @@ -62,7 +63,7 @@ com.google.cloud google-cloud-spanner-bom - 6.16.0 + 6.17.3 pom import @@ -73,6 +74,16 @@ pom import + + io.opencensus + opencensus-api + ${opencensus.version} + + + io.opencensus + opencensus-contrib-grpc-util + ${opencensus.version} + From ab2edc63fe2073ff5eb03aa501eeddb3406ac37f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 18:31:50 +1100 Subject: [PATCH 0603/1979] chore: release 2.5.6 (#689) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 399eeca8ca00..3d57b636819b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +### [2.5.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.5...v2.5.6) (2021-12-17) + + +### Bug Fixes + +* **java:** add -ntp flag to native image testing command ([#1299](https://www.github.com/googleapis/java-spanner-jdbc/issues/1299)) ([#688](https://www.github.com/googleapis/java-spanner-jdbc/issues/688)) ([4438aca](https://www.github.com/googleapis/java-spanner-jdbc/commit/4438aca73b9c8b33fa1edd23f823d87a093a6d59)) + + +### Dependencies + +* update OpenCensus API to 0.30.0 ([#694](https://www.github.com/googleapis/java-spanner-jdbc/issues/694)) ([345f136](https://www.github.com/googleapis/java-spanner-jdbc/commit/345f1366a7dd96f3b28afd353c5c23ebeff60c6b)) + ### [2.5.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.4...v2.5.5) (2021-12-03) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3c7719d40fd0..194099e3ec00 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.6-SNAPSHOT + 2.5.6 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 238f56f32f07..1713bc2f8360 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.6-SNAPSHOT + 2.5.6 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6d2b55dca955..b7e01f810b49 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.5:2.5.6-SNAPSHOT +google-cloud-spanner-jdbc:2.5.6:2.5.6 From 72f644f4e9619205f077c71929c05b2f062dd80a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 17 Dec 2021 07:38:12 +0000 Subject: [PATCH 0604/1979] chore: release 2.5.7-SNAPSHOT (#695) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 194099e3ec00..d4596f9054d3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.6 + 2.5.7-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1713bc2f8360..50cd9591ddad 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.6 + 2.5.7-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b7e01f810b49..e249076f445f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.6:2.5.6 +google-cloud-spanner-jdbc:2.5.6:2.5.7-SNAPSHOT From 8236d38f3b3115d9279bf848151f7975757563ea Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 17 Dec 2021 14:19:57 +0100 Subject: [PATCH 0605/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.6 (#696) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ab7953e5a6a8..f198e70d0e47 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.5 + 2.5.6 From 303568b1ab51c1b73791edcce9357357f2d698ad Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Tue, 21 Dec 2021 14:42:12 -0500 Subject: [PATCH 0606/1979] chore: add enumeration type of library (#697) --- java-spanner-jdbc/.repo-metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index c8768f786ab5..ba087567a76b 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -9,6 +9,7 @@ "repo": "googleapis/java-spanner-jdbc", "repo_short": "java-spanner-jdbc", "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc", + "library_type": "OTHER", "codeowner_team": "@googleapis/api-spanner-java" } From dc5bee60d6f5a4147f8edeef794a2a3a7d872088 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 28 Dec 2021 21:44:29 +0100 Subject: [PATCH 0607/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24.1.1 (#698) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `24.1.0` -> `24.1.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.1/compatibility-slim/24.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.1/confidence-slim/24.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5e0eab46f5e7..4a398b79365b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.1.0 + 24.1.1 pom import From b88e68cedcf36c0d27d1883849695cab038d8753 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 5 Jan 2022 23:54:15 +0100 Subject: [PATCH 0608/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.3 (#701) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.2` -> `1.2.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.3/compatibility-slim/1.2.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.3/confidence-slim/1.2.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.3`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​123-httpswwwgithubcomgoogleapisjava-shared-configcomparev122v123-2022-01-04) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.2...v1.2.3)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d4596f9054d3..344e03342650 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.2 + 1.2.3 From 9525e638de4a840ced4c59ca497ac15cfe57a5f0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 6 Jan 2022 20:02:27 +0100 Subject: [PATCH 0609/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.4 (#702) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.3` -> `1.2.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.4/compatibility-slim/1.2.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.4/confidence-slim/1.2.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.4`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​124-httpswwwgithubcomgoogleapisjava-shared-configcomparev123v124-2022-01-06) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.3...v1.2.4)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 344e03342650..15fccc87f0d0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.3 + 1.2.4 From ac5d218c43bc183a992db596b11d9c82c1172360 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 Jan 2022 04:30:14 +0100 Subject: [PATCH 0610/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24.1.2 (#703) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `24.1.1` -> `24.1.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.2/compatibility-slim/24.1.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.1.2/confidence-slim/24.1.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 4a398b79365b..e46a296e649a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.1.1 + 24.1.2 pom import From 680e9a715bad959843f7c683b2f571d073379de9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 Jan 2022 16:24:17 +0100 Subject: [PATCH 0611/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.6.0 (#704) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.5.1` -> `2.6.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.6.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.6.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.6.0/compatibility-slim/2.5.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.6.0/confidence-slim/2.5.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.6.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​260-httpswwwgithubcomgoogleapisjava-shared-dependenciescompare251v260-2022-01-07) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.5.1...v2.6.0) ##### Bug Fixes - **java:** add -ntp flag to native image testing command ([#​1299](https://www.togithub.com/googleapis/java-shared-dependencies/issues/1299)) ([#​546](https://www.togithub.com/googleapis/java-shared-dependencies/issues/546)) ([d8bb8d9](https://www.github.com/googleapis/java-shared-dependencies/commit/d8bb8d9d8e3b8c582f768cd3164e8580ec334511)) - **java:** run Maven in plain console-friendly mode ([#​1301](https://www.togithub.com/googleapis/java-shared-dependencies/issues/1301)) ([#​557](https://www.togithub.com/googleapis/java-shared-dependencies/issues/557)) ([6b57d08](https://www.github.com/googleapis/java-shared-dependencies/commit/6b57d08816ec6c1dfb637cae022624e896930ad8)) ##### Dependencies - gRPC upgrade to 1.43.2 ([#​567](https://www.togithub.com/googleapis/java-shared-dependencies/issues/567)) ([c946655](https://www.github.com/googleapis/java-shared-dependencies/commit/c94665571f26d24fbbb3f89ef5a3db99663bfdba)) - update dependency com.google.api-client:google-api-client-bom to v1.33.0 ([#​563](https://www.togithub.com/googleapis/java-shared-dependencies/issues/563)) ([0aedddb](https://www.github.com/googleapis/java-shared-dependencies/commit/0aedddb9a535753767d56f5910f355c7a1c8509c)) - update dependency com.google.api:api-common to v2.1.2 ([2f154a3](https://www.github.com/googleapis/java-shared-dependencies/commit/2f154a3ff759211438c72859e98b314c7ff8405f)) - update dependency com.google.http-client:google-http-client-bom to v1.41.0 ([#​562](https://www.togithub.com/googleapis/java-shared-dependencies/issues/562)) ([6da0735](https://www.github.com/googleapis/java-shared-dependencies/commit/6da0735d4db9df998d11c549488a024b800bed65)) - update dependency io.grpc:grpc-bom to v1.43.1 ([#​553](https://www.togithub.com/googleapis/java-shared-dependencies/issues/553)) ([b787c8f](https://www.github.com/googleapis/java-shared-dependencies/commit/b787c8f2032b7ffc9797158c3ff214b7813f34b7)) - update dependency org.apache.httpcomponents:httpcore to v4.4.15 ([#​550](https://www.togithub.com/googleapis/java-shared-dependencies/issues/550)) ([e2d3dba](https://www.github.com/googleapis/java-shared-dependencies/commit/e2d3dbad6dd54c117abb5ab1b6137cfee4e5a32b)) - update dependency org.checkerframework:checker-qual to v3.20.0 ([#​549](https://www.togithub.com/googleapis/java-shared-dependencies/issues/549)) ([586df59](https://www.github.com/googleapis/java-shared-dependencies/commit/586df5949d4ddca11d0705d696882c32d8436c31)) - update gax.version to v2.8.0 ([#​564](https://www.togithub.com/googleapis/java-shared-dependencies/issues/564)) ([9ad5d4f](https://www.github.com/googleapis/java-shared-dependencies/commit/9ad5d4f5385753a0c5739ef400f5d346e3342b84)) - update gax.version to v2.8.1 ([2f154a3](https://www.github.com/googleapis/java-shared-dependencies/commit/2f154a3ff759211438c72859e98b314c7ff8405f)) - update google.common-protos.version to v2.7.1 ([#​561](https://www.togithub.com/googleapis/java-shared-dependencies/issues/561)) ([9aa860d](https://www.github.com/googleapis/java-shared-dependencies/commit/9aa860d92f745f1d4382eb16439bf17ac6ca8ae9)) - update google.core.version to v2.3.5 ([#​565](https://www.togithub.com/googleapis/java-shared-dependencies/issues/565)) ([2f154a3](https://www.github.com/googleapis/java-shared-dependencies/commit/2f154a3ff759211438c72859e98b314c7ff8405f)) - update iam.version to v1.2.0 ([#​547](https://www.togithub.com/googleapis/java-shared-dependencies/issues/547)) ([3232c82](https://www.github.com/googleapis/java-shared-dependencies/commit/3232c828b628cb604a200b3e569e56e758e5e11d)) - upgrading protobuf to 3.19.2 ([#​560](https://www.togithub.com/googleapis/java-shared-dependencies/issues/560)) ([7ef3325](https://www.github.com/googleapis/java-shared-dependencies/commit/7ef33250f5473348d3546210b7a534360f476101)) ##### [2.5.1](https://www.github.com/googleapis/java-shared-dependencies/compare/2.5.0...v2.5.1) (2021-12-03) ##### Dependencies - update dependency com.google.api:api-common to v2.1.1 ([#​533](https://www.togithub.com/googleapis/java-shared-dependencies/issues/533)) ([4e23adb](https://www.github.com/googleapis/java-shared-dependencies/commit/4e23adb666dfaa18ae8bf869aca030153de16d62)) - update gax.version to v2.7.1 ([#​544](https://www.togithub.com/googleapis/java-shared-dependencies/issues/544)) ([5a0c480](https://www.github.com/googleapis/java-shared-dependencies/commit/5a0c480671fa834e600edc6ac6fe77967d1b79b3)) - update google.common-protos.version to v2.7.0 ([#​542](https://www.togithub.com/googleapis/java-shared-dependencies/issues/542)) ([af97eb5](https://www.github.com/googleapis/java-shared-dependencies/commit/af97eb5d9cff397080fdb3d4a6dbf7c2692e0358)) - update google.core.version to v2.3.3 ([#​534](https://www.togithub.com/googleapis/java-shared-dependencies/issues/534)) ([885acef](https://www.github.com/googleapis/java-shared-dependencies/commit/885acefe4ff5313eb53dc43b4825ca597b97dcfd))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 15fccc87f0d0..455a50c31255 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -70,7 +70,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.5.1 + 2.6.0 pom import From a52fad7ede7ab6a5699974ccb45ff3874af68097 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 15:32:13 +0000 Subject: [PATCH 0612/1979] chore: release 2.5.7 (#705) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.7](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.6...v2.5.7) (2022-01-07) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.6.0 ([#704](https://www.github.com/googleapis/java-spanner-jdbc/issues/704)) ([680e9a7](https://www.github.com/googleapis/java-spanner-jdbc/commit/680e9a715bad959843f7c683b2f571d073379de9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 3d57b636819b..926e7b5b3a54 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.7](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.6...v2.5.7) (2022-01-07) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.6.0 ([#704](https://www.github.com/googleapis/java-spanner-jdbc/issues/704)) ([bae659c](https://www.github.com/googleapis/java-spanner-jdbc/commit/bae659cac5a010c17767cdf4b3569e654efb605c)) + ### [2.5.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.5...v2.5.6) (2021-12-17) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 455a50c31255..00969e71071c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.7-SNAPSHOT + 2.5.7 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 50cd9591ddad..caea6a9df2c4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.7-SNAPSHOT + 2.5.7 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e249076f445f..9ed00556d9d6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.6:2.5.7-SNAPSHOT +google-cloud-spanner-jdbc:2.5.7:2.5.7 From 74423411e6c7e5540e1ed66588e53fb7fabfaeda Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 15:44:14 +0000 Subject: [PATCH 0613/1979] chore: release 2.5.8-SNAPSHOT (#706) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 00969e71071c..ebb28d59e9fc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.7 + 2.5.8-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index caea6a9df2c4..405084be7485 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.7 + 2.5.8-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9ed00556d9d6..bbbfe52c97a4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.7:2.5.7 +google-cloud-spanner-jdbc:2.5.7:2.5.8-SNAPSHOT From 6d8e7df1979feafa1422d813690e617a7e094f6a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 Jan 2022 21:14:37 +0100 Subject: [PATCH 0614/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.17.4 (#709) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.17.3` -> `6.17.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.17.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.17.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.17.4/compatibility-slim/6.17.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.17.4/confidence-slim/6.17.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.17.4`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6174-httpswwwgithubcomgoogleapisjava-spannercomparev6173v6174-2022-01-07) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.17.3...v6.17.4)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ebb28d59e9fc..8a2d14c2e56f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -63,7 +63,7 @@ com.google.cloud google-cloud-spanner-bom - 6.17.3 + 6.17.4 pom import From a854ec2c774dc473a0923228e93ee8863acd7f64 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 20:28:20 +0000 Subject: [PATCH 0615/1979] chore: release 2.5.8 (#710) :robot: I have created a release \*beep\* \*boop\* --- ### [2.5.8](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.7...v2.5.8) (2022-01-07) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.17.4 ([#709](https://www.github.com/googleapis/java-spanner-jdbc/issues/709)) ([6d8e7df](https://www.github.com/googleapis/java-spanner-jdbc/commit/6d8e7df1979feafa1422d813690e617a7e094f6a)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 926e7b5b3a54..91bac22f3db5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.8](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.7...v2.5.8) (2022-01-07) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.17.4 ([#709](https://www.github.com/googleapis/java-spanner-jdbc/issues/709)) ([bd12d7c](https://www.github.com/googleapis/java-spanner-jdbc/commit/bd12d7c33b18ceb1df417df8e275ffa745b195b2)) + ### [2.5.7](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.6...v2.5.7) (2022-01-07) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8a2d14c2e56f..336badad8868 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.8-SNAPSHOT + 2.5.8 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 405084be7485..0aa3f03f16b3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.8-SNAPSHOT + 2.5.8 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bbbfe52c97a4..6e0d132615c6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.7:2.5.8-SNAPSHOT +google-cloud-spanner-jdbc:2.5.8:2.5.8 From 147acb581e4302ee7a7605ddfbbab5b878549a10 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 7 Jan 2022 20:38:25 +0000 Subject: [PATCH 0616/1979] chore: release 2.5.9-SNAPSHOT (#711) :robot: I have created a release \*beep\* \*boop\* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 336badad8868..67c1173de734 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.8 + 2.5.9-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0aa3f03f16b3..477a06fdc9a8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.8 + 2.5.9-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6e0d132615c6..b5b50cfb1d5f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.8:2.5.8 +google-cloud-spanner-jdbc:2.5.8:2.5.9-SNAPSHOT From 75986f616bc6f69bf81563a2926c95622572a102 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 10 Jan 2022 19:22:35 +0000 Subject: [PATCH 0617/1979] chore(owlbot-java): disable re-writing clirr file in owlbot java post-processor (#1320) (#712) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/build.sh | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 3d2f8282468e..20c6ee3c30ca 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:a4d7b2cfc6a9d6b378a6b2458740eae15fcab28854bd23dad3a15102d2e47c87 + digest: sha256:efbfc5e9ff713005a037941f8ebcc0c69cc630e3ad934675ee26868705a30897 diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 583b1f994c4c..5e9d243d15ff 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -47,15 +47,15 @@ set +e case ${JOB_TYPE} in test) - mvn test -B -Dclirr.skip=true -Denforcer.skip=true + mvn test -B -ntp -Dclirr.skip=true -Denforcer.skip=true RETURN_CODE=$? ;; lint) - mvn com.coveo:fmt-maven-plugin:check + mvn com.coveo:fmt-maven-plugin:check -B -ntp RETURN_CODE=$? ;; javadoc) - mvn javadoc:javadoc javadoc:test-javadoc + mvn javadoc:javadoc javadoc:test-javadoc -B -ntp RETURN_CODE=$? ;; integration) @@ -71,7 +71,7 @@ integration) ;; graalvm) # Run Unit and Integration Tests with Native Image - mvn -ntp -Pnative -Penable-integration-tests test + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test RETURN_CODE=$? ;; samples) @@ -104,7 +104,7 @@ samples) fi ;; clirr) - mvn -B -Denforcer.skip=true clirr:check + mvn -B -ntp -Denforcer.skip=true clirr:check RETURN_CODE=$? ;; *) From aa6b9f1a2eca5002d2d24ed037e23626881ce945 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Mon, 10 Jan 2022 20:24:17 -0500 Subject: [PATCH 0618/1979] chore: change name to api_shortname in .repo-metadata.json (#713) --- java-spanner-jdbc/.repo-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index ba087567a76b..2f891483ddf5 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -1,5 +1,5 @@ { - "name": "spanner-jdbc", + "api_shortname": "spanner-jdbc", "name_pretty": "Google Cloud Spanner JDBC", "product_documentation": "https://cloud.google.com/spanner/docs/use-oss-jdbc", "client_documentation": "https://cloud.google.com/java/docs/reference/google-cloud-spanner-jdbc/latest/history", From cf8521ede2f6e9f3da6d006b4068174a27598954 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 11 Jan 2022 18:52:24 +0000 Subject: [PATCH 0619/1979] chore(java): update variable name to api_shortname in README template (#1323) (#714) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 20c6ee3c30ca..dddb13b8458b 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:efbfc5e9ff713005a037941f8ebcc0c69cc630e3ad934675ee26868705a30897 + digest: sha256:7f737996c88586c499f7b0c25294c760f9f5eec092289a0e08d2d3f42a069ebb diff --git a/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md index e1182687675c..5f586c61ffcb 100644 --- a/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md +++ b/java-spanner-jdbc/.github/ISSUE_TEMPLATE/bug_report.md @@ -21,7 +21,7 @@ If you are still having issues, please include as much information as possible: General, Core, and Other are also allowed as types 2. OS type and version: 3. Java version: -4. spanner-jdbc version(s): +4. version(s): #### Steps to reproduce From 66c64cac3ccd6ec935c7fc3e4e698b5f42b63cb5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 12 Jan 2022 17:50:17 +0100 Subject: [PATCH 0620/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.5 (#715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.4` -> `1.2.5` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.5/compatibility-slim/1.2.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.5/confidence-slim/1.2.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.5`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​125-httpsgithubcomgoogleapisjava-shared-configcomparev124v125-2022-01-11) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.4...v1.2.5)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 67c1173de734..a4e440a1b17f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.4 + 1.2.5 From 7db58f4f0d29045fc038d20f1ee9d6ef2fabf0d9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 12 Jan 2022 17:58:26 +0100 Subject: [PATCH 0621/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.8 (#707) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.6` -> `2.5.8` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.8/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.8/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.8/compatibility-slim/2.5.6)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.8/confidence-slim/2.5.6)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.8`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​258-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev257v258-2022-01-07) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.7...v2.5.8) ### [`v2.5.7`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​257-httpswwwgithubcomgoogleapisjava-spanner-jdbccomparev256v257-2022-01-07) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.6...v2.5.7)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f198e70d0e47..ef6b9670a2cd 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.6 + 2.5.8 From c3147bc72b1f8d9409f5e6e761861a982ccaa79f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 12 Jan 2022 18:10:18 +0100 Subject: [PATCH 0622/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24.2.0 (#716) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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://togithub.com/GoogleCloudPlatform/cloud-opensource-java) | `24.1.2` -> `24.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.2.0/compatibility-slim/24.1.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.2.0/confidence-slim/24.1.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e46a296e649a..6b2089bbf318 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.1.2 + 24.2.0 pom import From 5ee78fa7ca00f978c269a08d1046f854f3a110b3 Mon Sep 17 00:00:00 2001 From: Neenu Shaji Date: Thu, 13 Jan 2022 17:46:35 -0500 Subject: [PATCH 0623/1979] chore: update release-level in .repo-metadata.json (#718) --- java-spanner-jdbc/.repo-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index 2f891483ddf5..6a760b5e4b77 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -3,7 +3,7 @@ "name_pretty": "Google Cloud Spanner JDBC", "product_documentation": "https://cloud.google.com/spanner/docs/use-oss-jdbc", "client_documentation": "https://cloud.google.com/java/docs/reference/google-cloud-spanner-jdbc/latest/history", - "release_level": "ga", + "release_level": "stable", "language": "java", "min_java_version": 8, "repo": "googleapis/java-spanner-jdbc", From b58215da24304136178a22605bdcb32aab81df18 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 Jan 2022 20:00:37 +0100 Subject: [PATCH 0624/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.3.0 (#708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.codehaus.mojo:build-helper-maven-plugin](http://www.mojohaus.org/build-helper-maven-plugin/) ([source](https://togithub.com/mojohaus/build-helper-maven-plugin)) | `3.2.0` -> `3.3.0` | [![age](https://badges.renovateapi.com/packages/maven/org.codehaus.mojo:build-helper-maven-plugin/3.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.codehaus.mojo:build-helper-maven-plugin/3.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.codehaus.mojo:build-helper-maven-plugin/3.3.0/compatibility-slim/3.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.codehaus.mojo:build-helper-maven-plugin/3.3.0/confidence-slim/3.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ef6b9670a2cd..1684c9feec2b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.2.0 + 3.3.0 add-snippets-source diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 477a06fdc9a8..4da82e47ede9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.2.0 + 3.3.0 add-snippets-source From 02e473181dc931d15f6ca0e6e58f2be64115b4c8 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Wed, 19 Jan 2022 13:00:41 -0500 Subject: [PATCH 0625/1979] fix(java): replace excludedGroup with exclude (#720) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a4e440a1b17f..46a4b0550aec 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -221,7 +221,7 @@ org.apache.maven.plugins maven-surefire-plugin - com.google.cloud.spanner.IntegrationTest + com.google.cloud.spanner.IntegrationTest sponge_log From 8d1fd66c479c8bc161b0d89033d212425d104858 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 21 Jan 2022 21:30:28 +0100 Subject: [PATCH 0626/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.6 (#722) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.5` -> `1.2.6` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.6/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.6/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.6/compatibility-slim/1.2.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.6/confidence-slim/1.2.5)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.6`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​126-httpsgithubcomgoogleapisjava-shared-configcomparev125v126-2022-01-19) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.5...v1.2.6)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 46a4b0550aec..b8c966b52d48 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.5 + 1.2.6 From d9530fe5ac1a72855c69aaa0891482fad759af1b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 24 Jan 2022 21:38:11 +0100 Subject: [PATCH 0627/1979] test(deps): update dependency org.mockito:mockito-core to v4.3.0 (#723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.2.0` -> `4.3.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.0/compatibility-slim/4.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.0/confidence-slim/4.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.3.0`](https://togithub.com/mockito/mockito/releases/v4.3.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.2.0...v4.3.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.3.0 - 2022-01-24 - [20 commit(s)](https://togithub.com/mockito/mockito/compare/v4.2.0...v4.3.0) by Andrew Kozel, John Pyeatt, Liam Miller-Cushon, Thomas Keller, Tim van der Lippe, dependabot\[bot], temp-droid - Fixes [#​2489](https://togithub.com/mockito/mockito/issues/2489) : Fixed issue related to exceptions thrown from the nested spies [(#​2546)](https://togithub.com/mockito/mockito/pull/2546) - Issue 2544 [(#​2545)](https://togithub.com/mockito/mockito/pull/2545) - Bump versions.bytebuddy from 1.12.6 to 1.12.7 [(#​2543)](https://togithub.com/mockito/mockito/pull/2543) - Bump com.diffplug.spotless from 6.1.2 to 6.2.0 [(#​2542)](https://togithub.com/mockito/mockito/pull/2542) - Bump material from 1.4.0 to 1.5.0 [(#​2541)](https://togithub.com/mockito/mockito/pull/2541) - Bump appcompat from 1.4.0 to 1.4.1 [(#​2539)](https://togithub.com/mockito/mockito/pull/2539) - Bump com.diffplug.spotless from 6.1.1 to 6.1.2 [(#​2536)](https://togithub.com/mockito/mockito/pull/2536) - Remove an `@link` [(#​2535)](https://togithub.com/mockito/mockito/pull/2535) - Bump com.diffplug.spotless from 6.1.0 to 6.1.1 [(#​2534)](https://togithub.com/mockito/mockito/pull/2534) - Bump com.github.ben-manes.versions from 0.40.0 to 0.41.0 [(#​2533)](https://togithub.com/mockito/mockito/pull/2533) - Bump assertj-core from 3.21.0 to 3.22.0 [(#​2531)](https://togithub.com/mockito/mockito/pull/2531) - Bump com.github.ben-manes.versions from 0.39.0 to 0.40.0 [(#​2529)](https://togithub.com/mockito/mockito/pull/2529) - Bump com.diffplug.spotless from 6.0.5 to 6.1.0 [(#​2527)](https://togithub.com/mockito/mockito/pull/2527) - Bump kotlinx-coroutines-core from 1.5.2-native-mt to 1.6.0-native-mt [(#​2526)](https://togithub.com/mockito/mockito/pull/2526) - Bump versions.bytebuddy from 1.12.5 to 1.12.6 [(#​2524)](https://togithub.com/mockito/mockito/pull/2524) - Bump com.diffplug.spotless from 6.0.4 to 6.0.5 [(#​2520)](https://togithub.com/mockito/mockito/pull/2520) - Bump versions.bytebuddy from 1.12.4 to 1.12.5 [(#​2519)](https://togithub.com/mockito/mockito/pull/2519) - Fixes [#​2510](https://togithub.com/mockito/mockito/issues/2510): Remove ExpectedException from internal test suite [(#​2518)](https://togithub.com/mockito/mockito/pull/2518) - Fix JavaDoc warnings and enforce zero errors in Gradle [(#​2513)](https://togithub.com/mockito/mockito/pull/2513) - Remove `ExpectedException` from internal test suite [(#​2510)](https://togithub.com/mockito/mockito/issues/2510) - Incomplete stack trace returned from spy inside another spy [(#​2489)](https://togithub.com/mockito/mockito/issues/2489) - Introduce a BOM for Mockito's artifacts (closes [#​2321](https://togithub.com/mockito/mockito/issues/2321)) [(#​2323)](https://togithub.com/mockito/mockito/pull/2323) - Provide a bill of materials (BOM) [(#​2321)](https://togithub.com/mockito/mockito/issues/2321)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b8c966b52d48..e70a3f70aa47 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 4.2.0 + 4.3.0 2.2 0.30.0
    From 14c11a8bce926cc7eba4e06cbf2f09956b0d9eb2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 26 Jan 2022 00:18:30 +0100 Subject: [PATCH 0628/1979] deps: update actions/github-script action to v5 (#724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/github-script](https://togithub.com/actions/github-script) | action | major | `v3` -> `v5` | --- ### Release Notes
    actions/github-script ### [`v5`](https://togithub.com/actions/github-script/compare/v4...v5) [Compare Source](https://togithub.com/actions/github-script/compare/v4...v5) ### [`v4`](https://togithub.com/actions/github-script/compare/v3...v4) [Compare Source](https://togithub.com/actions/github-script/compare/v3...v4)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). From 727ac416808cd7c3cc349b8433a15732e846c8e9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 1 Feb 2022 06:18:03 +0100 Subject: [PATCH 0629/1979] deps: update opencensus.version to v0.31.0 (#727) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e70a3f70aa47..d0fd5aa45782 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -55,7 +55,7 @@ 1.1.3 4.3.0 2.2 - 0.30.0 + 0.31.0
    From d3611b1584f0c3b84d1e3a036c6b7a05c4cbeab7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 1 Feb 2022 06:30:29 +0100 Subject: [PATCH 0630/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.7.0 (#728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.6.0` -> `2.7.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.7.0/compatibility-slim/2.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.7.0/confidence-slim/2.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.7.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​270-httpsgithubcomgoogleapisjava-shared-dependenciescomparev260v270-2022-01-28) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.6.0...v2.7.0) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.13.1 ([#​555](https://togithub.com/googleapis/java-shared-dependencies/issues/555)) ([67b5663](https://togithub.com/googleapis/java-shared-dependencies/commit/67b56635509215fd132b2ffbcaed995a6de93879)) - update dependency com.google.api-client:google-api-client-bom to v1.33.1 ([#​580](https://togithub.com/googleapis/java-shared-dependencies/issues/580)) ([895dba2](https://togithub.com/googleapis/java-shared-dependencies/commit/895dba2afef6c295b0e21a4ccd27feee1b6af8e2)) - update dependency com.google.api:api-common to v2.1.3 ([#​587](https://togithub.com/googleapis/java-shared-dependencies/issues/587)) ([5dbbce8](https://togithub.com/googleapis/java-shared-dependencies/commit/5dbbce80baa045818757912e6db4f222c12b75f6)) - update dependency com.google.auth:google-auth-library-bom to v1.4.0 ([#​578](https://togithub.com/googleapis/java-shared-dependencies/issues/578)) ([c274c62](https://togithub.com/googleapis/java-shared-dependencies/commit/c274c62905192bcc48c82104bf50cbeaa1894c2b)) - update dependency com.google.errorprone:error_prone_annotations to v2.11.0 ([#​582](https://togithub.com/googleapis/java-shared-dependencies/issues/582)) ([314da38](https://togithub.com/googleapis/java-shared-dependencies/commit/314da38c9f12cf425b5d1be8297e9f2a78d13948)) - update dependency com.google.http-client:google-http-client-bom to v1.41.2 ([#​579](https://togithub.com/googleapis/java-shared-dependencies/issues/579)) ([c8df06d](https://togithub.com/googleapis/java-shared-dependencies/commit/c8df06ddb3f4a975e928bbdd9dfae293e81efa39)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.33.0 ([#​576](https://togithub.com/googleapis/java-shared-dependencies/issues/576)) ([3315988](https://togithub.com/googleapis/java-shared-dependencies/commit/3315988059ca0223f078b0f760960674bfa8c04a)) - update dependency com.google.protobuf:protobuf-bom to v3.19.3 ([#​571](https://togithub.com/googleapis/java-shared-dependencies/issues/571)) ([c1931e1](https://togithub.com/googleapis/java-shared-dependencies/commit/c1931e1c4611ca3d1e2afac1c9e983cf1ec4a7de)) - update dependency io.grpc:grpc-bom to v1.44.0 ([#​586](https://togithub.com/googleapis/java-shared-dependencies/issues/586)) ([52c47b7](https://togithub.com/googleapis/java-shared-dependencies/commit/52c47b7425af438ba1a82dac87f9002353a6a87a)) - update dependency org.checkerframework:checker-qual to v3.21.1 ([#​554](https://togithub.com/googleapis/java-shared-dependencies/issues/554)) ([81bbb91](https://togithub.com/googleapis/java-shared-dependencies/commit/81bbb91774ab67161371bfd0dfd143de89dee4c9)) - update gax.version to v2.11.0 ([#​581](https://togithub.com/googleapis/java-shared-dependencies/issues/581)) ([1899612](https://togithub.com/googleapis/java-shared-dependencies/commit/189961226f84cdd4e283780d2c7d4a4dffc3e00c)) - update gax.version to v2.9.0 ([#​573](https://togithub.com/googleapis/java-shared-dependencies/issues/573)) ([ee5e38e](https://togithub.com/googleapis/java-shared-dependencies/commit/ee5e38efea574eeb2b5803192da98ba1ce1c8e6e)) - update google.common-protos.version to v2.7.2 ([#​588](https://togithub.com/googleapis/java-shared-dependencies/issues/588)) ([caac0e6](https://togithub.com/googleapis/java-shared-dependencies/commit/caac0e68e336b801becb6322b5b81fce1824ad8a)) - update google.core.version to v2.4.0 ([#​589](https://togithub.com/googleapis/java-shared-dependencies/issues/589)) ([6a292e3](https://togithub.com/googleapis/java-shared-dependencies/commit/6a292e3530a06d6b228f3154ed4e979ef68d7aeb)) - update iam.version to v1.2.1 ([#​569](https://togithub.com/googleapis/java-shared-dependencies/issues/569)) ([62dd270](https://togithub.com/googleapis/java-shared-dependencies/commit/62dd2705b257c4bb539bfe619234f38d0e13b138)) - update opencensus.version to v0.30.0 ([#​552](https://togithub.com/googleapis/java-shared-dependencies/issues/552)) ([ebae62e](https://togithub.com/googleapis/java-shared-dependencies/commit/ebae62eca75234db4fd571f42b8ed0f6ce1bd1f7)) - update opencensus.version to v0.31.0 ([#​585](https://togithub.com/googleapis/java-shared-dependencies/issues/585)) ([021b066](https://togithub.com/googleapis/java-shared-dependencies/commit/021b066a833af1629c89fcca593d16b9786ee0bf))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d0fd5aa45782..1018039e9230 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -70,7 +70,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.6.0 + 2.7.0 pom import From e4f4a6e50fa1cfea12a64fa4a6c6497f1a5abdd7 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 2 Feb 2022 04:56:45 +0000 Subject: [PATCH 0631/1979] deps(java): update actions/github-script action to v5 (#1339) (#725) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 15 ++++++++++++++- .../.github/workflows/approve-readme.yaml | 2 +- .../.github/workflows/auto-release.yaml | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index dddb13b8458b..be3b9bde4fce 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,3 +1,16 @@ +# Copyright 2022 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. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:7f737996c88586c499f7b0c25294c760f9f5eec092289a0e08d2d3f42a069ebb + digest: sha256:7062473f423f339256346ddbee3d81fb1de6b784fabc2a4d959d7df2c720e375 diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml index 7513acaebcc2..c5132427982f 100644 --- a/java-spanner-jdbc/.github/workflows/approve-readme.yaml +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' steps: - - uses: actions/github-script@v3 + - uses: actions/github-script@v5 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} script: | diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 9b4fd4d8348d..59c7cadde314 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.head_ref, 'release-please') steps: - - uses: actions/github-script@v3 + - uses: actions/github-script@v5 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true From 3aefa8178d42c66d15dfe7b9a1832cfa4c6f2021 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 2 Feb 2022 16:14:48 +0100 Subject: [PATCH 0632/1979] test(deps): update dependency org.mockito:mockito-core to v4.3.1 (#726) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.3.0` -> `4.3.1` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.1/compatibility-slim/4.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.3.1/confidence-slim/4.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.3.1`](https://togithub.com/mockito/mockito/releases/v4.3.1) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.3.0...v4.3.1) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.3.1 - 2022-01-25 - [1 commit(s)](https://togithub.com/mockito/mockito/compare/v4.3.0...v4.3.1) by Stefano Cordio - Add `mockito-core` to the BOM [(#​2550)](https://togithub.com/mockito/mockito/pull/2550)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1018039e9230..dd7e33a78f2a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,7 @@ 3.0.2 1.4.4 1.1.3 - 4.3.0 + 4.3.1 2.2 0.31.0 From d7f3c34fd7224f3fc8623e5446a73fc5b030cc7a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 3 Feb 2022 19:56:35 +0000 Subject: [PATCH 0633/1979] chore: add kokoro config to run nightly integration test on java11.0.14 (#1347) (#731) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- .../.kokoro/nightly/java11-integration.cfg | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index be3b9bde4fce..8807efcad4be 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:7062473f423f339256346ddbee3d81fb1de6b784fabc2a4d959d7df2c720e375 + digest: sha256:7c853edc4136ae8f19f9d46d4569d38de2e446db2eea057f32e412bdba255846 diff --git a/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg b/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg new file mode 100644 index 000000000000..58049cc38f11 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg @@ -0,0 +1,37 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-public-resources/java11014" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration" +} +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "ENABLE_FLAKYBOT" + value: "true" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-it-service-account" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" +} From 7dfbd4eed5606213d645c9a1bef568e5ee6be78e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 3 Feb 2022 21:09:03 +0000 Subject: [PATCH 0634/1979] chore(main): release 2.5.9 (#721) :robot: I have created a release *beep* *boop* --- ### [2.5.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.8...v2.5.9) (2022-02-03) ### Bug Fixes * **java:** replace excludedGroup with exclude ([#720](https://github.com/googleapis/java-spanner-jdbc/issues/720)) ([02e4731](https://github.com/googleapis/java-spanner-jdbc/commit/02e473181dc931d15f6ca0e6e58f2be64115b4c8)) ### Dependencies * **java:** update actions/github-script action to v5 ([#1339](https://github.com/googleapis/java-spanner-jdbc/issues/1339)) ([#725](https://github.com/googleapis/java-spanner-jdbc/issues/725)) ([e4f4a6e](https://github.com/googleapis/java-spanner-jdbc/commit/e4f4a6e50fa1cfea12a64fa4a6c6497f1a5abdd7)) * update actions/github-script action to v5 ([#724](https://github.com/googleapis/java-spanner-jdbc/issues/724)) ([14c11a8](https://github.com/googleapis/java-spanner-jdbc/commit/14c11a8bce926cc7eba4e06cbf2f09956b0d9eb2)) * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.7.0 ([#728](https://github.com/googleapis/java-spanner-jdbc/issues/728)) ([d3611b1](https://github.com/googleapis/java-spanner-jdbc/commit/d3611b1584f0c3b84d1e3a036c6b7a05c4cbeab7)) * update opencensus.version to v0.31.0 ([#727](https://github.com/googleapis/java-spanner-jdbc/issues/727)) ([727ac41](https://github.com/googleapis/java-spanner-jdbc/commit/727ac416808cd7c3cc349b8433a15732e846c8e9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 91bac22f3db5..529679c47797 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +### [2.5.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.8...v2.5.9) (2022-02-03) + + +### Bug Fixes + +* **java:** replace excludedGroup with exclude ([#720](https://github.com/googleapis/java-spanner-jdbc/issues/720)) ([7f13c88](https://github.com/googleapis/java-spanner-jdbc/commit/7f13c88f8c9e509de8c82cb788ab9b4964806381)) + + +### Dependencies + +* **java:** update actions/github-script action to v5 ([#1339](https://github.com/googleapis/java-spanner-jdbc/issues/1339)) ([#725](https://github.com/googleapis/java-spanner-jdbc/issues/725)) ([4f96ec1](https://github.com/googleapis/java-spanner-jdbc/commit/4f96ec1c864b176564ac3200565b5ea524d8adfb)) +* update actions/github-script action to v5 ([#724](https://github.com/googleapis/java-spanner-jdbc/issues/724)) ([5c1d6ff](https://github.com/googleapis/java-spanner-jdbc/commit/5c1d6ff72ba81dac101904f1ebd63e4a09b47c64)) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.7.0 ([#728](https://github.com/googleapis/java-spanner-jdbc/issues/728)) ([b0a32d8](https://github.com/googleapis/java-spanner-jdbc/commit/b0a32d807cdf2458b60437ade38fa46511254701)) +* update opencensus.version to v0.31.0 ([#727](https://github.com/googleapis/java-spanner-jdbc/issues/727)) ([fce0770](https://github.com/googleapis/java-spanner-jdbc/commit/fce077056fbf55395a736dc1f58f8ecbc89eb10d)) + ### [2.5.8](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.7...v2.5.8) (2022-01-07) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dd7e33a78f2a..37da2ebdeba3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.9-SNAPSHOT + 2.5.9 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4da82e47ede9..6c1209ac1b1f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.9-SNAPSHOT + 2.5.9 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b5b50cfb1d5f..f32bd923ad7c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.8:2.5.9-SNAPSHOT +google-cloud-spanner-jdbc:2.5.9:2.5.9 From a1f19072100f8b0f936c163616ce1bf2edfed08f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 4 Feb 2022 01:52:48 +0000 Subject: [PATCH 0635/1979] chore(main): release 2.5.10-SNAPSHOT (#732) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 37da2ebdeba3..35e46670936d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.9 + 2.5.10-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6c1209ac1b1f..b5113fc18b1e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.9 + 2.5.10-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f32bd923ad7c..d703b7e43618 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.9:2.5.9 +google-cloud-spanner-jdbc:2.5.9:2.5.10-SNAPSHOT From 3537f9b5a495d235f26edeb54d71292bea2190b2 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:06:49 +0000 Subject: [PATCH 0636/1979] chore: enable auto release in java (#1349) (#736) * chore: fix auto-release * chore: remove codecov.yml * chore: update license headers for yaml files Source-Link: https://github.com/googleapis/synthtool/commit/5b777277a01a93e7f10c9279521e807b934e78d4 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- .../.github/workflows/approve-readme.yaml | 15 +++++++++++++++ .../.github/workflows/auto-release.yaml | 19 +++++++++++++++++-- java-spanner-jdbc/.github/workflows/ci.yaml | 15 +++++++++++++++ .../.github/workflows/samples.yaml | 15 +++++++++++++++ java-spanner-jdbc/.kokoro/build.bat | 15 +++++++++++++++ 6 files changed, 78 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 8807efcad4be..a8ddd81ae949 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:7c853edc4136ae8f19f9d46d4569d38de2e446db2eea057f32e412bdba255846 + digest: sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml index c5132427982f..1bb182327612 100644 --- a/java-spanner-jdbc/.github/workflows/approve-readme.yaml +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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: auto-merge-readme diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 59c7cadde314..2ba3082bee20 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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: auto-release @@ -16,8 +31,8 @@ jobs: return; } - // only approve PRs like "chore: release " - if ( !context.payload.pull_request.title.startsWith("chore: release") ) { + // only approve PRs like "chore(main): release " + if ( !context.payload.pull_request.title.startsWith("chore(main): release") ) { return; } diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 05de1f60dcf0..6b5e56aaacd1 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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: push: branches: diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index c46230a78c38..d5d964df15fa 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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: samples diff --git a/java-spanner-jdbc/.kokoro/build.bat b/java-spanner-jdbc/.kokoro/build.bat index 05826ad93fe8..cc602c9eba80 100644 --- a/java-spanner-jdbc/.kokoro/build.bat +++ b/java-spanner-jdbc/.kokoro/build.bat @@ -1,3 +1,18 @@ :: See documentation in type-shell-output.bat +# Copyright 2022 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. "C:\Program Files\Git\bin\bash.exe" %~dp0build.sh From 905e4d4997b335ad278c099e114cddaadab64d18 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 00:46:53 +0000 Subject: [PATCH 0637/1979] chore: update auto-release script to fix breaking changes in v5 (#1350) (#737) Source-Link: https://github.com/googleapis/synthtool/commit/53a58c23eb4decb3a17fab07388d42799e158b5f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:3c950ed12391ebaffd1ee66d0374766a1c50144ebe6a7a0042300b2e6bb5856b --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/workflows/auto-release.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index a8ddd81ae949..9786771c434b 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 + digest: sha256:3c950ed12391ebaffd1ee66d0374766a1c50144ebe6a7a0042300b2e6bb5856b diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 2ba3082bee20..18e23230d98f 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -37,7 +37,7 @@ jobs: } // only approve PRs with pom.xml and versions.txt changes - const filesPromise = github.pulls.listFiles.endpoint({ + const filesPromise = github.rest.pulls.listFiles.endpoint({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, @@ -69,7 +69,7 @@ jobs: return; } - const promise = github.pulls.list.endpoint({ + const promise = github.rest.pulls.list.endpoint({ owner: context.repo.owner, repo: context.repo.repo, state: 'open' @@ -86,7 +86,7 @@ jobs: } // approve release PR - await github.pulls.createReview({ + await github.rest.pulls.createReview({ owner: context.repo.owner, repo: context.repo.repo, body: 'Rubber stamped release!', @@ -95,7 +95,7 @@ jobs: }); // attach kokoro:force-run and automerge labels - await github.issues.addLabels({ + await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, From 250449b3e4a959486af5d262488f03a038ad6688 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Feb 2022 18:42:46 +0100 Subject: [PATCH 0638/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.7 (#738) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.6` -> `1.2.7` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/compatibility-slim/1.2.6)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/confidence-slim/1.2.6)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.2.7`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​127-httpsgithubcomgoogleapisjava-shared-configcomparev126v127-2022-02-04) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.6...v1.2.7)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 35e46670936d..f0798785dd85 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.6 + 1.2.7 From 616a6486c741270bf7b51d780ce66105c4509591 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Feb 2022 23:02:49 +0100 Subject: [PATCH 0639/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v24.3.0 (#740) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/GoogleCloudPlatform/cloud-opensource-java)) | `24.2.0` -> `24.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/compatibility-slim/24.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/confidence-slim/24.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6b2089bbf318..c61300540cb2 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.2.0 + 24.3.0 pom import From 7ba346064281e190a0081f15a1cac0fabf6c362a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Feb 2022 20:31:14 +0100 Subject: [PATCH 0640/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.18.0 (#734) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f0798785dd85..ffe49fcf53e1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -63,7 +63,7 @@ com.google.cloud google-cloud-spanner-bom - 6.17.4 + 6.18.0 pom import From 8cc7a5f99eb2be160ee22b7b566f7c96eec59640 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Feb 2022 20:31:24 +0100 Subject: [PATCH 0641/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.9 (#733) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1684c9feec2b..bc336cfef239 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.8 + 2.5.9 From 4d4951675165ea2ed33d4077ed859ffb3f754d44 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Feb 2022 19:42:58 +0000 Subject: [PATCH 0642/1979] chore(main): release 2.5.10 (#741) :robot: I have created a release *beep* *boop* --- ### [2.5.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.9...v2.5.10) (2022-02-09) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.18.0 ([#734](https://github.com/googleapis/java-spanner-jdbc/issues/734)) ([7ba3460](https://github.com/googleapis/java-spanner-jdbc/commit/7ba346064281e190a0081f15a1cac0fabf6c362a)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 529679c47797..4861c0e08045 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.9...v2.5.10) (2022-02-09) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.18.0 ([#734](https://github.com/googleapis/java-spanner-jdbc/issues/734)) ([52f407a](https://github.com/googleapis/java-spanner-jdbc/commit/52f407a5e73d13fdeb9b5438d6e5cbd026cb3942)) + ### [2.5.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.8...v2.5.9) (2022-02-03) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ffe49fcf53e1..5a187a2c13a9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.10-SNAPSHOT + 2.5.10 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b5113fc18b1e..104a48f06c28 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.10-SNAPSHOT + 2.5.10 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d703b7e43618..06d904c05fdb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.9:2.5.10-SNAPSHOT +google-cloud-spanner-jdbc:2.5.10:2.5.10 From 98e2a10e292fec2d7a483e721d53e5f8e2911f3f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Feb 2022 20:18:47 +0000 Subject: [PATCH 0643/1979] chore(main): release 2.5.11-SNAPSHOT (#742) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a187a2c13a9..e6bdafb8023b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.10 + 2.5.11-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 104a48f06c28..d815cb7c4787 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.10 + 2.5.11-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 06d904c05fdb..fb6f45f5d6fc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.10:2.5.10 +google-cloud-spanner-jdbc:2.5.10:2.5.11-SNAPSHOT From b9dc95d9b03ecbb473a7536e37bcb51b43c61858 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 10 Feb 2022 17:48:41 +0100 Subject: [PATCH 0644/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.10 (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.9` -> `2.5.10` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.10/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.10/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.10/compatibility-slim/2.5.9)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.10/confidence-slim/2.5.9)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.10`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2510-httpsgithubcomgoogleapisjava-spanner-jdbccomparev259v2510-2022-02-09) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.9...v2.5.10)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index bc336cfef239..28f36181c291 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.9 + 2.5.10 From 0c0d9860fc1377d7cbfc75e10506502476d761ee Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 11 Feb 2022 20:58:49 +0100 Subject: [PATCH 0645/1979] deps: update actions/github-script action to v6 (#745) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/github-script](https://togithub.com/actions/github-script) | action | major | `v5` -> `v6` | --- ### Release Notes
    actions/github-script ### [`v6`](https://togithub.com/actions/github-script/compare/v5...v6) [Compare Source](https://togithub.com/actions/github-script/compare/v5...v6)
    --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). From 9e9bd31d52b864955e8044372a1560fa51fd03df Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 11 Feb 2022 21:05:03 +0100 Subject: [PATCH 0646/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.3.2 (#744) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-javadoc-plugin](https://maven.apache.org/plugins/) | `3.3.1` -> `3.3.2` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/compatibility-slim/3.3.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/confidence-slim/3.3.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e6bdafb8023b..ed6f279b71ed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -428,7 +428,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + 3.3.2 html From e94b4a4b2a306a1a75ab81874ff89f216c2a4881 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 20:34:47 +0000 Subject: [PATCH 0647/1979] chore(main): release 2.5.11 (#746) :robot: I have created a release *beep* *boop* --- ### [2.5.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.10...v2.5.11) (2022-02-11) ### Dependencies * update actions/github-script action to v6 ([#745](https://github.com/googleapis/java-spanner-jdbc/issues/745)) ([0c0d986](https://github.com/googleapis/java-spanner-jdbc/commit/0c0d9860fc1377d7cbfc75e10506502476d761ee)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4861c0e08045..4c69968212a4 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.5.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.10...v2.5.11) (2022-02-11) + + +### Dependencies + +* update actions/github-script action to v6 ([#745](https://github.com/googleapis/java-spanner-jdbc/issues/745)) ([2ccd5b8](https://github.com/googleapis/java-spanner-jdbc/commit/2ccd5b8ac878c81535c14e404aeaf67e6e41a464)) + ### [2.5.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.9...v2.5.10) (2022-02-09) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ed6f279b71ed..5a8a0bd3b678 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.11-SNAPSHOT + 2.5.11 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d815cb7c4787..856b9a35fd56 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.11-SNAPSHOT + 2.5.11 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fb6f45f5d6fc..8e11d98ba4dc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.10:2.5.11-SNAPSHOT +google-cloud-spanner-jdbc:2.5.11:2.5.11 From 84ecdce6ffb55d7302523191814edbf2b3e9e199 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 21:40:39 +0000 Subject: [PATCH 0648/1979] chore(main): release 2.5.12-SNAPSHOT (#747) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a8a0bd3b678..eb7a3b557490 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.5.11 + 2.5.12-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 856b9a35fd56..86cca42e6cfd 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.11 + 2.5.12-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8e11d98ba4dc..d8da0dce57bd 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.11:2.5.11 +google-cloud-spanner-jdbc:2.5.11:2.5.12-SNAPSHOT From 17cb76c0704256358464d666cbfaaa47fd3cffd6 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 14 Feb 2022 22:53:01 +0100 Subject: [PATCH 0649/1979] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.6.9 (#748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.sonatype.plugins:nexus-staging-maven-plugin](http://www.sonatype.com/) ([source](https://togithub.com/sonatype/nexus-maven-plugins)) | `1.6.8` -> `1.6.9` | [![age](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.9/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.9/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.9/compatibility-slim/1.6.8)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.9/confidence-slim/1.6.8)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 87a742b88074..644e55712f29 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.9 true From 2542b67454f29a507e6e6353f3f1da12eb78e2a7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Feb 2022 17:47:14 +0100 Subject: [PATCH 0650/1979] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.6.10 (#750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.sonatype.plugins:nexus-staging-maven-plugin](http://www.sonatype.com/) ([source](https://togithub.com/sonatype/nexus-maven-plugins)) | `1.6.9` -> `1.6.10` | [![age](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/compatibility-slim/1.6.9)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/confidence-slim/1.6.9)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    sonatype/nexus-maven-plugins ### [`v1.6.10`](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.9...release-1.6.10) [Compare Source](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.9...release-1.6.10)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 644e55712f29..10bbeaf8f17e 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.9 + 1.6.10 true From 353c760c32ad8bf0a9b7fa223fd5589fdc006258 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Feb 2022 19:40:53 +0100 Subject: [PATCH 0651/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.5.11 (#749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.10` -> `2.5.11` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.11/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.11/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.11/compatibility-slim/2.5.10)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.5.11/confidence-slim/2.5.10)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.5.11`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2511-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2510v2511-2022-02-11) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.10...v2.5.11)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 28f36181c291..00cb69104f23 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.10 + 2.5.11 From 54f437fc5ba6afbff490e20f501aecc27a4a77d1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 17 Feb 2022 14:24:52 +0100 Subject: [PATCH 0652/1979] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.6.11 (#751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.sonatype.plugins:nexus-staging-maven-plugin](http://www.sonatype.com/) ([source](https://togithub.com/sonatype/nexus-maven-plugins)) | `1.6.10` -> `1.6.11` | [![age](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.11/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.11/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.11/compatibility-slim/1.6.10)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.11/confidence-slim/1.6.10)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    sonatype/nexus-maven-plugins ### [`v1.6.11`](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.10...release-1.6.11) [Compare Source](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.10...release-1.6.11)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 10bbeaf8f17e..41ecbd1459fa 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.10 + 1.6.11 true From c6b2e916511086c0bfb9b4038acbb9e98ce9430e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 19 Feb 2022 12:20:10 +0100 Subject: [PATCH 0653/1979] feat: add support for PostgreSQL dialect (#739) * feat: add support for PostgreSQL dialect * fix: address review comments * deps: bump java-spanner to 6.19.1 * feat: support automatic dialect detection * deps: remove threeten + add gax * build: use owned instance for integration tests * build: use same instance as the client library --- .../clirr-ignored-differences.xml | 9 + java-spanner-jdbc/pom.xml | 13 +- .../spanner/jdbc/AbstractJdbcConnection.java | 20 + .../jdbc/AbstractJdbcPreparedStatement.java | 5 +- .../spanner/jdbc/AbstractJdbcStatement.java | 5 +- .../spanner/jdbc/AbstractJdbcWrapper.java | 71 ++ .../jdbc/CloudSpannerJdbcConnection.java | 6 + .../cloud/spanner/jdbc/JdbcConnection.java | 5 +- .../cloud/spanner/jdbc/JdbcDataType.java | 26 + .../spanner/jdbc/JdbcParameterMetaData.java | 2 +- .../spanner/jdbc/JdbcParameterStore.java | 188 ++-- .../spanner/jdbc/JdbcPreparedStatement.java | 17 +- .../cloud/spanner/jdbc/JdbcResultSet.java | 67 +- .../spanner/jdbc/JdbcResultSetMetaData.java | 1 + .../cloud/spanner/jdbc/JdbcStatement.java | 9 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 28 +- .../jdbc/DatabaseMetaData_GetColumns.sql | 3 +- .../DatabaseMetaData_GetCrossReferences.sql | 1 + .../jdbc/DatabaseMetaData_GetExportedKeys.sql | 1 + .../jdbc/DatabaseMetaData_GetImportedKeys.sql | 1 + .../jdbc/DatabaseMetaData_GetIndexInfo.sql | 1 + .../jdbc/DatabaseMetaData_GetPrimaryKeys.sql | 1 + .../jdbc/DatabaseMetaData_GetSchemas.sql | 1 + .../jdbc/DatabaseMetaData_GetTables.sql | 1 + .../spanner/jdbc/AbstractJdbcWrapperTest.java | 192 ++++- .../spanner/jdbc/ITAbstractJdbcTest.java | 59 +- .../JdbcConnectionGeneratedSqlScriptTest.java | 22 +- .../spanner/jdbc/JdbcConnectionTest.java | 75 +- ...cDatabaseMetaDataWithMockedServerTest.java | 154 +++- .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 34 +- .../spanner/jdbc/JdbcParameterStoreTest.java | 233 ++++- .../jdbc/JdbcPreparedStatementTest.java | 46 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 24 + .../spanner/jdbc/JdbcSqlScriptVerifier.java | 17 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 43 +- .../spanner/jdbc/JdbcTimeoutSqlTest.java | 17 +- .../jdbc/PgNumericPreparedStatementTest.java | 338 ++++++++ .../spanner/jdbc/PgNumericResultSetTest.java | 801 ++++++++++++++++++ .../spanner/jdbc/it/DialectTestParameter.java | 50 ++ .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 36 +- .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 271 ++++++ .../jdbc/it/ITJdbcPreparedStatementTest.java | 154 +++- .../jdbc/it/ITJdbcQueryOptionsTest.java | 43 +- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 93 +- .../it/ITJdbcReadWriteAutocommitTest.java | 39 +- .../spanner/jdbc/it/ITJdbcScriptTest.java | 366 ++++++++ .../jdbc/it/ITJdbcSimpleStatementsTest.java | 86 +- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 37 +- .../spanner/jdbc/it/ITJdbcSqlScriptTest.java | 282 ------ .../spanner/jdbc/it/SpannerTestHost.java | 46 + .../spanner/jdbc/PostgreSQL/ITDdlTest.sql | 189 +++++ .../jdbc/PostgreSQL/ITReadOnlySpannerTest.sql | 145 ++++ .../ITReadOnlySpannerTest_CreateTables.sql | 24 + .../ITReadWriteAutocommitSpannerTest.sql | 236 ++++++ .../PostgreSQL/ITScriptTest_CreateTables.sql | 109 +++ .../ITScriptTest_InsertTestData.sql | 74 ++ .../ITScriptTest_TestAutoCommitDmlMode.sql | 87 ++ .../ITScriptTest_TestAutocommitReadOnly.sql | 64 ++ .../ITScriptTest_TestGetReadTimestamp.sql | 112 +++ .../ITScriptTest_TestInvalidStatements.sql | 32 + .../ITScriptTest_TestQueryOptions.sql | 51 ++ .../ITScriptTest_TestReadOnlyStaleness.sql | 262 ++++++ .../ITScriptTest_TestSetStatements.sql | 58 ++ ...ITScriptTest_TestTemporaryTransactions.sql | 67 ++ .../ITScriptTest_TestTransactionMode.sql | 155 ++++ ...criptTest_TestTransactionMode_ReadOnly.sql | 80 ++ .../jdbc/PostgreSQL/ITSqlMusicScriptTest.sql | 652 ++++++++++++++ .../spanner/jdbc/it/CreateMusicTables_PG.sql | 73 ++ 68 files changed, 5796 insertions(+), 714 deletions(-) create mode 100644 java-spanner-jdbc/clirr-ignored-differences.xml create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/DialectTestParameter.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlScriptTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SpannerTestHost.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITDdlTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest_CreateTables.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_CreateTables.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_InsertTestData.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutoCommitDmlMode.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitReadOnly.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestInvalidStatements.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestQueryOptions.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestReadOnlyStaleness.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestSetStatements.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode_ReadOnly.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlMusicScriptTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml new file mode 100644 index 000000000000..235cb90749a5 --- /dev/null +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -0,0 +1,9 @@ + + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.Dialect getDialect() + + diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index eb7a3b557490..925c0204a49e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,6 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.4 1.1.3 4.3.1 2.2 @@ -63,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.18.0 + 6.19.1 pom import @@ -103,6 +102,10 @@ com.google.api.grpc proto-google-common-protos + + com.google.api + gax + com.google.cloud google-cloud-spanner @@ -120,10 +123,6 @@ com.google.guava guava - - org.threeten - threetenbp - io.grpc grpc-netty-shaded @@ -234,7 +233,7 @@ com.google.cloud.spanner.GceTestEnvConfig - projects/gcloud-devel/instances/spanner-testing + projects/gcloud-devel/instances/spanner-testing-east1 2400 diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index a666a7490406..1a6cfe2edd18 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -16,6 +16,9 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; @@ -51,6 +54,7 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper private final ConnectionOptions options; private final com.google.cloud.spanner.connection.Connection spanner; private final Properties clientInfo; + private AbstractStatementParser parser; private SQLWarning firstWarning = null; private SQLWarning lastWarning = null; @@ -76,6 +80,22 @@ ConnectionOptions getConnectionOptions() { return options; } + @Override + public Dialect getDialect() { + return spanner.getDialect(); + } + + protected AbstractStatementParser getParser() throws SQLException { + if (parser == null) { + try { + parser = AbstractStatementParser.getInstance(spanner.getDialect()); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + return parser; + } + @Override public CallableStatement prepareCall(String sql) throws SQLException { return checkClosedAndThrowUnsupported(CALLABLE_STATEMENTS_UNSUPPORTED); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 2a905660b1c1..847f54d3887a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -42,10 +42,11 @@ abstract class AbstractJdbcPreparedStatement extends JdbcStatement implements PreparedStatement { private static final String METHOD_NOT_ON_PREPARED_STATEMENT = "This method may not be called on a PreparedStatement"; - private final JdbcParameterStore parameters = new JdbcParameterStore(); + private final JdbcParameterStore parameters; - AbstractJdbcPreparedStatement(JdbcConnection connection) { + AbstractJdbcPreparedStatement(JdbcConnection connection) throws SQLException { super(connection); + parameters = new JdbcParameterStore(connection.getDialect()); } JdbcParameterStore getParameters() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 9c516609aa14..6b5848a4aabc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -20,6 +20,7 @@ import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.Connection; import com.google.cloud.spanner.connection.StatementResult; import com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType; @@ -35,14 +36,16 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Statement { private static final String CURSORS_NOT_SUPPORTED = "Cursors are not supported"; private static final String ONLY_FETCH_FORWARD_SUPPORTED = "Only fetch_forward is supported"; + final AbstractStatementParser parser; private boolean closed; private boolean closeOnCompletion; private boolean poolable; private final JdbcConnection connection; private int queryTimeout; - AbstractJdbcStatement(JdbcConnection connection) { + AbstractJdbcStatement(JdbcConnection connection) throws SQLException { this.connection = connection; + this.parser = connection.getParser(); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 25ff70a6f3f3..ce1f84760c28 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -47,6 +47,7 @@ static int extractColumnType(Type type) { if (type.equals(Type.float64())) return Types.DOUBLE; if (type.equals(Type.int64())) return Types.BIGINT; if (type.equals(Type.numeric())) return Types.NUMERIC; + if (type.equals(Type.pgNumeric())) return Types.NUMERIC; if (type.equals(Type.string())) return Types.NVARCHAR; if (type.equals(Type.json())) return Types.NVARCHAR; if (type.equals(Type.timestamp())) return Types.TIMESTAMP; @@ -106,6 +107,7 @@ static String getClassName(Type type) { if (type == Type.float64()) return Double.class.getName(); if (type == Type.int64()) return Long.class.getName(); if (type == Type.numeric()) return BigDecimal.class.getName(); + if (type == Type.pgNumeric()) return BigDecimal.class.getName(); if (type == Type.string()) return String.class.getName(); if (type == Type.json()) return String.class.getName(); if (type == Type.timestamp()) return Timestamp.class.getName(); @@ -116,6 +118,7 @@ static String getClassName(Type type) { if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); if (type.getArrayElementType() == Type.numeric()) return BigDecimal[].class.getName(); + if (type.getArrayElementType() == Type.pgNumeric()) return BigDecimal[].class.getName(); if (type.getArrayElementType() == Type.string()) return String[].class.getName(); if (type.getArrayElementType() == Type.json()) return String[].class.getName(); if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); @@ -145,6 +148,16 @@ static byte checkedCastToByte(BigDecimal val) throws SQLException { } } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static byte checkedCastToByte(BigInteger val) throws SQLException { + try { + return val.byteValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "byte", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static short checkedCastToShort(long val) throws SQLException { if (val > Short.MAX_VALUE || val < Short.MIN_VALUE) { @@ -164,6 +177,16 @@ static short checkedCastToShort(BigDecimal val) throws SQLException { } } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static short checkedCastToShort(BigInteger val) throws SQLException { + try { + return val.shortValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "short", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static int checkedCastToInt(long val) throws SQLException { if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) { @@ -183,6 +206,16 @@ static int checkedCastToInt(BigDecimal val) throws SQLException { } } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static int checkedCastToInt(BigInteger val) throws SQLException { + try { + return val.intValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "int", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** Cast value and throw {@link SQLException} if out-of-range. */ static float checkedCastToFloat(double val) throws SQLException { if (val > Float.MAX_VALUE || val < -Float.MAX_VALUE) { @@ -226,6 +259,16 @@ static long checkedCastToLong(BigDecimal val) throws SQLException { } } + /** Cast value and throw {@link SQLException} if out-of-range. */ + static long checkedCastToLong(BigInteger val) throws SQLException { + try { + return val.longValueExact(); + } catch (ArithmeticException e) { + throw JdbcSqlExceptionFactory.of( + String.format(OUT_OF_RANGE_MSG, "long", val), com.google.rpc.Code.OUT_OF_RANGE); + } + } + /** * Parses the given string value as a double. Throws {@link SQLException} if the string is not a * valid double value. @@ -240,6 +283,20 @@ static double parseDouble(String val) throws SQLException { } } + /** + * Parses the given string value as a float. Throws {@link SQLException} if the string is not a + * valid float value. + */ + static float parseFloat(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return Float.parseFloat(val); + } catch (NumberFormatException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + /** * Parses the given string value as a {@link Date} value. Throws {@link SQLException} if the * string is not a valid {@link Date} value. @@ -332,6 +389,20 @@ static Timestamp parseTimestamp(String val, Calendar cal) throws SQLException { } } + /** + * Parses the given string value as a {@link BigDecimal} value. Throws {@link SQLException} if the + * string is not a valid {@link BigDecimal} value. + */ + static BigDecimal parseBigDecimal(String val) throws SQLException { + Preconditions.checkNotNull(val); + try { + return new BigDecimal(val); + } catch (NumberFormatException e) { + throw JdbcSqlExceptionFactory.of( + String.format("%s is not a valid number", val), com.google.rpc.Code.INVALID_ARGUMENT, e); + } + } + /** Should return true if this object has been closed */ public abstract boolean isClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 7801dcfdc680..679fa8716c68 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -20,6 +20,7 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.CommitResponse; 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.TimestampBound; @@ -321,6 +322,11 @@ default String getStatementTag() throws SQLException { */ String getConnectionUrl(); + /** @return The {@link Dialect} that is used by this connection. */ + default Dialect getDialect() { + return Dialect.GOOGLE_STANDARD_SQL; + } + /** * @see * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 9e4623cabe7c..867695fa88e1 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -23,7 +23,6 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.connection.AutocommitDmlMode; import com.google.cloud.spanner.connection.ConnectionOptions; -import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.connection.TransactionMode; import com.google.common.collect.Iterators; import java.sql.Array; @@ -72,8 +71,8 @@ public JdbcPreparedStatement prepareStatement(String sql) throws SQLException { @Override public String nativeSQL(String sql) throws SQLException { checkClosed(); - return JdbcParameterStore.convertPositionalParametersToNamedParameters( - StatementParser.removeCommentsAndTrim(sql)) + return getParser() + .convertPositionalParametersToNamedParameters('?', getParser().removeCommentsAndTrim(sql)) .sqlWithNamedParameters; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 1a62775b7176..7eecb2a678d6 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -203,6 +203,32 @@ public Type getSpannerType() { return Type.numeric(); } }, + PG_NUMERIC { + @Override + public int getSqlType() { + return Types.NUMERIC; + } + + @Override + public Class getJavaClass() { + return BigDecimal.class; + } + + @Override + public Code getCode() { + return Code.PG_NUMERIC; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getValue(columnIndex).getNumericArray(); + } + + @Override + public Type getSpannerType() { + return Type.pgNumeric(); + } + }, STRING { @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java index f5188653b3ea..a520e221ec09 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -16,7 +16,7 @@ package com.google.cloud.spanner.jdbc; -import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; import java.math.BigDecimal; import java.sql.Date; import java.sql.ParameterMetaData; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index a475646a64db..9ba490faa459 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -17,12 +17,12 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Statement.Builder; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; -import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.common.io.CharStreams; import com.google.rpc.Code; import java.io.IOException; @@ -45,10 +45,13 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; +import java.time.LocalDate; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; /** This class handles the parameters of a {@link PreparedStatement}. */ class JdbcParameterStore { @@ -78,7 +81,11 @@ private static final class JdbcParameter { */ private int highestIndex = 0; - JdbcParameterStore() {} + private final Dialect dialect; + + JdbcParameterStore(Dialect dialect) { + this.dialect = dialect; + } void clearParameters() { parametersList = new ArrayList<>(INITIAL_PARAMETERS_ARRAY_SIZE); @@ -300,11 +307,18 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { || value instanceof Reader || value instanceof URL; case Types.DATE: + return value instanceof Date + || value instanceof Time + || value instanceof Timestamp + || value instanceof LocalDate; case Types.TIME: case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: - return value instanceof Date || value instanceof Time || value instanceof Timestamp; + return value instanceof Date + || value instanceof Time + || value instanceof Timestamp + || value instanceof OffsetDateTime; case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: @@ -365,102 +379,6 @@ private int getParameterArrayIndex(String columnName) { return -1; } - /** Parameter information with positional parameters translated to named parameters. */ - static class ParametersInfo { - final int numberOfParameters; - final String sqlWithNamedParameters; - - private ParametersInfo(int numberOfParameters, String sqlWithNamedParameters) { - this.numberOfParameters = numberOfParameters; - this.sqlWithNamedParameters = sqlWithNamedParameters; - } - } - - /** - * Converts all positional parameters (?) in the given sql string into named parameters. The - * parameters are named @p1, @p2, etc. This method is used when converting a JDBC statement that - * uses positional parameters to a Cloud Spanner {@link Statement} instance that requires named - * parameters. The input SQL string may not contain any comments. - * - * @param sql The sql string without comments that should be converted - * @return A {@link ParametersInfo} object containing a string with named parameters instead of - * positional parameters and the number of parameters. - * @throws JdbcSqlExceptionImpl If the input sql string contains an unclosed string/byte literal. - */ - static ParametersInfo convertPositionalParametersToNamedParameters(String sql) - throws SQLException { - final char POS_PARAM = '?'; - final char SINGLE_QUOTE = '\''; - final char DOUBLE_QUOTE = '"'; - final char BACKTICK_QUOTE = '`'; - boolean isInQuoted = false; - char startQuote = 0; - boolean lastCharWasEscapeChar = false; - boolean isTripleQuoted = false; - int paramIndex = 1; - StringBuilder named = new StringBuilder(sql.length() + countOccurrencesOf(POS_PARAM, sql)); - for (int index = 0; index < sql.length(); index++) { - char c = sql.charAt(index); - if (isInQuoted) { - if ((c == '\n' || c == '\r') && !isTripleQuoted) { - throw JdbcSqlExceptionFactory.of( - "SQL statement contains an unclosed literal: " + sql, Code.INVALID_ARGUMENT); - } else if (c == startQuote) { - if (lastCharWasEscapeChar) { - lastCharWasEscapeChar = false; - } else if (isTripleQuoted) { - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isInQuoted = false; - startQuote = 0; - isTripleQuoted = false; - } - } else { - isInQuoted = false; - startQuote = 0; - } - } else { - lastCharWasEscapeChar = (c == '\\'); - } - named.append(c); - } else { - if (c == POS_PARAM) { - named.append("@p").append(paramIndex); - paramIndex++; - } else { - if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { - isInQuoted = true; - startQuote = c; - // check whether it is a triple-quote - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isTripleQuoted = true; - } - } - named.append(c); - } - } - } - if (isInQuoted) { - throw JdbcSqlExceptionFactory.of( - "SQL statement contains an unclosed literal: " + sql, Code.INVALID_ARGUMENT); - } - return new ParametersInfo(paramIndex - 1, named.toString()); - } - - /** Convenience method that is used to estimate the number of parameters in a SQL statement. */ - private static int countOccurrencesOf(char c, String string) { - int res = 0; - for (int i = 0; i < string.length(); i++) { - if (string.charAt(i) == c) { - res++; - } - } - return res; - } - /** Bind a JDBC parameter to a parameter on a Spanner {@link Statement}. */ Builder bindParameterValue(ValueBinder binder, int index) throws SQLException { return setValue(binder, getParameter(index), getType(index)); @@ -531,18 +449,25 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, throw JdbcSqlExceptionFactory.of(value + " is not a valid double", Code.INVALID_ARGUMENT); case Types.NUMERIC: case Types.DECIMAL: - if (value instanceof Number) { - if (value instanceof BigDecimal) { - return binder.to((BigDecimal) value); + if (dialect == Dialect.POSTGRESQL) { + if (value instanceof Number) { + return binder.to(Value.pgNumeric(value.toString())); } - try { - return binder.to(new BigDecimal(value.toString())); - } catch (NumberFormatException e) { - // ignore and fall through to the exception. + throw JdbcSqlExceptionFactory.of(value + " is not a valid Number", Code.INVALID_ARGUMENT); + } else { + if (value instanceof Number) { + if (value instanceof BigDecimal) { + return binder.to((BigDecimal) value); + } + try { + return binder.to(new BigDecimal(value.toString())); + } catch (NumberFormatException e) { + // ignore and fall through to the exception. + } } + throw JdbcSqlExceptionFactory.of( + value + " is not a valid BigDecimal", Code.INVALID_ARGUMENT); } - throw JdbcSqlExceptionFactory.of( - value + " is not a valid BigDecimal", Code.INVALID_ARGUMENT); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -584,6 +509,11 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, return binder.to(JdbcTypeConverter.toGoogleDate((Time) value)); } else if (value instanceof Timestamp) { return binder.to(JdbcTypeConverter.toGoogleDate((Timestamp) value)); + } else if (value instanceof LocalDate) { + LocalDate localDate = (LocalDate) value; + return binder.to( + com.google.cloud.Date.fromYearMonthDay( + localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth())); } throw JdbcSqlExceptionFactory.of(value + " is not a valid date", Code.INVALID_ARGUMENT); case Types.TIME: @@ -596,6 +526,11 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, return binder.to(JdbcTypeConverter.toGoogleTimestamp((Time) value)); } else if (value instanceof Timestamp) { return binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); + } else if (value instanceof OffsetDateTime) { + OffsetDateTime offsetDateTime = (OffsetDateTime) value; + return binder.to( + com.google.cloud.Timestamp.ofTimeSecondsAndNanos( + offsetDateTime.toEpochSecond(), offsetDateTime.getNano())); } throw JdbcSqlExceptionFactory.of( value + " is not a valid timestamp", Code.INVALID_ARGUMENT); @@ -698,12 +633,26 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } else if (Double.class.isAssignableFrom(value.getClass())) { return binder.to(((Double) value).doubleValue()); } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { - return binder.to((BigDecimal) value); + if (dialect == Dialect.POSTGRESQL) { + return binder.to(Value.pgNumeric(value.toString())); + } else { + return binder.to((BigDecimal) value); + } } else if (Date.class.isAssignableFrom(value.getClass())) { Date dateValue = (Date) value; return binder.to(JdbcTypeConverter.toGoogleDate(dateValue)); + } else if (LocalDate.class.isAssignableFrom(value.getClass())) { + LocalDate localDate = (LocalDate) value; + return binder.to( + com.google.cloud.Date.fromYearMonthDay( + localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth())); } else if (Timestamp.class.isAssignableFrom(value.getClass())) { return binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); + } else if (OffsetDateTime.class.isAssignableFrom(value.getClass())) { + OffsetDateTime offsetDateTime = (OffsetDateTime) value; + return binder.to( + com.google.cloud.Timestamp.ofTimeSecondsAndNanos( + offsetDateTime.toEpochSecond(), offsetDateTime.getNano())); } else if (Time.class.isAssignableFrom(value.getClass())) { Time timeValue = (Time) value; return binder.to(JdbcTypeConverter.toGoogleTimestamp(new Timestamp(timeValue.getTime()))); @@ -785,7 +734,11 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu return binder.toFloat64Array((double[]) null); case Types.NUMERIC: case Types.DECIMAL: - return binder.toNumericArray(null); + if (dialect == Dialect.POSTGRESQL) { + return binder.toPgNumericArray(null); + } else { + return binder.toNumericArray(null); + } case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -850,7 +803,14 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (Double[].class.isAssignableFrom(value.getClass())) { return binder.toFloat64Array(toDoubleList((Double[]) value)); } else if (BigDecimal[].class.isAssignableFrom(value.getClass())) { - return binder.toNumericArray(Arrays.asList((BigDecimal[]) value)); + if (dialect == Dialect.POSTGRESQL) { + return binder.toPgNumericArray( + Arrays.stream((BigDecimal[]) value) + .map(bigDecimal -> bigDecimal == null ? null : bigDecimal.toString()) + .collect(Collectors.toList())); + } else { + return binder.toNumericArray(Arrays.asList((BigDecimal[]) value)); + } } else if (Date[].class.isAssignableFrom(value.getClass())) { return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value)); } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { @@ -908,7 +868,11 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { return binder.to((com.google.cloud.Date) null); case Types.NUMERIC: case Types.DECIMAL: - return binder.to((BigDecimal) null); + if (dialect == Dialect.POSTGRESQL) { + return binder.to(Value.pgNumeric(null)); + } else { + return binder.to((BigDecimal) null); + } case Types.DOUBLE: return binder.to((Double) null); case Types.FLOAT: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index a25b39c0499e..a1b327b23de5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -19,10 +19,10 @@ import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Type; -import com.google.cloud.spanner.connection.StatementParser; -import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import java.sql.PreparedStatement; @@ -32,6 +32,7 @@ /** Implementation of {@link PreparedStatement} for Cloud Spanner. */ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement { + private static final char POS_PARAM_CHAR = '?'; private final String sql; private final String sqlWithoutComments; private final ParametersInfo parameters; @@ -39,9 +40,13 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement { JdbcPreparedStatement(JdbcConnection connection, String sql) throws SQLException { super(connection); this.sql = sql; - this.sqlWithoutComments = StatementParser.removeCommentsAndTrim(this.sql); - this.parameters = - JdbcParameterStore.convertPositionalParametersToNamedParameters(sqlWithoutComments); + try { + this.sqlWithoutComments = parser.removeCommentsAndTrim(this.sql); + this.parameters = + parser.convertPositionalParametersToNamedParameters(POS_PARAM_CHAR, sqlWithoutComments); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } } ParametersInfo getParametersInfo() { @@ -102,7 +107,7 @@ public JdbcParameterMetaData getParameterMetaData() throws SQLException { @Override public ResultSetMetaData getMetaData() throws SQLException { checkClosed(); - if (StatementParser.INSTANCE.isUpdateStatement(sql)) { + if (getConnection().getParser().isUpdateStatement(sql)) { // Return metadata for an empty result set as DML statements do not return any results (as a // result set). com.google.cloud.spanner.ResultSet resultSet = diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index c06c147f8146..089ef7b21610 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -16,8 +16,11 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.Type.Code.PG_NUMERIC; + 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 java.io.ByteArrayInputStream; import java.io.InputStream; @@ -121,6 +124,12 @@ SQLException createInvalidToGetAs(String sqlType, Code type) { com.google.rpc.Code.INVALID_ARGUMENT); } + SQLException createCastException(String sqlType, Object value) { + return JdbcSqlExceptionFactory.of( + String.format("Cannot cast to %s: %s", sqlType, value), + com.google.rpc.Code.INVALID_ARGUMENT); + } + @Override public String getString(int columnIndex) throws SQLException { checkClosedAndValidRow(); @@ -140,6 +149,8 @@ public String getString(int columnIndex) throws SQLException { return isNull ? null : Long.toString(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? null : spanner.getBigDecimal(spannerIndex).toString(); + case PG_NUMERIC: + return isNull ? null : spanner.getString(spannerIndex); case STRING: return isNull ? null : spanner.getString(spannerIndex); case JSON: @@ -168,6 +179,8 @@ public boolean getBoolean(int columnIndex) throws SQLException { return !isNull && spanner.getLong(spannerIndex) != 0L; case NUMERIC: return !isNull && !spanner.getBigDecimal(spannerIndex).equals(BigDecimal.ZERO); + case PG_NUMERIC: + return !isNull && !spanner.getString(spannerIndex).equals("0"); case STRING: return !isNull && Boolean.parseBoolean(spanner.getString(spannerIndex)); case BYTES: @@ -198,6 +211,10 @@ public byte getByte(int columnIndex) throws SQLException { return isNull ? (byte) 0 : checkedCastToByte(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? (byte) 0 : checkedCastToByte(spanner.getBigDecimal(spannerIndex)); + case PG_NUMERIC: + return isNull + ? (byte) 0 + : checkedCastToByte(parseBigDecimal(spanner.getString(spannerIndex)).toBigInteger()); case STRING: return isNull ? (byte) 0 : checkedCastToByte(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -228,6 +245,10 @@ public short getShort(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : checkedCastToShort(spanner.getBigDecimal(spannerIndex)); + case PG_NUMERIC: + return isNull + ? 0 + : checkedCastToShort(parseBigDecimal(spanner.getString(spannerIndex)).toBigInteger()); case STRING: return isNull ? 0 : checkedCastToShort(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -258,6 +279,10 @@ public int getInt(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToInt(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : checkedCastToInt(spanner.getBigDecimal(spannerIndex)); + case PG_NUMERIC: + return isNull + ? 0 + : checkedCastToInt(parseBigDecimal(spanner.getString(spannerIndex)).toBigInteger()); case STRING: return isNull ? 0 : checkedCastToInt(parseLong(spanner.getString(spannerIndex))); case BYTES: @@ -285,7 +310,11 @@ public long getLong(int columnIndex) throws SQLException { case INT64: return isNull ? 0L : spanner.getLong(spannerIndex); case NUMERIC: - return isNull ? 0L : checkedCastToLong(spanner.getBigDecimal(spannerIndex)); + return isNull ? 0 : checkedCastToLong(parseBigDecimal(spanner.getString(spannerIndex))); + case PG_NUMERIC: + return isNull + ? 0L + : checkedCastToLong(parseBigDecimal(spanner.getString(spannerIndex)).toBigInteger()); case STRING: return isNull ? 0L : parseLong(spanner.getString(spannerIndex)); case BYTES: @@ -314,6 +343,8 @@ public float getFloat(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToFloat(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : spanner.getBigDecimal(spannerIndex).floatValue(); + case PG_NUMERIC: + return isNull ? 0 : parseFloat(spanner.getString(spannerIndex)); case STRING: return isNull ? 0 : checkedCastToFloat(parseDouble(spanner.getString(spannerIndex))); case BYTES: @@ -342,6 +373,8 @@ public double getDouble(int columnIndex) throws SQLException { return isNull ? 0 : spanner.getLong(spannerIndex); case NUMERIC: return isNull ? 0 : spanner.getBigDecimal(spannerIndex).doubleValue(); + case PG_NUMERIC: + return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); case STRING: return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); case BYTES: @@ -358,7 +391,9 @@ public double getDouble(int columnIndex) throws SQLException { @Override public byte[] getBytes(int columnIndex) throws SQLException { checkClosedAndValidRow(); - return isNull(columnIndex) ? null : spanner.getBytes(columnIndex - 1).toByteArray(); + final boolean isNull = isNull(columnIndex); + final int spannerIndex = columnIndex - 1; + return isNull ? null : spanner.getBytes(spannerIndex).toByteArray(); } @Override @@ -380,6 +415,7 @@ public Date getDate(int columnIndex) throws SQLException { case FLOAT64: case INT64: case NUMERIC: + case PG_NUMERIC: case BYTES: case JSON: case STRUCT: @@ -405,6 +441,7 @@ public Time getTime(int columnIndex) throws SQLException { case FLOAT64: case INT64: case NUMERIC: + case PG_NUMERIC: case BYTES: case JSON: case STRUCT: @@ -431,6 +468,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case FLOAT64: case INT64: case NUMERIC: + case PG_NUMERIC: case BYTES: case JSON: case STRUCT: @@ -587,6 +625,14 @@ private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.float64()) return getDouble(columnIndex); if (type == Type.int64()) return getLong(columnIndex); if (type == Type.numeric()) return getBigDecimal(columnIndex); + if (type == Type.pgNumeric()) { + final String value = getString(columnIndex); + try { + return parseBigDecimal(value); + } catch (Exception e) { + return parseDouble(value); + } + } if (type == Type.string()) return getString(columnIndex); if (type == Type.json()) return getString(columnIndex); if (type == Type.timestamp()) return getTimestamp(columnIndex); @@ -665,6 +711,9 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) case NUMERIC: res = isNull ? null : spanner.getBigDecimal(spannerIndex); break; + case PG_NUMERIC: + res = isNull ? null : parseBigDecimal(spanner.getString(spannerIndex)); + break; case STRING: try { res = isNull ? null : new BigDecimal(spanner.getString(spannerIndex)); @@ -735,10 +784,16 @@ public Array getArray(int columnIndex) throws SQLException { throw JdbcSqlExceptionFactory.of( "Column with index " + columnIndex + " does not contain an array", com.google.rpc.Code.INVALID_ARGUMENT); - JdbcDataType dataType = JdbcDataType.getType(type.getArrayElementType().getCode()); - List elements = dataType.getArrayElements(spanner, columnIndex - 1); - - return JdbcArray.createArray(dataType, elements); + final Code elementCode = type.getArrayElementType().getCode(); + final JdbcDataType dataType = JdbcDataType.getType(elementCode); + try { + List elements = dataType.getArrayElements(spanner, columnIndex - 1); + return JdbcArray.createArray(dataType, elements); + } catch (NumberFormatException e) { + final String sqlType = "ARRAY<" + type.getArrayElementType() + ">"; + final Value value = spanner.getValue(columnIndex - 1); + throw createCastException(sqlType, value); + } } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index 69162e8077e0..ae312e909715 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -137,6 +137,7 @@ public int getPrecision(int column) { case Types.DOUBLE: return 14; case Types.BIGINT: + case Types.INTEGER: return 10; case Types.NUMERIC: return 14; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 3674ae02b07c..5c4bbed9e656 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -23,7 +23,6 @@ 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.StatementParser; import com.google.cloud.spanner.connection.StatementResult; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; @@ -49,7 +48,7 @@ enum BatchType { private BatchType currentBatchType = BatchType.NONE; final List batchedStatements = new ArrayList<>(); - JdbcStatement(JdbcConnection connection) { + JdbcStatement(JdbcConnection connection) throws SQLException { super(connection); } @@ -199,10 +198,10 @@ public int getFetchSize() throws SQLException { * @throws SQLException if the sql statement is not allowed for batching. */ private BatchType determineStatementBatchType(String sql) throws SQLException { - String sqlWithoutComments = StatementParser.removeCommentsAndTrim(sql); - if (StatementParser.INSTANCE.isDdlStatement(sqlWithoutComments)) { + String sqlWithoutComments = parser.removeCommentsAndTrim(sql); + if (parser.isDdlStatement(sqlWithoutComments)) { return BatchType.DDL; - } else if (StatementParser.INSTANCE.isUpdateStatement(sqlWithoutComments)) { + } else if (parser.isUpdateStatement(sqlWithoutComments)) { return BatchType.DML; } throw JdbcSqlExceptionFactory.of( diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 56043b0416be..f6cba1dcd20b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -29,15 +29,17 @@ import java.sql.Array; import java.sql.SQLException; import java.sql.Time; +import java.time.Instant; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.concurrent.TimeUnit; -import org.threeten.bp.Instant; -import org.threeten.bp.ZoneId; -import org.threeten.bp.ZonedDateTime; -import org.threeten.bp.format.DateTimeFormatter; /** Convenience class for converting values between Java, JDBC and Cloud Spanner. */ class JdbcTypeConverter { @@ -144,9 +146,22 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (targetType.equals(java.sql.Date.class)) { if (type.getCode() == Code.DATE) return value; } + if (targetType.equals(LocalDate.class)) { + if (type.getCode() == Code.DATE) { + return ((java.sql.Date) value).toLocalDate(); + } + } if (targetType.equals(java.sql.Timestamp.class)) { if (type.getCode() == Code.TIMESTAMP) return value; } + if (targetType.equals(OffsetDateTime.class)) { + if (type.getCode() == Code.TIMESTAMP) { + Timestamp timestamp = Timestamp.of((java.sql.Timestamp) value); + return OffsetDateTime.ofInstant( + Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()), + ZoneId.systemDefault()); + } + } if (targetType.equals(java.sql.Array.class)) { if (type.getCode() == Code.ARRAY) return value; } @@ -182,6 +197,9 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx case NUMERIC: return Value.numericArray( Arrays.asList((BigDecimal[]) ((java.sql.Array) value).getArray())); + case PG_NUMERIC: + return Value.pgNumericArray( + Arrays.asList((String[]) ((java.sql.Array) value).getArray())); case STRING: return Value.stringArray(Arrays.asList((String[]) ((java.sql.Array) value).getArray())); case TIMESTAMP: @@ -206,6 +224,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.int64((Long) value); case NUMERIC: return Value.numeric((BigDecimal) value); + case PG_NUMERIC: + return Value.pgNumeric(value == null ? null : value.toString()); case STRING: return Value.string((String) value); case TIMESTAMP: diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 14106ee1e92e..3ee102a8cff2 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * @@ -84,4 +85,4 @@ WHERE UPPER(C.TABLE_CATALOG) LIKE ? AND UPPER(C.TABLE_SCHEMA) LIKE ? AND UPPER(C.TABLE_NAME) LIKE ? AND UPPER(C.COLUMN_NAME) LIKE ? -ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION \ No newline at end of file +ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql index 7d362ca58e87..d5c1620c2edb 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql index 631886d710ed..ba6630c40d95 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql index 50994a55b2a9..4bc9296fb161 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql index e0b2a2f60bbe..5fddb8b067e2 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetIndexInfo.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql index cec8e7e0530f..455c474c252c 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetPrimaryKeys.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql index 1e302623fb13..3903236b1086 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetSchemas.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql index 1d4855810851..8b3083bdaa71 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetTables.sql @@ -1,3 +1,4 @@ +/*GSQL*/ /* * Copyright 2019 Google LLC * diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index 3569e67c586d..372bbb090346 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -17,10 +17,15 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.cloud.Timestamp; import com.google.rpc.Code; +import java.math.BigDecimal; +import java.math.BigInteger; import java.sql.Date; import java.sql.SQLException; import java.sql.Time; @@ -67,10 +72,22 @@ public void testUnwrap() { assertThat(unwrapSucceeds(subject, getClass())).isFalse(); } - private static final class CheckedCastToByteChecker { - public boolean cast(Long val) { + @FunctionalInterface + private interface SqlFunction { + R apply(T value) throws SQLException; + } + + private static final class CheckedCastChecker { + + private final SqlFunction checker; + + public CheckedCastChecker(SqlFunction checker) { + this.checker = checker; + } + + public boolean cast(T value) { try { - AbstractJdbcWrapper.checkedCastToByte(val); + checker.apply(value); return true; } catch (SQLException e) { return false; @@ -80,7 +97,8 @@ public boolean cast(Long val) { @Test public void testCheckedCastToByte() { - CheckedCastToByteChecker checker = new CheckedCastToByteChecker(); + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToByte); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); assertThat(checker.cast((long) Byte.MAX_VALUE)).isTrue(); @@ -92,20 +110,38 @@ public void testCheckedCastToByte() { assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToShortChecker { - public boolean cast(Long val) { - try { - AbstractJdbcWrapper.checkedCastToShort(val); - return true; - } catch (SQLException e) { - return false; - } - } + @Test + public void testCheckedCastFromBigDecimalToByte() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToByte); + assertTrue(checker.cast(BigDecimal.ZERO)); + assertTrue(checker.cast(BigDecimal.ONE)); + assertTrue(checker.cast(BigDecimal.valueOf(-1))); + assertTrue(checker.cast(BigDecimal.valueOf(Byte.MIN_VALUE))); + assertTrue(checker.cast(BigDecimal.valueOf(Byte.MAX_VALUE))); + + assertFalse(checker.cast(BigDecimal.valueOf(Byte.MAX_VALUE).add(BigDecimal.ONE))); + assertFalse(checker.cast(BigDecimal.valueOf(Byte.MIN_VALUE).subtract(BigDecimal.ONE))); + } + + @Test + public void testCheckedCastFromBigIntegerToByte() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToByte); + assertTrue(checker.cast(BigInteger.ZERO)); + assertTrue(checker.cast(BigInteger.ONE)); + assertTrue(checker.cast(BigInteger.valueOf(-1))); + assertTrue(checker.cast(BigInteger.valueOf(Byte.MIN_VALUE))); + assertTrue(checker.cast(BigInteger.valueOf(Byte.MAX_VALUE))); + + assertFalse(checker.cast(BigInteger.valueOf(Byte.MAX_VALUE).add(BigInteger.ONE))); + assertFalse(checker.cast(BigInteger.valueOf(Byte.MIN_VALUE).subtract(BigInteger.ONE))); } @Test public void testCheckedCastToShort() { - CheckedCastToShortChecker checker = new CheckedCastToShortChecker(); + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToShort); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); assertThat(checker.cast((long) Short.MAX_VALUE)).isTrue(); @@ -117,20 +153,38 @@ public void testCheckedCastToShort() { assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToIntChecker { - public boolean cast(Long val) { - try { - AbstractJdbcWrapper.checkedCastToInt(val); - return true; - } catch (SQLException e) { - return false; - } - } + @Test + public void testCheckedCastFromBigDecimalToShort() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToShort); + assertTrue(checker.cast(BigDecimal.ZERO)); + assertTrue(checker.cast(BigDecimal.ONE)); + assertTrue(checker.cast(BigDecimal.valueOf(-1))); + assertTrue(checker.cast(BigDecimal.valueOf(Short.MIN_VALUE))); + assertTrue(checker.cast(BigDecimal.valueOf(Short.MAX_VALUE))); + + assertFalse(checker.cast(BigDecimal.valueOf(Short.MAX_VALUE).add(BigDecimal.ONE))); + assertFalse(checker.cast(BigDecimal.valueOf(Short.MIN_VALUE).subtract(BigDecimal.ONE))); + } + + @Test + public void testCheckedCastFromBigIntegerToShort() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToShort); + assertTrue(checker.cast(BigInteger.ZERO)); + assertTrue(checker.cast(BigInteger.ONE)); + assertTrue(checker.cast(BigInteger.valueOf(-1))); + assertTrue(checker.cast(BigInteger.valueOf(Short.MIN_VALUE))); + assertTrue(checker.cast(BigInteger.valueOf(Short.MAX_VALUE))); + + assertFalse(checker.cast(BigInteger.valueOf(Short.MAX_VALUE).add(BigInteger.ONE))); + assertFalse(checker.cast(BigInteger.valueOf(Short.MIN_VALUE).subtract(BigInteger.ONE))); } @Test public void testCheckedCastToInt() { - CheckedCastToIntChecker checker = new CheckedCastToIntChecker(); + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToInt); assertThat(checker.cast(0L)).isTrue(); assertThat(checker.cast(1L)).isTrue(); assertThat(checker.cast((long) Integer.MAX_VALUE)).isTrue(); @@ -142,20 +196,66 @@ public void testCheckedCastToInt() { assertThat(checker.cast(Long.MIN_VALUE)).isFalse(); } - private static final class CheckedCastToFloatChecker { - public boolean cast(Double val) { - try { - AbstractJdbcWrapper.checkedCastToFloat(val); - return true; - } catch (SQLException e) { - return false; - } - } + @Test + public void testCheckedCastFromBigDecimalToInt() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToInt); + assertTrue(checker.cast(BigDecimal.ZERO)); + assertTrue(checker.cast(BigDecimal.ONE)); + assertTrue(checker.cast(BigDecimal.valueOf(-1))); + assertTrue(checker.cast(BigDecimal.valueOf(Integer.MIN_VALUE))); + assertTrue(checker.cast(BigDecimal.valueOf(Integer.MAX_VALUE))); + + assertFalse(checker.cast(BigDecimal.valueOf(Integer.MAX_VALUE).add(BigDecimal.ONE))); + assertFalse(checker.cast(BigDecimal.valueOf(Integer.MIN_VALUE).subtract(BigDecimal.ONE))); + } + + @Test + public void testCheckedCastFromBigIntegerToInt() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToInt); + assertTrue(checker.cast(BigInteger.ZERO)); + assertTrue(checker.cast(BigInteger.ONE)); + assertTrue(checker.cast(BigInteger.valueOf(-1))); + assertTrue(checker.cast(BigInteger.valueOf(Integer.MIN_VALUE))); + assertTrue(checker.cast(BigInteger.valueOf(Integer.MAX_VALUE))); + + assertFalse(checker.cast(BigInteger.valueOf(Integer.MAX_VALUE).add(BigInteger.ONE))); + assertFalse(checker.cast(BigInteger.valueOf(Integer.MIN_VALUE).subtract(BigInteger.ONE))); + } + + @Test + public void testCheckedCastFromBigDecimalToLong() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToLong); + assertTrue(checker.cast(BigDecimal.ZERO)); + assertTrue(checker.cast(BigDecimal.ONE)); + assertTrue(checker.cast(BigDecimal.valueOf(-1))); + assertTrue(checker.cast(BigDecimal.valueOf(Long.MIN_VALUE))); + assertTrue(checker.cast(BigDecimal.valueOf(Long.MAX_VALUE))); + + assertFalse(checker.cast(BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE))); + assertFalse(checker.cast(BigDecimal.valueOf(Long.MIN_VALUE).subtract(BigDecimal.ONE))); + } + + @Test + public void testCheckedCastFromBigIntegerToLong() { + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToLong); + assertTrue(checker.cast(BigInteger.ZERO)); + assertTrue(checker.cast(BigInteger.ONE)); + assertTrue(checker.cast(BigInteger.valueOf(-1))); + assertTrue(checker.cast(BigInteger.valueOf(Long.MIN_VALUE))); + assertTrue(checker.cast(BigInteger.valueOf(Long.MAX_VALUE))); + + assertFalse(checker.cast(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE))); + assertFalse(checker.cast(BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE))); } @Test public void testCheckedCastToFloat() { - CheckedCastToFloatChecker checker = new CheckedCastToFloatChecker(); + final CheckedCastChecker checker = + new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToFloat); assertThat(checker.cast(0D)).isTrue(); assertThat(checker.cast(1D)).isTrue(); assertThat(checker.cast((double) Float.MAX_VALUE)).isTrue(); @@ -167,6 +267,30 @@ public void testCheckedCastToFloat() { assertThat(checker.cast(-Double.MAX_VALUE)).isFalse(); } + @Test + public void testParseBigDecimal() throws SQLException { + assertEquals(BigDecimal.valueOf(123, 2), AbstractJdbcWrapper.parseBigDecimal("1.23")); + try { + AbstractJdbcWrapper.parseBigDecimal("NaN"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT.getNumber(), e.getErrorCode()); + } + } + + @Test + public void testParseFloat() throws SQLException { + assertEquals(3.14F, AbstractJdbcWrapper.parseFloat("3.14"), 0.001F); + try { + AbstractJdbcWrapper.parseFloat("invalid number"); + fail("missing expected SQLException"); + } catch (SQLException e) { + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT.getNumber(), e.getErrorCode()); + } + } + private boolean unwrapSucceeds(AbstractJdbcWrapper subject, Class iface) { try { subject.unwrap(iface); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java index efc2d8df16ce..2ab75e59bed1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.GceTestEnvConfig; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; @@ -33,6 +34,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Arrays; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -48,7 +50,7 @@ public ITJdbcConnectionProvider() {} @Override public JdbcGenericConnection getConnection() { try { - return JdbcGenericConnection.of(createConnection()); + return JdbcGenericConnection.of(createConnection(getDialect())); } catch (SQLException e) { throw new RuntimeException(e); } @@ -66,7 +68,8 @@ protected void after() { }; private static final String DEFAULT_KEY_FILE = null; - private static Database database; + private static Database googleStandardSqlDatabase; + private static Database postgresDatabase; protected static String getKeyFile() { return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); @@ -81,12 +84,20 @@ protected static IntegrationTestEnv getTestEnv() { } protected static Database getDatabase() { - return database; + return getDatabase(Dialect.GOOGLE_STANDARD_SQL); + } + + protected static Database getDatabase(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return postgresDatabase; + } + return googleStandardSqlDatabase; } @BeforeClass public static void setup() { - database = env.getTestHelper().createTestDatabase(); + googleStandardSqlDatabase = env.getTestHelper().createTestDatabase(); + postgresDatabase = env.getTestHelper().createTestDatabase(Dialect.POSTGRESQL, Arrays.asList()); } @AfterClass @@ -101,10 +112,11 @@ public static void teardown() { * * @return The newly opened JDBC connection. */ - public CloudSpannerJdbcConnection createConnection() throws SQLException { + public CloudSpannerJdbcConnection createConnection(Dialect dialect) throws SQLException { // Create a connection URL for the generic connection API. StringBuilder url = - ITAbstractSpannerTest.extractConnectionUrl(env.getTestHelper().getOptions(), getDatabase()); + ITAbstractSpannerTest.extractConnectionUrl( + env.getTestHelper().getOptions(), getDatabase(dialect)); // Prepend it with 'jdbc:' to make it a valid JDBC connection URL. url.insert(0, "jdbc:"); if (hasValidKeyFile()) { @@ -112,7 +124,12 @@ public CloudSpannerJdbcConnection createConnection() throws SQLException { } appendConnectionUri(url); - return DriverManager.getConnection(url.toString()).unwrap(CloudSpannerJdbcConnection.class); + return DriverManager.getConnection(url.toString() + ";dialect=" + dialect.name()) + .unwrap(CloudSpannerJdbcConnection.class); + } + + public CloudSpannerJdbcConnection createConnection() throws SQLException { + return createConnection(Dialect.GOOGLE_STANDARD_SQL); } protected void appendConnectionUri(StringBuilder uri) {} @@ -142,32 +159,42 @@ protected boolean doCreateMusicTables() { @Before public void createTestTable() throws SQLException { if (doCreateDefaultTestTable()) { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(getDialect())) { connection.setAutoCommit(true); if (!tableExists(connection, "TEST")) { connection.setAutoCommit(false); + String createTableDdl; + if (getDialect() == Dialect.GOOGLE_STANDARD_SQL) { + createTableDdl = + "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)"; + } else { + createTableDdl = + "CREATE TABLE TEST (ID BIGINT PRIMARY KEY, NAME VARCHAR(100) NOT NULL)"; + } connection.createStatement().execute("START BATCH DDL"); - connection - .createStatement() - .execute( - "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)"); + connection.createStatement().execute(createTableDdl); connection.createStatement().execute("RUN BATCH"); } } } } + public Dialect getDialect() { + return Dialect.GOOGLE_STANDARD_SQL; + } + @Before public void createMusicTables() throws SQLException { if (doCreateMusicTables()) { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(getDialect())) { connection.setAutoCommit(true); if (!tableExists(connection, "Singers")) { - String scriptFile; + String scriptFile = "CreateMusicTables.sql"; + if (getDialect() == Dialect.POSTGRESQL) { + scriptFile = "CreateMusicTables_PG.sql"; + } if (EmulatorSpannerHelper.isUsingEmulator()) { scriptFile = "CreateMusicTables_Emulator.sql"; - } else { - scriptFile = "CreateMusicTables.sql"; } for (String statement : AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, getClass())) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index 2ec3f1b08c3c..c1c90e8f6cd5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.connection.AbstractConnectionImplTest; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; @@ -30,7 +31,9 @@ import java.sql.SQLException; 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; /** * This test executes a SQL script that has been generated from the log of all the subclasses of @@ -38,16 +41,29 @@ * connection reacts correctly in all possible states (i.e. DML statements should not be allowed * when the connection is in read-only mode, or when a read-only transaction has started etc.) */ -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcConnectionGeneratedSqlScriptTest { + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } static class TestConnectionProvider implements GenericConnectionProvider { + private final Dialect dialect; + + TestConnectionProvider(Dialect dialect) { + this.dialect = dialect; + } + @Override public GenericConnection getConnection() { ConnectionOptions options = mock(ConnectionOptions.class); when(options.getUri()).thenReturn(ConnectionImplTest.URI); com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); + when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); try { JdbcConnection connection = @@ -65,7 +81,7 @@ public GenericConnection getConnection() { @Test public void testGeneratedScript() throws Exception { - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile( "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class, false); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 3205cbb5e569..79eafe01c42d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.SpannerExceptionFactory; @@ -53,28 +54,43 @@ import java.util.concurrent.Executor; 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; import org.mockito.Mockito; -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcConnectionTest { - private static final com.google.cloud.spanner.ResultSet SELECT1_RESULTSET = - ResultSets.forRows( - Type.struct(StructField.of("", Type.int64())), - Collections.singletonList(Struct.newBuilder().set("").to(1L).build())); + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + private com.google.cloud.spanner.ResultSet createSelect1ResultSet() { + return ResultSets.forRows( + Type.struct(StructField.of("", Type.int64())), + Collections.singletonList(Struct.newBuilder().set("").to(1L).build())); + } private JdbcConnection createConnection(ConnectionOptions options) throws SQLException { com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options); + when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); return new JdbcConnection( "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", options); } + private ConnectionOptions mockOptions() { + return mock(ConnectionOptions.class); + } + @Test public void testAutoCommit() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); when(options.isAutocommit()).thenReturn(true); try (Connection connection = createConnection(options)) { assertThat(connection.getAutoCommit()).isTrue(); @@ -90,7 +106,7 @@ public void testAutoCommit() throws SQLException { @Test public void testReadOnly() { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); when(options.isAutocommit()).thenReturn(true); when(options.isReadOnly()).thenReturn(true); try (Connection connection = createConnection(options)) { @@ -109,7 +125,7 @@ public void testReadOnly() { @Test public void testCommit() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { // verify that there is no transaction started assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); @@ -128,7 +144,7 @@ public void testCommit() throws SQLException { @Test public void testRollback() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { // verify that there is no transaction started assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); @@ -302,7 +318,7 @@ private void testClosed( private void testInvokeMethodOnClosedConnection(Method method, Object... args) throws SQLException, IllegalAccessException, IllegalArgumentException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); JdbcConnection connection = createConnection(options); connection.close(); boolean valid = false; @@ -323,7 +339,7 @@ private void testInvokeMethodOnClosedConnection(Method method, Object... args) @Test public void testTransactionIsolation() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { assertThat(connection.getTransactionIsolation()) .isEqualTo(Connection.TRANSACTION_SERIALIZABLE); @@ -359,7 +375,7 @@ public void testTransactionIsolation() throws SQLException { @Test public void testHoldability() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { assertThat(connection.getHoldability()).isEqualTo(ResultSet.CLOSE_CURSORS_AT_COMMIT); // assert that setting it to this value is ok. @@ -388,7 +404,7 @@ public void testHoldability() throws SQLException { @Test public void testWarnings() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { assertThat((Object) connection.getWarnings()).isNull(); @@ -413,7 +429,7 @@ public void testWarnings() throws SQLException { @Test public void getDefaultClientInfo() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { Properties defaultProperties = connection.getClientInfo(); assertThat(defaultProperties.stringPropertyNames()) @@ -423,7 +439,7 @@ public void getDefaultClientInfo() throws SQLException { @Test public void testSetInvalidClientInfo() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { assertThat((Object) connection.getWarnings()).isNull(); connection.setClientInfo("test", "foo"); @@ -445,7 +461,7 @@ public void testSetInvalidClientInfo() throws SQLException { @Test public void testSetClientInfo() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { try (ResultSet validProperties = connection.getMetaData().getClientInfoProperties()) { while (validProperties.next()) { @@ -477,15 +493,16 @@ public void testSetClientInfo() throws SQLException { @Test public void testIsValid() throws SQLException { // Setup. - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); + when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); Statement statement = Statement.of(JdbcConnection.IS_VALID_QUERY); // Verify that an opened connection that returns a result set is valid. try (JdbcConnection connection = new JdbcConnection("url", options)) { - when(spannerConnection.executeQuery(statement)).thenReturn(SELECT1_RESULTSET); + when(spannerConnection.executeQuery(statement)).thenReturn(createSelect1ResultSet()); assertThat(connection.isValid(1)).isTrue(); try { // Invalid timeout value. @@ -506,14 +523,14 @@ public void testIsValid() throws SQLException { @Test public void testIsValidOnClosedConnection() throws SQLException { - Connection connection = createConnection(mock(ConnectionOptions.class)); + Connection connection = createConnection(mockOptions()); connection.close(); assertThat(connection.isValid(1)).isFalse(); } @Test public void testCreateStatement() throws SQLException { - try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + try (JdbcConnection connection = createConnection(mockOptions())) { for (int resultSetType : new int[] { ResultSet.TYPE_FORWARD_ONLY, @@ -587,7 +604,7 @@ private void assertCreateStatementFails( @Test public void testPrepareStatement() throws SQLException { - try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + try (JdbcConnection connection = createConnection(mockOptions())) { for (int resultSetType : new int[] { ResultSet.TYPE_FORWARD_ONLY, @@ -663,7 +680,7 @@ private void assertPrepareStatementFails( @Test public void testPrepareStatementWithAutoGeneratedKeys() throws SQLException { String sql = "INSERT INTO FOO (COL1) VALUES (?)"; - try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + try (JdbcConnection connection = createConnection(mockOptions())) { PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.NO_GENERATED_KEYS); ResultSet rs = statement.getGeneratedKeys(); @@ -679,7 +696,7 @@ public void testPrepareStatementWithAutoGeneratedKeys() throws SQLException { @Test public void testCatalog() throws SQLException { - ConnectionOptions options = mock(ConnectionOptions.class); + 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 @@ -699,7 +716,7 @@ public void testCatalog() throws SQLException { @Test public void testSchema() throws SQLException { - try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + try (JdbcConnection connection = createConnection(mockOptions())) { assertThat(connection.getSchema()).isEqualTo(""); // This should be allowed. connection.setSchema(""); @@ -715,7 +732,7 @@ public void testSchema() throws SQLException { @Test public void testIsReturnCommitStats() throws SQLException { - try (JdbcConnection connection = createConnection(mock(ConnectionOptions.class))) { + try (JdbcConnection connection = createConnection(mockOptions())) { assertFalse(connection.isReturnCommitStats()); connection.setReturnCommitStats(true); assertTrue(connection.isReturnCommitStats()); @@ -724,7 +741,7 @@ public void testIsReturnCommitStats() throws SQLException { @Test public void testIsReturnCommitStats_throwsSqlException() { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); @@ -746,7 +763,7 @@ public void testIsReturnCommitStats_throwsSqlException() { @Test public void testSetReturnCommitStats_throwsSqlException() { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); @@ -769,7 +786,7 @@ public void testSetReturnCommitStats_throwsSqlException() { @Test public void testGetCommitResponse_throwsSqlException() { - ConnectionOptions options = mock(ConnectionOptions.class); + ConnectionOptions options = mockOptions(); com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java index af7b8942b05c..f9011e4f2d36 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataWithMockedServerTest.java @@ -16,12 +16,15 @@ package com.google.cloud.spanner.jdbc; +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; import com.google.cloud.spanner.connection.SpannerPool; -import com.google.cloud.spanner.connection.StatementParser; -import com.google.cloud.spanner.jdbc.JdbcParameterStore.ParametersInfo; import com.google.protobuf.ListValue; import com.google.protobuf.Value; import com.google.spanner.v1.ResultSetMetadata; @@ -39,12 +42,15 @@ import java.sql.SQLException; import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; 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 JdbcDatabaseMetaDataWithMockedServerTest { private static final ResultSetMetadata RESULTSET_METADATA = ResultSetMetadata.newBuilder() @@ -66,8 +72,23 @@ public class JdbcDatabaseMetaDataWithMockedServerTest { .setMetadata(RESULTSET_METADATA) .build(); + private static final String GSQL_STATEMENT = "/*GSQL*/"; + + /* Checks if the SQL statement starts with /*GSQL*/ + private boolean isGoogleSql(String sql) { + return sql.startsWith(GSQL_STATEMENT); + } + + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + private static MockSpannerServiceImpl mockSpanner; private static Server server; + private AbstractStatementParser parser; @BeforeClass public static void startStaticServer() throws IOException { @@ -84,6 +105,11 @@ public static void stopServer() throws Exception { server.awaitTermination(); } + @Before + public void setup() { + parser = AbstractStatementParser.getInstance(dialect); + } + @After public void reset() { // Close Spanner pool to prevent reusage of the same Spanner instance (and thereby the same @@ -106,9 +132,9 @@ private Connection createConnection() throws SQLException { @Test public void getTablesInDdlBatch() throws SQLException { String sql = - StatementParser.removeCommentsAndTrim( + parser.removeCommentsAndTrim( JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetTables.sql")); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -140,9 +166,9 @@ public void getTablesInDdlBatch() throws SQLException { @Test public void getColumnsInDdlBatch() throws SQLException { String sql = - StatementParser.removeCommentsAndTrim( + parser.removeCommentsAndTrim( JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetColumns.sql")); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -175,9 +201,8 @@ public void getKeysInDdlBatch() throws SQLException { "DatabaseMetaData_GetImportedKeys.sql", "DatabaseMetaData_GetExportedKeys.sql" }) { - String sql = - StatementParser.removeCommentsAndTrim(JdbcDatabaseMetaData.readSqlFromFile(fileName)); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + String sql = parser.removeCommentsAndTrim(JdbcDatabaseMetaData.readSqlFromFile(fileName)); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -212,9 +237,9 @@ public void getKeysInDdlBatch() throws SQLException { @Test public void getCrossReferencesInDdlBatch() throws SQLException { String sql = - StatementParser.removeCommentsAndTrim( + parser.removeCommentsAndTrim( JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetCrossReferences.sql")); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -247,9 +272,9 @@ public void getCrossReferencesInDdlBatch() throws SQLException { @Test public void getIndexInfoInDdlBatch() throws SQLException { String sql = - StatementParser.removeCommentsAndTrim( + parser.removeCommentsAndTrim( JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql")); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -280,9 +305,9 @@ public void getIndexInfoInDdlBatch() throws SQLException { @Test public void getSchemasInDdlBatch() throws SQLException { String sql = - StatementParser.removeCommentsAndTrim( + parser.removeCommentsAndTrim( JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetSchemas.sql")); - ParametersInfo params = JdbcParameterStore.convertPositionalParametersToNamedParameters(sql); + ParametersInfo params = parser.convertPositionalParametersToNamedParameters('?', sql); mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder(params.sqlWithNamedParameters) @@ -306,4 +331,99 @@ public void getSchemasInDdlBatch() throws SQLException { connection.createStatement().execute("ABORT BATCH"); } } + + @Test + public void verifyGoogleSqlHeaderIsCorrectlyParsed() { + // Verify that the `/*GSQL*/` header is kept in the SQL statement without comments if the + // dialect is PostgreSQL, and that it is removed if the dialect is Google_Standard_Sql. + if (dialect == Dialect.POSTGRESQL) { + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetCrossReferences.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetImportedKeys.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetPrimaryKeys.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetTables.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetColumns.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetExportedKeys.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql")))) + .isTrue(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetSchemas.sql")))) + .isTrue(); + } else { + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetCrossReferences.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetImportedKeys.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetPrimaryKeys.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetTables.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetColumns.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile( + "DatabaseMetaData_GetExportedKeys.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetIndexInfo.sql")))) + .isFalse(); + assertThat( + isGoogleSql( + parser.removeCommentsAndTrim( + JdbcDatabaseMetaData.readSqlFromFile("DatabaseMetaData_GetSchemas.sql")))) + .isFalse(); + } + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 0668f88fa9b0..2c1bfe820dc7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -19,9 +19,11 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; +import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl; import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl; @@ -113,7 +115,6 @@ public static void startStaticServer() throws IOException { @AfterClass public static void stopServer() throws Exception { - SpannerPool.closeSpannerPool(); server.shutdown(); server.awaitTermination(); } @@ -122,7 +123,20 @@ public static void stopServer() throws Exception { public void reset() { // Close Spanner pool to prevent reusage of the same Spanner instance (and thereby the same // session pool). - SpannerPool.closeSpannerPool(); + try { + SpannerPool.closeSpannerPool(); + } catch (SpannerException e) { + // Ignore leaked session errors that can be caused by the internal dialect auto-detection that + // is executed at startup. This query can still be running when an error is caused by tests in + // this class, and that will be registered as a session leak as that session has not yet been + // checked in to the pool. + if (!(e.getErrorCode() == ErrorCode.FAILED_PRECONDITION + && e.getMessage() + .contains( + "There is/are 1 connection(s) still open. Close all connections before calling closeSpanner()"))) { + throw e; + } + } mockSpanner.removeAllExecutionTimes(); mockSpanner.reset(); } @@ -205,7 +219,13 @@ public void autocommitExecuteSql() { } @Test - public void autocommitPDMLExecuteSql() { + public void autocommitPDMLExecuteSql() throws SQLException { + // Make sure the dialect auto-detection has finished before we instruct the RPC to always return + // an error. + try (java.sql.Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).getDialect(); + } + mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { @@ -316,7 +336,13 @@ public void transactionalRollback() throws SQLException { } @Test - public void autocommitExecuteStreamingSql() { + public void autocommitExecuteStreamingSql() throws SQLException { + // Make sure the dialect auto-detection has finished before we instruct the RPC to always return + // an error. + try (java.sql.Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).getDialect(); + } + mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 89f4ae4cf8d6..0596d829e514 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -16,18 +16,20 @@ package com.google.cloud.spanner.jdbc; -import static com.google.cloud.spanner.jdbc.JdbcParameterStore.convertPositionalParametersToNamedParameters; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.common.io.CharStreams; -import com.google.common.truth.Truth; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -43,20 +45,39 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.Collections; import java.util.UUID; +import org.junit.Before; 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 JdbcParameterStoreTest { + @Parameters(name = "dialect = {0}") + public static Object[] parameters() { + return Dialect.values(); + } + + @Parameter public Dialect dialect; + + private AbstractStatementParser parser; + + @Before + public void setUp() { + parser = AbstractStatementParser.getInstance(dialect); + } /** Tests setting a {@link Value} as a parameter value. */ @Test public void testSetValueAsParameter() throws SQLException { - JdbcParameterStore params = new JdbcParameterStore(); + JdbcParameterStore params = new JdbcParameterStore(dialect); params.setParameter(1, Value.bool(true)); verifyParameter(params, Value.bool(true)); params.setParameter(1, Value.bytes(ByteArray.copyFrom("test"))); @@ -108,7 +129,7 @@ public void testSetValueAsParameter() throws SQLException { @SuppressWarnings("deprecation") @Test public void testSetParameterWithType() throws SQLException, IOException { - JdbcParameterStore params = new JdbcParameterStore(); + JdbcParameterStore params = new JdbcParameterStore(dialect); // test the valid default combinations params.setParameter(1, true, Types.BOOLEAN); assertTrue((Boolean) params.getParameter(1)); @@ -150,6 +171,24 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(new Timestamp(0L), params.getParameter(1)); verifyParameter( params, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(0L, 0))); + OffsetDateTime offsetDateTime = + OffsetDateTime.of(2021, 9, 24, 12, 27, 59, 42457, ZoneOffset.ofHours(2)); + params.setParameter(1, offsetDateTime, Types.TIMESTAMP_WITH_TIMEZONE); + assertEquals(offsetDateTime, params.getParameter(1)); + verifyParameter( + params, + Value.timestamp( + com.google.cloud.Timestamp.ofTimeSecondsAndNanos( + offsetDateTime.toEpochSecond(), offsetDateTime.getNano()))); + LocalDate localDate = LocalDate.of(2021, 9, 24); + params.setParameter(1, localDate, Types.DATE); + assertEquals(localDate, params.getParameter(1)); + verifyParameter( + params, + Value.date( + com.google.cloud.Date.fromYearMonthDay( + localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth()))); + params.setParameter(1, new byte[] {1, 2, 3}, Types.BINARY); assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); @@ -187,7 +226,11 @@ public void testSetParameterWithType() throws SQLException, IOException { verifyParameter(params, Value.json(jsonString)); params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + if (dialect == Dialect.POSTGRESQL) { + verifyParameter(params, Value.pgNumeric(BigDecimal.ONE.toString())); + } else { + verifyParameter(params, Value.numeric(BigDecimal.ONE)); + } // types that should lead to int64 for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { @@ -340,34 +383,41 @@ public void testSetParameterWithType() throws SQLException, IOException { // types that should lead to numeric for (int type : new int[] {Types.DECIMAL, Types.NUMERIC}) { + final Value expectedIntegralNumeric = + dialect == Dialect.POSTGRESQL ? Value.pgNumeric("1") : Value.numeric(BigDecimal.ONE); + final Value expectedRationalNumeric = + dialect == Dialect.POSTGRESQL + ? Value.pgNumeric("1.0") + : Value.numeric(BigDecimal.valueOf(1.0)); + params.setParameter(1, BigDecimal.ONE, type); assertEquals(BigDecimal.ONE, params.getParameter(1)); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + verifyParameter(params, expectedIntegralNumeric); params.setParameter(1, (byte) 1, type); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + verifyParameter(params, expectedIntegralNumeric); params.setParameter(1, (short) 1, type); assertEquals(1, ((Short) params.getParameter(1)).shortValue()); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + verifyParameter(params, expectedIntegralNumeric); params.setParameter(1, 1, type); assertEquals(1, ((Integer) params.getParameter(1)).intValue()); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + verifyParameter(params, expectedIntegralNumeric); params.setParameter(1, 1L, type); assertEquals(1, ((Long) params.getParameter(1)).longValue()); - verifyParameter(params, Value.numeric(BigDecimal.ONE)); + verifyParameter(params, expectedIntegralNumeric); params.setParameter(1, (float) 1, type); assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); - verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); + verifyParameter(params, expectedRationalNumeric); params.setParameter(1, (double) 1, type); assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); - verifyParameter(params, Value.numeric(BigDecimal.valueOf(1.0))); + verifyParameter(params, expectedRationalNumeric); } } @Test public void testSetInvalidParameterWithType() throws SQLException, IOException { - JdbcParameterStore params = new JdbcParameterStore(); + JdbcParameterStore params = new JdbcParameterStore(dialect); // types that should lead to int64, but with invalid values. for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { @@ -484,7 +534,7 @@ private void assertInvalidParameter(JdbcParameterStore params, Object value, int @SuppressWarnings("deprecation") @Test public void testSetParameterWithoutType() throws SQLException { - JdbcParameterStore params = new JdbcParameterStore(); + JdbcParameterStore params = new JdbcParameterStore(dialect); params.setParameter(1, (byte) 1, (Integer) null); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); @@ -563,7 +613,7 @@ private boolean asciiStreamsEqual(InputStream is1, InputStream is2) throws IOExc /** Tests setting array types of parameters */ @Test public void testSetArrayParameter() throws SQLException { - JdbcParameterStore params = new JdbcParameterStore(); + JdbcParameterStore params = new JdbcParameterStore(dialect); params.setParameter( 1, JdbcArray.createArray("BOOL", new Boolean[] {true, false, true}), Types.ARRAY); assertEquals( @@ -737,40 +787,47 @@ private void verifyParameterBindFails(JdbcParameterStore params) throws SQLExcep } @Test - public void testConvertPositionalParametersToNamedParameters() throws SQLException { + public void testGoogleStandardSQLDialectConvertPositionalParametersToNamedParameters() { + assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); assertEquals( "select * from foo where name=@p1", - convertPositionalParametersToNamedParameters("select * from foo where name=?") + parser.convertPositionalParametersToNamedParameters('?', "select * from foo where name=?") .sqlWithNamedParameters); assertEquals( "@p1'?test?\"?test?\"?'@p2", - convertPositionalParametersToNamedParameters("?'?test?\"?test?\"?'?") + parser.convertPositionalParametersToNamedParameters('?', "?'?test?\"?test?\"?'?") .sqlWithNamedParameters); assertEquals( "@p1'?it\\'?s'@p2", - convertPositionalParametersToNamedParameters("?'?it\\'?s'?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s'?") + .sqlWithNamedParameters); assertEquals( "@p1'?it\\\"?s'@p2", - convertPositionalParametersToNamedParameters("?'?it\\\"?s'?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\\"?s'?") + .sqlWithNamedParameters); assertEquals( "@p1\"?it\\\"?s\"@p2", - convertPositionalParametersToNamedParameters("?\"?it\\\"?s\"?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?\"?it\\\"?s\"?") + .sqlWithNamedParameters); assertEquals( "@p1`?it\\`?s`@p2", - convertPositionalParametersToNamedParameters("?`?it\\`?s`?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?`?it\\`?s`?") + .sqlWithNamedParameters); assertEquals( "@p1'''?it\\'?s'''@p2", - convertPositionalParametersToNamedParameters("?'''?it\\'?s'''?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s'''?") + .sqlWithNamedParameters); assertEquals( "@p1\"\"\"?it\\\"?s\"\"\"@p2", - convertPositionalParametersToNamedParameters("?\"\"\"?it\\\"?s\"\"\"?") + parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") .sqlWithNamedParameters); assertEquals( "@p1```?it\\`?s```@p2", - convertPositionalParametersToNamedParameters("?```?it\\`?s```?").sqlWithNamedParameters); + parser.convertPositionalParametersToNamedParameters('?', "?```?it\\`?s```?") + .sqlWithNamedParameters); assertEquals( "@p1'''?it\\'?s \n ?it\\'?s'''@p2", - convertPositionalParametersToNamedParameters("?'''?it\\'?s \n ?it\\'?s'''?") + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s \n ?it\\'?s'''?") .sqlWithNamedParameters); assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); @@ -779,23 +836,26 @@ public void testConvertPositionalParametersToNamedParameters() throws SQLExcepti assertEquals( "select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'", - convertPositionalParametersToNamedParameters( + parser.convertPositionalParametersToNamedParameters( + '?', "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") .sqlWithNamedParameters); assertEquals( "select * " + "from foo " + "where name=@p1 " + "and col2 like @p2 " + "and col3 > @p3", - convertPositionalParametersToNamedParameters( + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") .sqlWithNamedParameters); assertEquals( "select * " + "from foo " + "where id between @p1 and @p2", - convertPositionalParametersToNamedParameters( - "select * " + "from foo " + "where id between ? and ?") + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where id between ? and ?") .sqlWithNamedParameters); assertEquals( "select * " + "from foo " + "limit @p1 offset @p2", - convertPositionalParametersToNamedParameters("select * " + "from foo " + "limit ? offset ?") + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "limit ? offset ?") .sqlWithNamedParameters); assertEquals( "select * " @@ -808,7 +868,93 @@ public void testConvertPositionalParametersToNamedParameters() throws SQLExcepti + "and col6 not in (@p6, @p7, @p8) " + "and col7 in (@p9, @p10, @p11) " + "and col8 between @p12 and @p13", - convertPositionalParametersToNamedParameters( + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + + "from foo " + + "where col1=? " + + "and col2 like ? " + + "and col3 > ? " + + "and col4 < ? " + + "and col5 != ? " + + "and col6 not in (?, ?, ?) " + + "and col7 in (?, ?, ?) " + + "and col8 between ? and ?") + .sqlWithNamedParameters); + } + + @Test + public void testPostgresDialectConvertPositionalParametersToNamedParameters() { + assumeTrue(dialect == Dialect.POSTGRESQL); + assertEquals( + "select * from foo where name=$1", + parser.convertPositionalParametersToNamedParameters('?', "select * from foo where name=?") + .sqlWithNamedParameters); + assertEquals( + "$1'?test?\"?test?\"?'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?test?\"?test?\"?'?") + .sqlWithNamedParameters); + assertEquals( + "$1'?it\\'?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s'?") + .sqlWithNamedParameters); + assertEquals( + "$1'?it\\\"?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\\"?s'?") + .sqlWithNamedParameters); + assertEquals( + "$1\"?it\\\"?s\"$2", + parser.convertPositionalParametersToNamedParameters('?', "?\"?it\\\"?s\"?") + .sqlWithNamedParameters); + assertEquals( + "$1'''?it\\'?s'''$2", + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s'''?") + .sqlWithNamedParameters); + assertEquals( + "$1\"\"\"?it\\\"?s\"\"\"$2", + parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") + .sqlWithNamedParameters); + + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); + assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); + + assertEquals( + "select 1, $1, 'test?test', \"test?test\", foo.* from `foo` where col1=$2 and col2='test' and col3=$3 and col4='?' and col5=\"?\" and col6='?''?''?'", + parser.convertPositionalParametersToNamedParameters( + '?', + "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") + .sqlWithNamedParameters); + + assertEquals( + "select * " + "from foo " + "where name=$1 " + "and col2 like $2 " + "and col3 > $3", + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") + .sqlWithNamedParameters); + assertEquals( + "select * " + "from foo " + "where id between $1 and $2", + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where id between ? and ?") + .sqlWithNamedParameters); + assertEquals( + "select * " + "from foo " + "limit $1 offset $2", + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "limit ? offset ?") + .sqlWithNamedParameters); + assertEquals( + "select * " + + "from foo " + + "where col1=$1 " + + "and col2 like $2 " + + "and col3 > $3 " + + "and col4 < $4 " + + "and col5 != $5 " + + "and col6 not in ($6, $7, $8) " + + "and col7 in ($9, $10, $11) " + + "and col8 between $12 and $13", + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where col1=? " @@ -824,17 +970,16 @@ public void testConvertPositionalParametersToNamedParameters() throws SQLExcepti private void assertUnclosedLiteral(String sql) { try { - convertPositionalParametersToNamedParameters(sql); + parser.convertPositionalParametersToNamedParameters('?', sql); fail("missing expected exception"); - } catch (SQLException t) { - Truth.assertThat((Throwable) t).isInstanceOf(JdbcSqlException.class); - JdbcSqlException e = (JdbcSqlException) t; - Truth.assertThat(e.getCode()).isSameInstanceAs(Code.INVALID_ARGUMENT); - Truth.assertThat(e.getMessage()) - .startsWith( - Code.INVALID_ARGUMENT.name() - + ": SQL statement contains an unclosed literal: " - + sql); + } catch (SpannerException e) { + assertEquals(Code.INVALID_ARGUMENT.getNumber(), e.getCode()); + assertTrue( + e.getMessage() + .startsWith( + Code.INVALID_ARGUMENT.name() + + ": SQL statement contains an unclosed literal: " + + sql)); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index fdc9969cb409..99f8974159cc 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; 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; @@ -26,6 +27,8 @@ import static org.mockito.Mockito.when; import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.ResultSets; @@ -34,6 +37,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; 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; @@ -55,10 +59,19 @@ import java.util.UUID; 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 JdbcPreparedStatementTest { + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + private String generateSqlWithParameters(int numberOfParams) { StringBuilder sql = new StringBuilder("INSERT INTO FOO ("); boolean first = true; @@ -90,6 +103,8 @@ private JdbcConnection createMockConnection() throws SQLException { private JdbcConnection createMockConnection(Connection spanner) throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + when(connection.getParser()).thenReturn(AbstractStatementParser.getInstance(dialect)); when(connection.getSpannerConnection()).thenReturn(spanner); when(connection.createBlob()).thenCallRealMethod(); when(connection.createClob()).thenCallRealMethod(); @@ -329,7 +344,10 @@ public void testGetResultSetMetadata() throws SQLException { Type.struct( StructField.of("ID", Type.int64()), StructField.of("NAME", Type.string()), - StructField.of("AMOUNT", Type.float64())), + StructField.of("AMOUNT", Type.float64()), + dialect == Dialect.POSTGRESQL + ? StructField.of("PERCENTAGE", Type.pgNumeric()) + : StructField.of("PERCENTAGE", Type.numeric())), Collections.singletonList( Struct.newBuilder() .set("ID") @@ -338,18 +356,25 @@ public void testGetResultSetMetadata() throws SQLException { .to("foo") .set("AMOUNT") .to(Math.PI) + .set("PERCENTAGE") + .to( + dialect == Dialect.POSTGRESQL + ? Value.pgNumeric("1.23") + : Value.numeric(new BigDecimal("1.23"))) .build())); when(connection.analyzeQuery(Statement.of(sql), QueryAnalyzeMode.PLAN)).thenReturn(rs); try (JdbcPreparedStatement ps = new JdbcPreparedStatement(createMockConnection(connection), sql)) { ResultSetMetaData metadata = ps.getMetaData(); - assertEquals(3, metadata.getColumnCount()); + assertEquals(4, metadata.getColumnCount()); assertEquals("ID", metadata.getColumnLabel(1)); assertEquals("NAME", metadata.getColumnLabel(2)); assertEquals("AMOUNT", metadata.getColumnLabel(3)); + assertEquals("PERCENTAGE", metadata.getColumnLabel(4)); assertEquals(Types.BIGINT, metadata.getColumnType(1)); assertEquals(Types.NVARCHAR, metadata.getColumnType(2)); assertEquals(Types.DOUBLE, metadata.getColumnType(3)); + assertEquals(Types.NUMERIC, metadata.getColumnType(4)); } } @@ -363,4 +388,17 @@ public void testGetResultSetMetaDataForDml() throws SQLException { assertEquals(0, metadata.getColumnCount()); } } + + @Test + public void testInvalidSql() { + String sql = "SELECT * FROM Singers WHERE SingerId='"; + SQLException sqlException = + assertThrows( + SQLException.class, + () -> new JdbcPreparedStatement(createMockConnection(mock(Connection.class)), sql)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals( + ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value(), jdbcSqlException.getErrorCode()); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 7ed85ef89ccc..024f6c24369b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -49,6 +49,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Time; +import java.time.Instant; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; @@ -1729,4 +1733,24 @@ public void testGetObjectAsValue() throws SQLException { Value.timestampArray(TIMESTAMP_ARRAY_VALUE), subject.getObject(TIMESTAMP_ARRAY_COL, Value.class)); } + + @Test + public void testGetLocalDate() throws SQLException { + LocalDate localDate = subject.getObject(DATE_COL_NOT_NULL, LocalDate.class); + assertEquals( + LocalDate.of(DATE_VALUE.getYear(), DATE_VALUE.getMonth(), DATE_VALUE.getDayOfMonth()), + localDate); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetOffsetDateTime() throws SQLException { + OffsetDateTime offsetDateTime = subject.getObject(TIMESTAMP_COL_NOT_NULL, OffsetDateTime.class); + assertEquals( + OffsetDateTime.ofInstant( + Instant.ofEpochSecond(TIMESTAMP_VALUE.getSeconds(), TIMESTAMP_VALUE.getNanos()), + ZoneOffset.systemDefault()), + offsetDateTime); + assertFalse(subject.wasNull()); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java index 3143d5ac1db3..51e1213370d1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -19,12 +19,12 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; -import com.google.cloud.spanner.connection.StatementParser; +import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.StatementResult.ResultType; import com.google.rpc.Code; import java.sql.Array; -import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -118,18 +118,18 @@ protected Object getFirstValue() throws Exception { } public static class JdbcGenericConnection extends GenericConnection { - private final Connection connection; + private final CloudSpannerJdbcConnection connection; /** * Use this to strip comments from a statement before the statement is executed. This should * only be used when the connection is used in a unit test with a mocked underlying connection. */ private boolean stripCommentsBeforeExecute; - public static JdbcGenericConnection of(Connection connection) { + public static JdbcGenericConnection of(CloudSpannerJdbcConnection connection) { return new JdbcGenericConnection(connection); } - private JdbcGenericConnection(Connection connection) { + private JdbcGenericConnection(CloudSpannerJdbcConnection connection) { this.connection = connection; } @@ -137,7 +137,7 @@ private JdbcGenericConnection(Connection connection) { protected GenericStatementResult execute(String sql) throws SQLException { Statement statement = connection.createStatement(); if (isStripCommentsBeforeExecute()) { - sql = StatementParser.removeCommentsAndTrim(sql); + sql = AbstractStatementParser.getInstance(getDialect()).removeCommentsAndTrim(sql); } boolean result = statement.execute(sql); return new JdbcGenericStatementResult(statement, result); @@ -157,6 +157,11 @@ boolean isStripCommentsBeforeExecute() { void setStripCommentsBeforeExecute(boolean stripCommentsBeforeExecute) { this.stripCommentsBeforeExecute = stripCommentsBeforeExecute; } + + @Override + public Dialect getDialect() { + return connection.getDialect(); + } } public JdbcSqlScriptVerifier() {} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index e73be4ef7479..3ee9edcb6bd9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -24,11 +24,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.Connection; -import com.google.cloud.spanner.connection.StatementParser; import com.google.cloud.spanner.connection.StatementResult; import com.google.cloud.spanner.connection.StatementResult.ResultType; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; @@ -42,19 +43,29 @@ import java.util.concurrent.TimeUnit; 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; import org.mockito.stubbing.Answer; -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcStatementTest { private static final String SELECT = "SELECT 1"; private static final String UPDATE = "UPDATE FOO SET BAR=1 WHERE BAZ=2"; private static final String LARGE_UPDATE = "UPDATE FOO SET BAR=1 WHERE 1=1"; private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + @SuppressWarnings("unchecked") - private JdbcStatement createStatement() { + private JdbcStatement createStatement() throws SQLException { Connection spanner = mock(Connection.class); + when(spanner.getDialect()).thenReturn(dialect); com.google.cloud.spanner.ResultSet resultSet = mock(com.google.cloud.spanner.ResultSet.class); when(resultSet.next()).thenReturn(true, false); @@ -106,7 +117,8 @@ private JdbcStatement createStatement() { List statements = (List) invocation.getArguments()[0]; if (statements.isEmpty() - || StatementParser.INSTANCE.isDdlStatement(statements.get(0).getSql())) { + || AbstractStatementParser.getInstance(dialect) + .isDdlStatement(statements.get(0).getSql())) { return new long[0]; } long[] res = @@ -118,6 +130,8 @@ private JdbcStatement createStatement() { }); JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + when(connection.getParser()).thenReturn(AbstractStatementParser.getInstance(dialect)); when(connection.getSpannerConnection()).thenReturn(spanner); return new JdbcStatement(connection); } @@ -126,6 +140,7 @@ private JdbcStatement createStatement() { public void testQueryTimeout() throws SQLException { final String select = "SELECT 1"; JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); Connection spanner = mock(Connection.class); when(connection.getSpannerConnection()).thenReturn(spanner); StatementResult result = mock(StatementResult.class); @@ -230,8 +245,8 @@ public void testExecuteQuery() throws SQLException { @Test public void testExecuteQueryWithUpdateStatement() { - Statement statement = createStatement(); try { + Statement statement = createStatement(); statement.executeQuery(UPDATE); fail("missing expected exception"); } catch (SQLException e) { @@ -244,8 +259,8 @@ public void testExecuteQueryWithUpdateStatement() { @Test public void testExecuteQueryWithDdlStatement() { - Statement statement = createStatement(); try { + Statement statement = createStatement(); statement.executeQuery(DDL); fail("missing expected exception"); } catch (SQLException e) { @@ -271,6 +286,7 @@ public void testExecuteUpdate() throws SQLException { @Test public void testInternalExecuteUpdate() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); Connection spannerConnection = mock(Connection.class); when(connection.getSpannerConnection()).thenReturn(spannerConnection); com.google.cloud.spanner.Statement updateStatement = @@ -293,6 +309,7 @@ public void testInternalExecuteUpdate() throws SQLException { @Test public void testInternalExecuteLargeUpdate() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); Connection spannerConnection = mock(Connection.class); when(connection.getSpannerConnection()).thenReturn(spannerConnection); com.google.cloud.spanner.Statement updateStatement = @@ -329,8 +346,8 @@ public void testExecuteLargeUpdate() throws SQLException { @Test public void testExecuteUpdateWithSelectStatement() { - Statement statement = createStatement(); try { + Statement statement = createStatement(); statement.executeUpdate(SELECT); fail("missing expected exception"); } catch (SQLException e) { @@ -436,7 +453,9 @@ public void testLargeDmlBatch() throws SQLException { @Test public void testConvertUpdateCounts() { - try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { + JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + try (JdbcStatement statement = new JdbcStatement(connection)) { int[] updateCounts = statement.convertUpdateCounts(new long[] {1L, 2L, 3L}); assertThat(updateCounts).asList().containsExactly(1, 2, 3); updateCounts = statement.convertUpdateCounts(new long[] {0L, 0L, 0L}); @@ -450,8 +469,10 @@ public void testConvertUpdateCounts() { } @Test - public void testConvertUpdateCountsToSuccessNoInfo() { - try (JdbcStatement statement = new JdbcStatement(mock(JdbcConnection.class))) { + public void testConvertUpdateCountsToSuccessNoInfo() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + try (JdbcStatement statement = new JdbcStatement(connection)) { long[] updateCounts = new long[3]; statement.convertUpdateCountsToSuccessNoInfo(new long[] {1L, 2L, 3L}, updateCounts); assertThat(updateCounts) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java index 8e36a7db10f8..cd462b431826 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java @@ -16,12 +16,15 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.jdbc.JdbcConnectionGeneratedSqlScriptTest.TestConnectionProvider; import java.sql.Connection; import java.sql.Statement; 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; /** * As JDBC connections store the statement timeout on {@link Statement} objects instead of on the @@ -30,11 +33,19 @@ * timeouts, while the underlying {@link com.google.cloud.spanner.connection.Connection}s use * milliseconds. This test script tests a number of special cases regarding this. */ -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcTimeoutSqlTest { + + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + @Test public void testTimeoutScript() throws Exception { - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider()); + JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass(), false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java new file mode 100644 index 000000000000..fde7c42e03e2 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java @@ -0,0 +1,338 @@ +/* + * Copyright 2022 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 com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.Type; +import com.google.spanner.v1.TypeAnnotationCode; +import com.google.spanner.v1.TypeCode; +import io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.math.BigDecimal; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Arrays; +import java.util.Map; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PgNumericPreparedStatementTest { + + private static final String PROJECT = "my-project"; + private static final String INSTANCE = "my-instance"; + private static final String DATABASE = "my-database"; + private static final String QUERY = "INSERT INTO Table (col1) VALUES (?)"; + private static final String REWRITTEN_QUERY = "INSERT INTO Table (col1) VALUES ($1)"; + private static MockSpannerServiceImpl mockSpanner; + private static InetSocketAddress address; + private static Server server; + private Connection connection; + + @BeforeClass + public static void beforeClass() throws Exception { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); + mockSpanner.putStatementResult(StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void afterClass() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + @Before + public void setUp() throws Exception { + final String endpoint = address.getHostString() + ":" + server.getPort(); + final String url = + String.format( + "jdbc:cloudspanner://%s/projects/%s/instances/%s/databases/%s?usePlainText=true;dialect=POSTGRESQL", + endpoint, PROJECT, INSTANCE, DATABASE); + connection = DriverManager.getConnection(url); + mockSpanner.reset(); + } + + @After + public void tearDown() throws Exception { + connection.close(); + } + + @Test + public void testSetByteAsObject() throws SQLException { + final Byte param = 1; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetShortAsObject() throws SQLException { + final Short param = 1; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetIntAsObject() throws SQLException { + final Integer param = 1; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetLongAsObject() throws SQLException { + final Long param = 1L; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetFloatAsObject() throws SQLException { + final Float param = 1F; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetFloatNaNAsObject() throws SQLException { + final Float param = Float.NaN; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetDoubleAsObject() throws SQLException { + final Double param = 1D; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetDoubleNaNAsObject() throws SQLException { + final Double param = Double.NaN; + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetBigDecimalAsObject() throws SQLException { + final BigDecimal param = new BigDecimal("1.23"); + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetBigDecimalAsObjectWithoutExplicitType() throws SQLException { + final BigDecimal param = new BigDecimal("1.23"); + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setObject(1, param); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetBigDecimal() throws SQLException { + final BigDecimal param = new BigDecimal("1"); + + mockScalarUpdateWithParam(param.toString()); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setBigDecimal(1, param); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(param.toString()); + } + + @Test + public void testSetNull() throws SQLException { + mockScalarUpdateWithParam(null); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setNull(1, Types.NUMERIC); + preparedStatement.executeUpdate(); + } + assertRequestWithScalar(null); + } + + @Test + public void testSetNumericArray() throws SQLException { + final BigDecimal[] param = {BigDecimal.ONE, null, BigDecimal.TEN}; + + mockArrayUpdateWithParam(Arrays.asList("1", null, "10")); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setArray(1, connection.createArrayOf("numeric", param)); + preparedStatement.executeUpdate(); + } + assertRequestWithArray(Arrays.asList("1", null, "10")); + } + + @Test + public void testSetNullArray() throws SQLException { + mockArrayUpdateWithParam(null); + try (PreparedStatement preparedStatement = connection.prepareStatement(QUERY)) { + preparedStatement.setArray(1, connection.createArrayOf("numeric", null)); + preparedStatement.executeUpdate(); + } + assertRequestWithArray(null); + } + + private void mockScalarUpdateWithParam(String value) { + mockSpanner.putStatementResult( + StatementResult.update( + Statement.newBuilder(REWRITTEN_QUERY) + .bind("p1") + .to(com.google.cloud.spanner.Value.pgNumeric(value)) + .build(), + 1)); + } + + private void mockArrayUpdateWithParam(Iterable value) { + mockSpanner.putStatementResult( + StatementResult.update( + Statement.newBuilder(REWRITTEN_QUERY) + .bind("p1") + .to(com.google.cloud.spanner.Value.pgNumericArray(value)) + .build(), + 1)); + } + + private void assertRequestWithScalar(String value) { + final ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + final String actualSql = request.getSql(); + final Struct actualParams = request.getParams(); + final Map actualParamTypes = request.getParamTypesMap(); + + final Value parameterValue = protoValueFromString(value); + final Struct expectedParams = Struct.newBuilder().putFields("p1", parameterValue).build(); + final ImmutableMap expectedTypes = + ImmutableMap.of( + "p1", + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build()); + assertEquals(REWRITTEN_QUERY, actualSql); + assertEquals(expectedParams, actualParams); + assertEquals(expectedTypes, actualParamTypes); + } + + private void assertRequestWithArray(Iterable value) { + final ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + final String actualSql = request.getSql(); + final Struct actualParams = request.getParams(); + final Map actualParamTypes = request.getParamTypesMap(); + + Value parameterValue; + if (value != null) { + final ListValue.Builder builder = ListValue.newBuilder(); + value.forEach(v -> builder.addValues(protoValueFromString(v))); + parameterValue = Value.newBuilder().setListValue(builder.build()).build(); + } else { + parameterValue = Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); + } + final Struct expectedParams = Struct.newBuilder().putFields("p1", parameterValue).build(); + final ImmutableMap expectedTypes = + ImmutableMap.of( + "p1", + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC)) + .build()); + assertEquals(REWRITTEN_QUERY, actualSql); + assertEquals(expectedParams, actualParams); + assertEquals(expectedTypes, actualParamTypes); + } + + private Value protoValueFromString(String value) { + if (value == null) { + return Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); + } else { + return Value.newBuilder().setStringValue(value).build(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java new file mode 100644 index 000000000000..119897af9c0b --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java @@ -0,0 +1,801 @@ +/* + * Copyright 2021 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 com.google.protobuf.NullValue.NULL_VALUE; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +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 com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.common.io.ByteSource; +import com.google.protobuf.ListValue; +import com.google.spanner.v1.ResultSetMetadata; +import com.google.spanner.v1.StructType; +import com.google.spanner.v1.StructType.Field; +import com.google.spanner.v1.TypeAnnotationCode; +import com.google.spanner.v1.TypeCode; +import io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.InetSocketAddress; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.DriverManager; +import java.sql.NClob; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PgNumericResultSetTest { + + private static final String PROJECT = "my-project"; + private static final String INSTANCE = "my-instance"; + private static final String DATABASE = "my-database"; + private static final String COLUMN_NAME = "PgNumeric"; + private static final ResultSetMetadata SCALAR_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName(COLUMN_NAME) + .setType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC)))) + .build(); + private static final ResultSetMetadata ARRAY_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName(COLUMN_NAME) + .setType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC))))) + .build(); + private static final String QUERY = "SELECT " + COLUMN_NAME + " FROM Table WHERE Id = 0"; + private static final int MAX_PG_NUMERIC_SCALE = 131_072; + private static final int MAX_PG_NUMERIC_PRECISION = 16_383; + + private static MockSpannerServiceImpl mockSpanner; + private static InetSocketAddress address; + private static Server server; + private Connection connection; + + @BeforeClass + public static void beforeClass() throws Exception { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); + + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void afterClass() throws Exception { + SpannerPool.closeSpannerPool(); + server.shutdown(); + server.awaitTermination(); + } + + @Before + public void setUp() throws Exception { + final String endpoint = address.getHostString() + ":" + server.getPort(); + final String url = + String.format( + "jdbc:cloudspanner://%s/projects/%s/instances/%s/databases/%s?usePlainText=true", + endpoint, PROJECT, INSTANCE, DATABASE); + connection = DriverManager.getConnection(url); + } + + @After + public void tearDown() throws Exception { + connection.close(); + } + + @Test + public void testGetString() throws Exception { + final String maxScale = String.join("", Collections.nCopies(MAX_PG_NUMERIC_SCALE, "1")); + final String maxPrecision = + "0." + String.join("", Collections.nCopies(MAX_PG_NUMERIC_PRECISION, "2")); + + mockScalarResults("0", "1", "1.23", maxScale, maxPrecision, "NaN", null); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getString, ResultSet::getString); + + matcher.nextAndAssertEquals("0"); + matcher.nextAndAssertEquals("1"); + matcher.nextAndAssertEquals("1.23"); + matcher.nextAndAssertEquals(maxScale); + matcher.nextAndAssertEquals(maxPrecision); + matcher.nextAndAssertEquals("NaN"); + matcher.nextAndAssertEquals(null); + } + } + + @Test + public void testGetNString() throws Exception { + final String maxScale = String.join("", Collections.nCopies(MAX_PG_NUMERIC_SCALE, "1")); + final String maxPrecision = + "0." + String.join("", Collections.nCopies(MAX_PG_NUMERIC_PRECISION, "2")); + + mockScalarResults("0", "1", "1.23", maxScale, maxPrecision, "NaN", null); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getNString, ResultSet::getNString); + + matcher.nextAndAssertEquals("0"); + matcher.nextAndAssertEquals("1"); + matcher.nextAndAssertEquals("1.23"); + matcher.nextAndAssertEquals(maxScale); + matcher.nextAndAssertEquals(maxPrecision); + matcher.nextAndAssertEquals("NaN"); + matcher.nextAndAssertEquals(null); + } + } + + @Test + public void testGetBoolean() throws Exception { + mockScalarResults("0", null, "1", "NaN", "1.00"); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getBoolean, ResultSet::getBoolean); + + // 0 == false + matcher.nextAndAssertEquals(false); + // NULL == false + matcher.nextAndAssertEquals(false); + // anything else == true + matcher.nextAndAssertEquals(true); // "1" == true + matcher.nextAndAssertEquals(true); // "Nan" == true + matcher.nextAndAssertEquals(true); // "1.00" == true + } + } + + @Test + public void testGetByte() throws Exception { + final String minValue = Byte.MIN_VALUE + ""; + final String underflow = String.valueOf((int) Byte.MIN_VALUE - 1); + final String maxValue = Byte.MAX_VALUE + ""; + final String overflow = String.valueOf((int) Short.MAX_VALUE + 1); + + mockScalarResults(minValue, maxValue, "1.23", null, "NaN", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getByte, ResultSet::getByte); + + matcher.nextAndAssertEquals(Byte.MIN_VALUE); + matcher.nextAndAssertEquals(Byte.MAX_VALUE); + matcher.nextAndAssertEquals((byte) 1); + // NULL == 0 + matcher.nextAndAssertEquals((byte) 0); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "NaN is not a valid number"); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for byte: " + underflow); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for byte: " + overflow); + } + } + + @Test + public void testGetShort() throws Exception { + final String minValue = Short.MIN_VALUE + ""; + final String underflow = String.valueOf((int) Short.MIN_VALUE - 1); + final String maxValue = Short.MAX_VALUE + ""; + final String overflow = String.valueOf((int) Short.MAX_VALUE + 1); + + mockScalarResults(minValue, maxValue, "1.23", null, "NaN", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getShort, ResultSet::getShort); + + matcher.nextAndAssertEquals(Short.MIN_VALUE); + matcher.nextAndAssertEquals(Short.MAX_VALUE); + matcher.nextAndAssertEquals((short) 1); + // NULL == 0 + matcher.nextAndAssertEquals((short) 0); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "NaN is not a valid number"); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for short: " + underflow); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for short: " + overflow); + } + } + + @Test + public void testGetInt() throws Exception { + final String minValue = Integer.MIN_VALUE + ""; + final String underflow = String.valueOf((long) Integer.MIN_VALUE - 1L); + final String maxValue = Integer.MAX_VALUE + ""; + final String overflow = String.valueOf((long) Integer.MAX_VALUE + 1L); + + mockScalarResults(minValue, maxValue, "1.23", null, "NaN", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getInt, ResultSet::getInt); + + matcher.nextAndAssertEquals(Integer.MIN_VALUE); + matcher.nextAndAssertEquals(Integer.MAX_VALUE); + matcher.nextAndAssertEquals(1); + // NULL == 0 + matcher.nextAndAssertEquals(0); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "NaN is not a valid number"); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for int: " + underflow); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for int: " + overflow); + } + } + + @Test + public void testGetLong() throws Exception { + final String minValue = Long.MIN_VALUE + ""; + final String underflow = BigDecimal.valueOf(Long.MIN_VALUE).subtract(BigDecimal.ONE).toString(); + final String maxValue = Long.MAX_VALUE + ""; + final String overflow = BigDecimal.valueOf(Long.MAX_VALUE).add(BigDecimal.ONE).toString(); + + mockScalarResults(minValue, maxValue, "1.23", null, "NaN", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getLong, ResultSet::getLong); + + matcher.nextAndAssertEquals(Long.MIN_VALUE); + matcher.nextAndAssertEquals(Long.MAX_VALUE); + matcher.nextAndAssertEquals(1L); + // NULL == 0 + matcher.nextAndAssertEquals((long) 0); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "NaN is not a valid number"); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for long: " + underflow); + matcher.nextAndAssertError( + JdbcSqlExceptionImpl.class, "Value out of range for long: " + overflow); + } + } + + // TODO(thiagotnunes): Confirm that it is ok to wrap around in under / over flows (like pg) + @Test + public void testGetFloat() throws Exception { + final String minValue = Float.MIN_VALUE + ""; + final String underflow = + BigDecimal.valueOf(Float.MIN_VALUE).subtract(BigDecimal.ONE).toString(); + final String maxValue = (Float.MAX_VALUE - 1) + ""; + final String overflow = BigDecimal.valueOf(Float.MAX_VALUE).add(BigDecimal.ONE).toString(); + + mockScalarResults( + minValue, maxValue, "1.23", null, "NaN", "-Infinity", "+Infinity", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getFloat, ResultSet::getFloat); + + matcher.nextAndAssertEquals(Float.MIN_VALUE); + matcher.nextAndAssertEquals(Float.MAX_VALUE); + matcher.nextAndAssertEquals(1.23F); + // NULL == 0 + matcher.nextAndAssertEquals(0F); + matcher.nextAndAssertEquals(Float.NaN); + matcher.nextAndAssertEquals(Float.NEGATIVE_INFINITY); + matcher.nextAndAssertEquals(Float.POSITIVE_INFINITY); + // Value rolls back to 0 + (underflow value) + matcher.nextAndAssertEquals(-1F); + // Value is capped at Float.MAX_VALUE + matcher.nextAndAssertEquals(Float.MAX_VALUE); + } + } + + @Test + public void testGetDouble() throws Exception { + final String minValue = Double.MIN_VALUE + ""; + final String underflow = + BigDecimal.valueOf(Double.MIN_VALUE).subtract(BigDecimal.ONE).toString(); + final String maxValue = (Double.MAX_VALUE - 1) + ""; + final String overflow = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.ONE).toString(); + + mockScalarResults( + minValue, maxValue, "1.23", null, "NaN", "-Infinity", "+Infinity", underflow, overflow); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getDouble, ResultSet::getDouble); + + matcher.nextAndAssertEquals(Double.MIN_VALUE); + matcher.nextAndAssertEquals(Double.MAX_VALUE); + matcher.nextAndAssertEquals(1.23D); + // NULL == 0 + matcher.nextAndAssertEquals(0D); + matcher.nextAndAssertEquals(Double.NaN); + matcher.nextAndAssertEquals(Double.NEGATIVE_INFINITY); + matcher.nextAndAssertEquals(Double.POSITIVE_INFINITY); + // Value rolls back to 0 + (underflow value) + matcher.nextAndAssertEquals(-1D); + // Value is capped at Double.MAX_VALUE + matcher.nextAndAssertEquals(Double.MAX_VALUE); + } + } + + @Test + public void testGetBigDecimal() throws Exception { + final String maxScale = String.join("", Collections.nCopies(MAX_PG_NUMERIC_SCALE, "1")); + final String maxPrecision = + "0." + String.join("", Collections.nCopies(MAX_PG_NUMERIC_PRECISION, "2")); + + mockScalarResults(maxScale, maxPrecision, "0", "1.23", null, "NaN"); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getBigDecimal, ResultSet::getBigDecimal); + + // Default representation is BigDecimal + matcher.nextAndAssertEquals(new BigDecimal(maxScale)); + matcher.nextAndAssertEquals(new BigDecimal(maxPrecision)); + matcher.nextAndAssertEquals(BigDecimal.ZERO); + matcher.nextAndAssertEquals(new BigDecimal("1.23")); + matcher.nextAndAssertEquals(null); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "NaN is not a valid number"); + } + } + + @Test + public void testGetObject() throws Exception { + final String maxScale = String.join("", Collections.nCopies(MAX_PG_NUMERIC_SCALE, "1")); + final String maxPrecision = + "0." + String.join("", Collections.nCopies(MAX_PG_NUMERIC_PRECISION, "2")); + + mockScalarResults(maxScale, maxPrecision, null, "NaN", "-Infinity", "+Infinity"); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getObject, ResultSet::getObject); + + // Default representation is BigDecimal + matcher.nextAndAssertEquals(new BigDecimal(maxScale)); + matcher.nextAndAssertEquals(new BigDecimal(maxPrecision)); + matcher.nextAndAssertEquals(null); + // Nan is represented as Double + matcher.nextAndAssertEquals(Double.NaN); + // -Infinity is represented as Double + matcher.nextAndAssertEquals(Double.NEGATIVE_INFINITY); + // +Infinity is represented as Double + matcher.nextAndAssertEquals(Double.POSITIVE_INFINITY); + } + } + + @Test + public void testGetDate() throws Exception { + mockScalarResults("1.23", null); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher matcher = + resultSetMatcherFrom(resultSet, ResultSet::getDate, ResultSet::getDate); + + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "Invalid column type to get as date"); + matcher.nextAndAssertError(JdbcSqlExceptionImpl.class, "Invalid column type to get as date"); + } + } + + @Test + public void testGetTime() throws Exception { + mockScalarResults("1.23", null); + + try (Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(QUERY)) { + + final ResultSetMatcher
  • EXPECTED_TABLES = + Arrays.asList( + new Table("albums"), + new Table("concerts"), + new Table("singers"), + // TODO: Enable when views are supported for PostgreSQL dialect databases. + // new Table("singersview", "VIEW"), + new Table("songs"), + new Table("tablewithallcolumntypes"), + new Table("tablewithref")); + + @Test + public void testGetTables() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet rs = + connection.getMetaData().getTables(getDefaultCatalog(), DEFAULT_SCHEMA, null, null)) { + for (Table table : EXPECTED_TABLES) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(table.name, rs.getString("TABLE_NAME")); + assertEquals(table.type, rs.getString("TABLE_TYPE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("TYPE_CAT")); + assertNull(rs.getString("TYPE_SCHEM")); + assertNull(rs.getString("TYPE_NAME")); + assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); + assertNull(rs.getString("REF_GENERATION")); + } + assertFalse(rs.next()); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index ca6adcb0b7a5..550542318599 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -17,35 +17,35 @@ START BATCH DDL; CREATE TABLE Singers ( - SingerId BIGINT PRIMARY KEY, - FirstName VARCHAR(1024), - LastName VARCHAR(1024), - SingerInfo BYTEA, - BirthDate VARCHAR + SingerId BIGINT PRIMARY KEY, + FirstName VARCHAR(1024), + LastName VARCHAR(1024), + SingerInfo BYTEA, + BirthDate VARCHAR ); CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); CREATE TABLE Albums ( - SingerId BIGINT NOT NULL, - AlbumId BIGINT NOT NULL, - AlbumTitle VARCHAR, - MarketingBudget BIGINT, - PRIMARY KEY(SingerId, AlbumId), - FOREIGN KEY(SingerId) REFERENCES Singers(SingerID) + SingerId BIGINT NOT NULL, + AlbumId BIGINT NOT NULL, + AlbumTitle VARCHAR, + MarketingBudget BIGINT, + PRIMARY KEY(SingerId, AlbumId), + FOREIGN KEY(SingerId) REFERENCES Singers(SingerID) ); CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); CREATE TABLE Songs ( - SingerId BIGINT NOT NULL, - AlbumId BIGINT NOT NULL, - TrackId BIGINT NOT NULL, - SongName VARCHAR, - Duration BIGINT, - SongGenre VARCHAR(25), - PRIMARY KEY(SingerId, AlbumId, TrackId), - FOREIGN KEY(AlbumId) REFERENCES Albums(AlbumId) + SingerId BIGINT NOT NULL, + AlbumId BIGINT NOT NULL, + TrackId BIGINT NOT NULL, + SongName VARCHAR, + Duration BIGINT, + SongGenre VARCHAR(25), + PRIMARY KEY(SingerId, AlbumId, TrackId), + FOREIGN KEY(SingerId, AlbumId) REFERENCES Albums(SingerId, AlbumId) ); CREATE UNIQUE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC); @@ -53,21 +53,33 @@ CREATE UNIQUE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, S CREATE INDEX SongsBySongName ON Songs(SongName); CREATE TABLE Concerts ( - VenueId BIGINT NOT NULL, - SingerId BIGINT NOT NULL, - ConcertDate VARCHAR NOT NULL, - BeginTime VARCHAR, - EndTime VARCHAR, - PRIMARY KEY(VenueId, SingerId, ConcertDate) + VenueId BIGINT NOT NULL, + SingerId BIGINT NOT NULL, + ConcertDate VARCHAR NOT NULL, + BeginTime VARCHAR, + EndTime VARCHAR, + PRIMARY KEY(VenueId, SingerId, ConcertDate), + FOREIGN KEY(SingerId) REFERENCES Singers(SingerId) ); CREATE TABLE TableWithAllColumnTypes ( - ColInt64 BIGINT PRIMARY KEY, - ColFloat8 FLOAT8 NOT NULL, - ColBool BOOL NOT NULL, - ColString VARCHAR(100) NOT NULL, - ColBytes BYTEA NOT NULL, - ColNumeric NUMERIC NOT NULL + ColInt64 BIGINT PRIMARY KEY, + ColFloat64 FLOAT8 NOT NULL, + ColBool BOOL NOT NULL, + ColString VARCHAR(100) NOT NULL, + ColStringMax TEXT, + ColBytes BYTEA NOT NULL, + ColTimestamp TIMESTAMP WITH TIME ZONE, + ColNumeric NUMERIC NOT NULL +); + +CREATE TABLE TableWithRef ( + Id BIGINT NOT NULL PRIMARY KEY, + RefFloat FLOAT8 NOT NULL, + RefString VARCHAR(100) NOT NULL, + CONSTRAINT Fk_TableWithRef_TableWithAllColumnTypes + FOREIGN KEY (RefFloat, RefString) + REFERENCES TableWithAllColumnTypes (ColFloat64, ColString) ); RUN BATCH; From b05b329a4ba142f72fd7d4a8e3b8d7d857d793d6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 24 Feb 2022 19:22:54 +0000 Subject: [PATCH 0657/1979] chore(main): release 2.6.0 (#753) :robot: I have created a release *beep* *boop* --- ## [2.6.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.11...v2.6.0) (2022-02-24) ### Features * add support for PostgreSQL dialect ([#739](https://github.com/googleapis/java-spanner-jdbc/issues/739)) ([c6b2e91](https://github.com/googleapis/java-spanner-jdbc/commit/c6b2e916511086c0bfb9b4038acbb9e98ce9430e)) ### Bug Fixes * create specific metadata queries for PG ([#759](https://github.com/googleapis/java-spanner-jdbc/issues/759)) ([92e05d0](https://github.com/googleapis/java-spanner-jdbc/commit/92e05d0a0769c17cac17db354017e5b41bfbf539)) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.20.0 ([#758](https://github.com/googleapis/java-spanner-jdbc/issues/758)) ([6bcf53b](https://github.com/googleapis/java-spanner-jdbc/commit/6bcf53bc7000e95b8587bef281676b39fab1a13c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 17 +++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4c69968212a4..8e4563f5bc6b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [2.6.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.11...v2.6.0) (2022-02-24) + + +### Features + +* add support for PostgreSQL dialect ([#739](https://github.com/googleapis/java-spanner-jdbc/issues/739)) ([f9daa19](https://github.com/googleapis/java-spanner-jdbc/commit/f9daa19453b33252bf61160ff9cde1c37284ca2b)) + + +### Bug Fixes + +* create specific metadata queries for PG ([#759](https://github.com/googleapis/java-spanner-jdbc/issues/759)) ([caffda0](https://github.com/googleapis/java-spanner-jdbc/commit/caffda03e528da6a3c2c17b7058eb5d29f5086f9)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.20.0 ([#758](https://github.com/googleapis/java-spanner-jdbc/issues/758)) ([311d1ca](https://github.com/googleapis/java-spanner-jdbc/commit/311d1cabff7e7e2f5cf2cdcdda90ba536eadfa68)) + ### [2.5.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.10...v2.5.11) (2022-02-11) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 911cf2e5b986..147343700b62 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0google-cloud-spanner-jdbc - 2.5.12-SNAPSHOT + 2.6.0jarGoogle Cloud Spanner JDBChttps://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 86cca42e6cfd..154f015602b5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.12-SNAPSHOT + 2.6.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d8da0dce57bd..1b776e2208d3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.5.11:2.5.12-SNAPSHOT +google-cloud-spanner-jdbc:2.6.0:2.6.0 From dc1753b596a2af0181179b5d7669110e2960828d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 24 Feb 2022 19:33:13 +0000 Subject: [PATCH 0658/1979] chore(main): release 2.6.1-SNAPSHOT (#762) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 147343700b62..fd8e15427743 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0google-cloud-spanner-jdbc - 2.6.0 + 2.6.1-SNAPSHOTjarGoogle Cloud Spanner JDBChttps://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 154f015602b5..e7ec90c24ac6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.0 + 2.6.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1b776e2208d3..e66ddf04af6b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.0:2.6.0 +google-cloud-spanner-jdbc:2.6.0:2.6.1-SNAPSHOT From 90826c8fc7ada709a15e5af15c4964d8a3c6e8d0 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 25 Feb 2022 22:08:29 +0000 Subject: [PATCH 0659/1979] ci: pull request template includes sample format (#1357) (#767) Source-Link: https://github.com/googleapis/synthtool/commit/e122cb03ea37652946651346736d99b9dcc4311f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:387835a1375a0049ec44e02542c844302854c732d8291bdf8e472c0ff70a8f67 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 9786771c434b..9351fdfb9ac8 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:3c950ed12391ebaffd1ee66d0374766a1c50144ebe6a7a0042300b2e6bb5856b + digest: sha256:387835a1375a0049ec44e02542c844302854c732d8291bdf8e472c0ff70a8f67 diff --git a/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md index 52845889399c..c1fcf1103b58 100644 --- a/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md +++ b/java-spanner-jdbc/.github/PULL_REQUEST_TEMPLATE.md @@ -5,3 +5,6 @@ Thank you for opening a Pull Request! Before submitting your PR, there are a few - [ ] Appropriate docs were updated (if necessary) Fixes # ☕️ + +If you write sample code, please follow the [samples format]( +https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md). From 25d0e61afa61911a42b5fdc742cf2c2590386e13 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 1 Mar 2022 03:46:21 +0100 Subject: [PATCH 0660/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.6.0 (#766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.5.11` -> `2.6.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.0/compatibility-slim/2.5.11)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.0/confidence-slim/2.5.11)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.6.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​260-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2511v260-2022-02-24) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.11...v2.6.0) ##### Features - add support for PostgreSQL dialect ([#​739](https://togithub.com/googleapis/java-spanner-jdbc/issues/739)) ([c6b2e91](https://togithub.com/googleapis/java-spanner-jdbc/commit/c6b2e916511086c0bfb9b4038acbb9e98ce9430e)) ##### Bug Fixes - create specific metadata queries for PG ([#​759](https://togithub.com/googleapis/java-spanner-jdbc/issues/759)) ([92e05d0](https://togithub.com/googleapis/java-spanner-jdbc/commit/92e05d0a0769c17cac17db354017e5b41bfbf539)) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.20.0 ([#​758](https://togithub.com/googleapis/java-spanner-jdbc/issues/758)) ([6bcf53b](https://togithub.com/googleapis/java-spanner-jdbc/commit/6bcf53bc7000e95b8587bef281676b39fab1a13c)) ##### [2.5.11](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.10...v2.5.11) (2022-02-11) ##### Dependencies - update actions/github-script action to v6 ([#​745](https://togithub.com/googleapis/java-spanner-jdbc/issues/745)) ([0c0d986](https://togithub.com/googleapis/java-spanner-jdbc/commit/0c0d9860fc1377d7cbfc75e10506502476d761ee)) ##### [2.5.10](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.9...v2.5.10) (2022-02-09) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.18.0 ([#​734](https://togithub.com/googleapis/java-spanner-jdbc/issues/734)) ([7ba3460](https://togithub.com/googleapis/java-spanner-jdbc/commit/7ba346064281e190a0081f15a1cac0fabf6c362a)) ##### [2.5.9](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.5.8...v2.5.9) (2022-02-03) ##### Bug Fixes - **java:** replace excludedGroup with exclude ([#​720](https://togithub.com/googleapis/java-spanner-jdbc/issues/720)) ([02e4731](https://togithub.com/googleapis/java-spanner-jdbc/commit/02e473181dc931d15f6ca0e6e58f2be64115b4c8)) ##### Dependencies - **java:** update actions/github-script action to v5 ([#​1339](https://togithub.com/googleapis/java-spanner-jdbc/issues/1339)) ([#​725](https://togithub.com/googleapis/java-spanner-jdbc/issues/725)) ([e4f4a6e](https://togithub.com/googleapis/java-spanner-jdbc/commit/e4f4a6e50fa1cfea12a64fa4a6c6497f1a5abdd7)) - update actions/github-script action to v5 ([#​724](https://togithub.com/googleapis/java-spanner-jdbc/issues/724)) ([14c11a8](https://togithub.com/googleapis/java-spanner-jdbc/commit/14c11a8bce926cc7eba4e06cbf2f09956b0d9eb2)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.7.0 ([#​728](https://togithub.com/googleapis/java-spanner-jdbc/issues/728)) ([d3611b1](https://togithub.com/googleapis/java-spanner-jdbc/commit/d3611b1584f0c3b84d1e3a036c6b7a05c4cbeab7)) - update opencensus.version to v0.31.0 ([#​727](https://togithub.com/googleapis/java-spanner-jdbc/issues/727)) ([727ac41](https://togithub.com/googleapis/java-spanner-jdbc/commit/727ac416808cd7c3cc349b8433a15732e846c8e9)) ##### [2.5.8](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.7...v2.5.8) (2022-01-07) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.17.4 ([#​709](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/709)) ([6d8e7df](https://www.github.com/googleapis/java-spanner-jdbc/commit/6d8e7df1979feafa1422d813690e617a7e094f6a)) ##### [2.5.7](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.6...v2.5.7) (2022-01-07) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.6.0 ([#​704](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/704)) ([680e9a7](https://www.github.com/googleapis/java-spanner-jdbc/commit/680e9a715bad959843f7c683b2f571d073379de9)) ##### [2.5.6](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.5...v2.5.6) (2021-12-17) ##### Bug Fixes - **java:** add -ntp flag to native image testing command ([#​1299](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/1299)) ([#​688](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/688)) ([f03ebc6](https://www.github.com/googleapis/java-spanner-jdbc/commit/f03ebc6560239a27907620b32bab3bf5e5d85f80)) ##### Dependencies - update OpenCensus API to 0.30.0 ([#​694](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/694)) ([62d51f1](https://www.github.com/googleapis/java-spanner-jdbc/commit/62d51f13b37963e6abdf5c52968b481f5c23c749)) ##### [2.5.5](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.4...v2.5.5) (2021-12-03) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.1 ([#​684](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/684)) ([bf37ebf](https://www.github.com/googleapis/java-spanner-jdbc/commit/bf37ebf8c7880a95ac2f8102ee77d445f125f783)) ##### [2.5.4](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.3...v2.5.4) (2021-11-17) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.16.0 ([#​673](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/673)) ([ca09466](https://www.github.com/googleapis/java-spanner-jdbc/commit/ca094660b26ce851f981303db8ca830761f492d8)) ##### [2.5.3](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.2...v2.5.3) (2021-11-15) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.5.0 ([#​668](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/668)) ([5228db2](https://www.github.com/googleapis/java-spanner-jdbc/commit/5228db2b1c18c61715eae439cd94116da2a0b444)) ##### [2.5.2](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.1...v2.5.2) (2021-11-11) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.2 ([#​664](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/664)) ([b03eec9](https://www.github.com/googleapis/java-spanner-jdbc/commit/b03eec9985eeb050328c30f19c03483fdde8be1e)) ##### [2.5.1](https://www.github.com/googleapis/java-spanner-jdbc/compare/v2.5.0...v2.5.1) (2021-10-27) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.15.1 ([#​652](https://www.togithub.com/googleapis/java-spanner-jdbc/issues/652)) ([872d846](https://www.github.com/googleapis/java-spanner-jdbc/commit/872d846ef29f3b9b8c90de41f990fc7a46d1d610))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 00cb69104f23..4f2c47ba1171 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.5.11 + 2.6.0 From 94bc10ed392483524624fb18e64e0e76fd04c61a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 22:32:19 +0000 Subject: [PATCH 0661/1979] chore: update github actions (#1361) (#768) * chore: update github actions * chore: update Source-Link: https://github.com/googleapis/synthtool/commit/1622741e6877d4b335b137ac7e07f7f32d4e5af7 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:e3746f84955528d0fe24bf2e4df89875d6ce5a036af01b9c326d61a38838523a --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- .../.github/workflows/approve-readme.yaml | 2 +- .../.github/workflows/auto-release.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 20 +++++++++---------- .../.github/workflows/samples.yaml | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 9351fdfb9ac8..53941094cf48 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:387835a1375a0049ec44e02542c844302854c732d8291bdf8e472c0ff70a8f67 + digest: sha256:e3746f84955528d0fe24bf2e4df89875d6ce5a036af01b9c326d61a38838523a diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml index 1bb182327612..f5fc7d5169eb 100644 --- a/java-spanner-jdbc/.github/workflows/approve-readme.yaml +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' steps: - - uses: actions/github-script@v5 + - uses: actions/github-script@v6 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} script: | diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 18e23230d98f..7a106d007edf 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.head_ref, 'release-please') steps: - - uses: actions/github-script@v5 + - uses: actions/github-script@v6 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 6b5e56aaacd1..83ef7f9c2cf3 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -27,8 +27,8 @@ jobs: matrix: java: [8, 11, 17] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: ${{matrix.java}} @@ -39,8 +39,8 @@ jobs: windows: runs-on: windows-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: 8 @@ -54,8 +54,8 @@ jobs: matrix: java: [8, 11, 17] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: ${{matrix.java}} @@ -64,8 +64,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: 11 @@ -76,8 +76,8 @@ jobs: clirr: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index d5d964df15fa..de737e92a8a2 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -20,8 +20,8 @@ jobs: checkstyle: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: java-version: 8 - name: Run checkstyle From d4e71325c2603bfda3a8b1114b2027f8557e51ad Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 2 Mar 2022 19:10:28 +0100 Subject: [PATCH 0662/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.8.0 (#770) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.7.0` -> `2.8.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.8.0/compatibility-slim/2.7.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.8.0/confidence-slim/2.7.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.8.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​280-httpsgithubcomgoogleapisjava-shared-dependenciescomparev270v280-2022-03-02) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.7.0...v2.8.0) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.33.2 ([#​602](https://togithub.com/googleapis/java-shared-dependencies/issues/602)) ([85b132f](https://togithub.com/googleapis/java-shared-dependencies/commit/85b132f5830772646025b6a9fbbb970a941b86b5)) - update dependency com.google.api:api-common to v2.1.4 ([#​605](https://togithub.com/googleapis/java-shared-dependencies/issues/605)) ([ca7d49a](https://togithub.com/googleapis/java-shared-dependencies/commit/ca7d49aee26b6d90abd2afd61c20861d2307fe9c)) - update dependency com.google.auth:google-auth-library-bom to v1.5.3 ([#​614](https://togithub.com/googleapis/java-shared-dependencies/issues/614)) ([e6413f3](https://togithub.com/googleapis/java-shared-dependencies/commit/e6413f3b1be78473ace7085c344eda2d78cdf01a)) - update dependency com.google.cloud:google-cloud-core to v2.5.6 ([#​621](https://togithub.com/googleapis/java-shared-dependencies/issues/621)) ([3d5669f](https://togithub.com/googleapis/java-shared-dependencies/commit/3d5669f215689dd2df71200ffe37d5a9d385cda8)) - update dependency com.google.code.gson:gson to v2.9.0 ([#​611](https://togithub.com/googleapis/java-shared-dependencies/issues/611)) ([f59c28d](https://togithub.com/googleapis/java-shared-dependencies/commit/f59c28d8cd30ada1237f7722135ba148dce6315e)) - update dependency com.google.http-client:google-http-client-bom to v1.41.4 ([#​608](https://togithub.com/googleapis/java-shared-dependencies/issues/608)) ([f9a4f23](https://togithub.com/googleapis/java-shared-dependencies/commit/f9a4f23d3a32148ac59e53eaae6558ccbceca12c)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.33.1 ([#​606](https://togithub.com/googleapis/java-shared-dependencies/issues/606)) ([3882494](https://togithub.com/googleapis/java-shared-dependencies/commit/3882494770d48fcc02ed19088aa06612a8e440eb)) - update dependency com.google.protobuf:protobuf-bom to v3.19.4 ([#​593](https://togithub.com/googleapis/java-shared-dependencies/issues/593)) ([1e155bf](https://togithub.com/googleapis/java-shared-dependencies/commit/1e155bfc957bbb7e25d2e0994cdecaa81843bdc5)) - update dependency io.grpc:grpc-bom to v1.44.1 ([#​613](https://togithub.com/googleapis/java-shared-dependencies/issues/613)) ([3038a2c](https://togithub.com/googleapis/java-shared-dependencies/commit/3038a2c86cd20c91b65f2d7926eeb739147a68db)) - update dependency junit:junit to v4.13.2 ([#​607](https://togithub.com/googleapis/java-shared-dependencies/issues/607)) ([987e617](https://togithub.com/googleapis/java-shared-dependencies/commit/987e61796c7a093e005fe8832cf39275c391b2c1)) - update dependency org.checkerframework:checker-qual to v3.21.3 ([#​596](https://togithub.com/googleapis/java-shared-dependencies/issues/596)) ([ac5083c](https://togithub.com/googleapis/java-shared-dependencies/commit/ac5083cd010924dc128f041c2cdbab20166a6bf0)) - update gax.version to v2.12.2 ([#​592](https://togithub.com/googleapis/java-shared-dependencies/issues/592)) ([713ff8d](https://togithub.com/googleapis/java-shared-dependencies/commit/713ff8dd94f939c417524616bc47c771a3fbe0cf)) - update google.common-protos.version to v2.7.4 ([#​603](https://togithub.com/googleapis/java-shared-dependencies/issues/603)) ([bb9b4c7](https://togithub.com/googleapis/java-shared-dependencies/commit/bb9b4c7e39552cc73b3b9d4c826b26e8cb74459f)) - update google.core.version ([#​599](https://togithub.com/googleapis/java-shared-dependencies/issues/599)) ([327d0df](https://togithub.com/googleapis/java-shared-dependencies/commit/327d0df9b57203c0d4f426de0380770d3d7910d6)) - update iam.version to v1.2.6 ([#​598](https://togithub.com/googleapis/java-shared-dependencies/issues/598)) ([2801439](https://togithub.com/googleapis/java-shared-dependencies/commit/280143964c7c3b93a8d7f67215ba2cc74ffce761))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd8e15427743..2db95dad19f6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.7.0 + 2.8.0 pom import From 73376b2b6373e9fc9896170dd507105d9d07a687 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 18:36:33 +0000 Subject: [PATCH 0663/1979] chore(main): release 2.6.1 (#772) :robot: I have created a release *beep* *boop* --- ### [2.6.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.0...v2.6.1) (2022-03-02) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.8.0 ([#770](https://github.com/googleapis/java-spanner-jdbc/issues/770)) ([d4e7132](https://github.com/googleapis/java-spanner-jdbc/commit/d4e71325c2603bfda3a8b1114b2027f8557e51ad)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8e4563f5bc6b..5a00e3afe73f 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.6.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.0...v2.6.1) (2022-03-02) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.8.0 ([#770](https://github.com/googleapis/java-spanner-jdbc/issues/770)) ([4f32b2d](https://github.com/googleapis/java-spanner-jdbc/commit/4f32b2d6031870c386b37f574d2107f446ed7db7)) + ## [2.6.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.5.11...v2.6.0) (2022-02-24) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2db95dad19f6..dec99ce50923 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.1-SNAPSHOT + 2.6.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e7ec90c24ac6..a2b22301a286 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.1-SNAPSHOT + 2.6.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e66ddf04af6b..9c5aeaea9d6d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.0:2.6.1-SNAPSHOT +google-cloud-spanner-jdbc:2.6.1:2.6.1 From 1dc9e9b14b0bee725155dfe83e32c9faa8740cf0 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 19:52:30 +0000 Subject: [PATCH 0664/1979] chore: fix license header in build.bat (#1363) (#774) * chore: fix license header in build.bat * chore: add disctribution field for setup-java action Source-Link: https://github.com/googleapis/synthtool/commit/4fea5f40a9075f3ba205ede0b453010cf080e194 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:df8d7b2cc0dbc65871e7edd86601901a0612b272fa3f7f0eb590c5c53aa5f92e --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- .../.github/workflows/samples.yaml | 1 + java-spanner-jdbc/.kokoro/build.bat | 30 +++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 53941094cf48..3473042c086e 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:e3746f84955528d0fe24bf2e4df89875d6ce5a036af01b9c326d61a38838523a + digest: sha256:df8d7b2cc0dbc65871e7edd86601901a0612b272fa3f7f0eb590c5c53aa5f92e diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index de737e92a8a2..912ed8b2b027 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -23,6 +23,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: + distribution: zulu java-version: 8 - name: Run checkstyle run: mvn -P lint --quiet --batch-mode checkstyle:check diff --git a/java-spanner-jdbc/.kokoro/build.bat b/java-spanner-jdbc/.kokoro/build.bat index cc602c9eba80..067cf4a4c489 100644 --- a/java-spanner-jdbc/.kokoro/build.bat +++ b/java-spanner-jdbc/.kokoro/build.bat @@ -1,18 +1,18 @@ +:: Copyright 2022 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. :: See documentation in type-shell-output.bat -# Copyright 2022 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. "C:\Program Files\Git\bin\bash.exe" %~dp0build.sh From 3a08fdbf17d14dcf67b2fa4d4e16f611f1b31016 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 8 Mar 2022 02:52:32 +0000 Subject: [PATCH 0665/1979] chore: update java template (#1367) (#776) * chore: update java template * chore: fix tests * chore: fix tests * chore: update project Source-Link: https://github.com/googleapis/synthtool/commit/1155a97fed1c195d10ad406d483bc8ac2507f1d7 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:b0b1c1c89570e229b1026372a2b8989ba31495007055b8d30178b7648503eefa --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/nightly/integration.cfg | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 3473042c086e..426cf83e2ec6 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:df8d7b2cc0dbc65871e7edd86601901a0612b272fa3f7f0eb590c5c53aa5f92e + digest: sha256:b0b1c1c89570e229b1026372a2b8989ba31495007055b8d30178b7648503eefa diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index e51c7b4c6c11..a2907a257b2b 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -13,12 +13,12 @@ env_vars: { # TODO: remove this after we've migrated all tests and scripts env_vars: { key: "GCLOUD_PROJECT" - value: "gcloud-devel" + value: "java-docs-samples-testing" } env_vars: { key: "GOOGLE_CLOUD_PROJECT" - value: "gcloud-devel" + value: "java-docs-samples-testing" } env_vars: { From 245c6dc92121d3c12a8e42c213b8f4ab471189d3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Mar 2022 21:26:16 +0100 Subject: [PATCH 0666/1979] test(deps): update dependency org.mockito:mockito-core to v4.4.0 (#779) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.3.1` -> `4.4.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.4.0/compatibility-slim/4.3.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.4.0/confidence-slim/4.3.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.4.0`](https://togithub.com/mockito/mockito/releases/v4.4.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.3.1...v4.4.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.4.0 - 2022-03-08 - [16 commit(s)](https://togithub.com/mockito/mockito/compare/v4.3.1...v4.4.0) by Andrew Kozel, Brice Dutheil, Jean-Baptiste Mille, Mirko Alicastro, dependabot\[bot] - Bump groovy from 3.0.9 to 3.0.10 [(#​2586)](https://togithub.com/mockito/mockito/pull/2586) - Bump google-java-format from 1.14.0 to 1.15.0 [(#​2585)](https://togithub.com/mockito/mockito/pull/2585) - Bump actions/checkout from 2.4.0 to 3 [(#​2582)](https://togithub.com/mockito/mockito/pull/2582) - Bump shipkit-auto-version from 1.1.19 to 1.1.20 [(#​2580)](https://togithub.com/mockito/mockito/pull/2580) - Bump biz.aQute.bnd.builder from 6.1.0 to 6.2.0 [(#​2579)](https://togithub.com/mockito/mockito/pull/2579) - Bump biz.aQute.bnd.gradle from 6.1.0 to 6.2.0 [(#​2578)](https://togithub.com/mockito/mockito/pull/2578) - Adds a Google Java Format for JDK17 [(#​2572)](https://togithub.com/mockito/mockito/pull/2572) - Clean up JUnit3 references [(#​2570)](https://togithub.com/mockito/mockito/pull/2570) - Bump com.diffplug.spotless from 6.2.2 to 6.3.0 [(#​2567)](https://togithub.com/mockito/mockito/pull/2567) - Bump google-java-format from 1.13.0 to 1.14.0 [(#​2565)](https://togithub.com/mockito/mockito/pull/2565) - Bump versions.bytebuddy from 1.12.7 to 1.12.8 [(#​2564)](https://togithub.com/mockito/mockito/pull/2564) - Bump com.diffplug.spotless from 6.2.1 to 6.2.2 [(#​2562)](https://togithub.com/mockito/mockito/pull/2562) - Bump com.github.ben-manes.versions from 0.41.0 to 0.42.0 [(#​2559)](https://togithub.com/mockito/mockito/pull/2559) - Bump com.diffplug.spotless from 6.2.0 to 6.2.1 [(#​2556)](https://togithub.com/mockito/mockito/pull/2556) - Fixes [#​2548](https://togithub.com/mockito/mockito/issues/2548) : Makes InOrder able to verify static methods [(#​2549)](https://togithub.com/mockito/mockito/pull/2549) - \[PR open] Add feature to verify static methods calls in order [(#​2548)](https://togithub.com/mockito/mockito/issues/2548) - Fixes [#​2201](https://togithub.com/mockito/mockito/issues/2201) : Fixed checking of declared exceptions. [(#​2547)](https://togithub.com/mockito/mockito/pull/2547) - Calling getExceptionTypes() on concrete object that is used as interface doesn't return exception types from interface [(#​2201)](https://togithub.com/mockito/mockito/issues/2201)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dec99ce50923..f688fe1bdee6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.3.1 + 4.4.0 2.2 0.31.0 From 710a1167175618dd53d448dc5641d8c83a650de9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Mar 2022 21:40:16 +0100 Subject: [PATCH 0667/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.3.0 (#777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.2.7` -> `1.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.0/compatibility-slim/1.2.7)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.0/confidence-slim/1.2.7)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.3.0`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​130-httpsgithubcomgoogleapisjava-shared-configcomparev127v130-2022-03-07) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.7...v1.3.0) ##### Features - increase IT timeout from 20 to 60 mins ([#​440](https://togithub.com/googleapis/java-shared-config/issues/440)) ([a4427bc](https://togithub.com/googleapis/java-shared-config/commit/a4427bceebd0624e23f0b02bb24d7ed46ea4b3a6)) ##### Dependencies - update dependency com.google.cloud:native-image-support to v0.12.6 ([#​423](https://togithub.com/googleapis/java-shared-config/issues/423)) ([9a0cb79](https://togithub.com/googleapis/java-shared-config/commit/9a0cb79896d5c97dc3c5648a6740d53eb9ada673)) - update dependency com.puppycrawl.tools:checkstyle to v9.3 ([#​415](https://togithub.com/googleapis/java-shared-config/issues/415)) ([9e2d3fd](https://togithub.com/googleapis/java-shared-config/commit/9e2d3fd8bd42bc210dae5798f7d5dfe950c29f51)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.10 ([#​429](https://togithub.com/googleapis/java-shared-config/issues/429)) ([0355f29](https://togithub.com/googleapis/java-shared-config/commit/0355f2988ebcff19615b72bc65523555e4844523)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.10 ([#​430](https://togithub.com/googleapis/java-shared-config/issues/430)) ([16984d2](https://togithub.com/googleapis/java-shared-config/commit/16984d25a84aa6a8daf2a0925ea57cd0d3f0ee24)) ##### [1.2.7](https://togithub.com/googleapis/java-shared-config/compare/v1.2.6...v1.2.7) (2022-02-04) ##### Dependencies - update dependency com.google.cloud:native-image-support to v0.12.0 ([#​414](https://togithub.com/googleapis/java-shared-config/issues/414)) ([2133cc0](https://togithub.com/googleapis/java-shared-config/commit/2133cc093efd8420e352274f3eab09de819ff796)) ##### [1.2.6](https://togithub.com/googleapis/java-shared-config/compare/v1.2.5...v1.2.6) (2022-01-19) ##### Bug Fixes - library should released as 1.2.6 ([#​408](https://togithub.com/googleapis/java-shared-config/issues/408)) ([4972daa](https://togithub.com/googleapis/java-shared-config/commit/4972daa60467797566c4b043cebd322577b8eb73)) ##### [1.2.5](https://togithub.com/googleapis/java-shared-config/compare/v1.2.4...v1.2.5) (2022-01-11) ##### Bug Fixes - **java:** Enable unit tests in generated libraries for native image testing ([#​394](https://togithub.com/googleapis/java-shared-config/issues/394)) ([a453b9f](https://togithub.com/googleapis/java-shared-config/commit/a453b9f141c7555f2fd5333eb17d223410ab66eb)) ##### [1.2.4](https://www.github.com/googleapis/java-shared-config/compare/v1.2.3...v1.2.4) (2022-01-06) ##### Dependencies - revert dependency com.google.googlejavaformat:google-java-format to v1.7 ([#​391](https://www.togithub.com/googleapis/java-shared-config/issues/391)) ([17077fb](https://www.github.com/googleapis/java-shared-config/commit/17077fb1a58eef7098dc5e1e9b2c78a63c5c11e1)) ##### [1.2.3](https://www.github.com/googleapis/java-shared-config/compare/v1.2.2...v1.2.3) (2022-01-04) ##### Bug Fixes - **java:** add -ntp flag to native image testing command ([#​1299](https://www.togithub.com/googleapis/java-shared-config/issues/1299)) ([#​376](https://www.togithub.com/googleapis/java-shared-config/issues/376)) ([50e7a10](https://www.github.com/googleapis/java-shared-config/commit/50e7a10a8dca0505fd831e3dd929577d2f82b011)) - **java:** Only enable integration tests for native image testing ([#​375](https://www.togithub.com/googleapis/java-shared-config/issues/375)) ([663f421](https://www.github.com/googleapis/java-shared-config/commit/663f421de342afcba24703079f778738045d3ff2)) - **java:** Pass missing integration test flags to native image test commands ([#​1309](https://www.togithub.com/googleapis/java-shared-config/issues/1309)) ([#​383](https://www.togithub.com/googleapis/java-shared-config/issues/383)) ([b17b44e](https://www.github.com/googleapis/java-shared-config/commit/b17b44e37fe44ba61616417189c6b2271f3a4d18)) ##### Dependencies - update auto-value-annotation.version to v1.9 ([#​378](https://www.togithub.com/googleapis/java-shared-config/issues/378)) ([5e1cd0e](https://www.github.com/googleapis/java-shared-config/commit/5e1cd0e39910548ec4eb6639da979c3b66411503)) - update dependency com.google.googlejavaformat:google-java-format to v1.13.0 ([#​361](https://www.togithub.com/googleapis/java-shared-config/issues/361)) ([095d60a](https://www.github.com/googleapis/java-shared-config/commit/095d60a061a574dcf84b9fcf26dff48617a306b1)) - update dependency com.puppycrawl.tools:checkstyle to v9.2 ([#​366](https://www.togithub.com/googleapis/java-shared-config/issues/366)) ([061df67](https://www.github.com/googleapis/java-shared-config/commit/061df676d8b2fef5bbb0ce9661d3c96fcb57e73a)) - update dependency com.puppycrawl.tools:checkstyle to v9.2.1 ([#​382](https://www.togithub.com/googleapis/java-shared-config/issues/382)) ([1a182c5](https://www.github.com/googleapis/java-shared-config/commit/1a182c52e7c5431875296940d68c9bdfcf74be00)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.9 ([#​379](https://www.togithub.com/googleapis/java-shared-config/issues/379)) ([0a2b05f](https://www.github.com/googleapis/java-shared-config/commit/0a2b05ff7f649331efbc4dd540705da10691a2f1)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.8 ([#​372](https://www.togithub.com/googleapis/java-shared-config/issues/372)) ([6fe795e](https://www.github.com/googleapis/java-shared-config/commit/6fe795ede39575656ef1609bf7aac28c1d170976)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.9 ([#​380](https://www.togithub.com/googleapis/java-shared-config/issues/380)) ([f2efad5](https://www.github.com/googleapis/java-shared-config/commit/f2efad585b431fe186c7900a8171a999c689405b)) - update dependency org.junit.vintage:junit-vintage-engine to v5.8.2 ([#​365](https://www.togithub.com/googleapis/java-shared-config/issues/365)) ([604058d](https://www.github.com/googleapis/java-shared-config/commit/604058d52dc962db9a506762926576542687285e)) ##### [1.2.2](https://www.github.com/googleapis/java-shared-config/compare/v1.2.1...v1.2.2) (2021-11-16) ##### Bug Fixes - update dependency com.google.cloud:native-image-support to v0.10.0 ([#​358](https://www.togithub.com/googleapis/java-shared-config/issues/358)) ([0441958](https://www.github.com/googleapis/java-shared-config/commit/044195865a1122d419cadae90fddbf8dc5b4a32d)) ##### [1.2.1](https://www.github.com/googleapis/java-shared-config/compare/v1.2.0...v1.2.1) (2021-11-08) ##### Bug Fixes - Add native image feature to register protobuf reflection in tests ([#​347](https://www.togithub.com/googleapis/java-shared-config/issues/347)) ([88c3e3b](https://www.github.com/googleapis/java-shared-config/commit/88c3e3b0ad1e480e0fdbe9f6fe1f9df183066ee6)) ##### Dependencies - update dependency com.google.auto.service:auto-service-annotations to v1.0.1 ([#​346](https://www.togithub.com/googleapis/java-shared-config/issues/346)) ([9c1f943](https://www.github.com/googleapis/java-shared-config/commit/9c1f94345fb47346fe66f901976c2347b8102bc8)) - update dependency com.google.cloud:native-image-support to v0.9.0 ([#​350](https://www.togithub.com/googleapis/java-shared-config/issues/350)) ([3b496b0](https://www.github.com/googleapis/java-shared-config/commit/3b496b03bd95e59fcd1a3a1eb6cc0dfd330db769)) - update dependency com.puppycrawl.tools:checkstyle to v9.1 ([#​345](https://www.togithub.com/googleapis/java-shared-config/issues/345)) ([f5c03d3](https://www.github.com/googleapis/java-shared-config/commit/f5c03d35684ef4e0bb3178ab6056f231f3f4faf6))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f688fe1bdee6..7ff1444775f9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.7 + 1.3.0 From 3477c2f1c14a5328656ed5e437045ab2587cbeab Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 8 Mar 2022 20:54:24 +0000 Subject: [PATCH 0668/1979] chore(main): release 2.6.2-SNAPSHOT (#773) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ff1444775f9..e4e8552949f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.1 + 2.6.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a2b22301a286..4833104146d7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.1 + 2.6.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9c5aeaea9d6d..0b8f32c2b187 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.1:2.6.1 +google-cloud-spanner-jdbc:2.6.1:2.6.2-SNAPSHOT From ebe1cc9939968f2829ba09641891b2aaf142b947 Mon Sep 17 00:00:00 2001 From: Mike Eltsufin Date: Sat, 12 Mar 2022 00:49:47 -0500 Subject: [PATCH 0669/1979] chore: correct Spanner instance reference for ITs (#781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: correct Spanner instance reference for ITs Fixes #778. * Update pom.xml * Update integration.cfg * Update owlbot.py * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Neenu Shaji Co-authored-by: Owl Bot --- java-spanner-jdbc/owlbot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/java-spanner-jdbc/owlbot.py b/java-spanner-jdbc/owlbot.py index 8ea5787cbc99..5beca6a87af0 100644 --- a/java-spanner-jdbc/owlbot.py +++ b/java-spanner-jdbc/owlbot.py @@ -21,4 +21,5 @@ '.github/release-please.yml', '.github/sync-repo-settings.yaml', '.github/blunderbuss.yml', + '.kokoro/nightly/integration.cfg' ]) From 12ebc9dd5d1fbdc41f11c4f378fec206c1eb7e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 14 Mar 2022 07:51:01 +0100 Subject: [PATCH 0670/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.21.2 (#783) --- java-spanner-jdbc/pom.xml | 2 +- .../cloud/spanner/jdbc/JdbcParameterStoreTest.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e4e8552949f0..bb46e3c425c5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.20.0 + 6.21.2 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 0596d829e514..03aa1dde9f4f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -915,9 +915,16 @@ public void testPostgresDialectConvertPositionalParametersToNamedParameters() { parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") .sqlWithNamedParameters); - assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); + // PostgreSQL allows newlines inside string literals. + assertEquals( + "$1'?it\\'?s \n ?it\\'?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s \n ?it\\'?s'?") + .sqlWithNamedParameters); assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); - assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); + assertEquals( + "$1'''?it\\'?s \n ?it\\'?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s \n ?it\\'?s'?") + .sqlWithNamedParameters); assertEquals( "select 1, $1, 'test?test', \"test?test\", foo.* from `foo` where col1=$2 and col2='test' and col3=$3 and col4='?' and col5=\"?\" and col6='?''?''?'", From 72a5d18441aa5626a292655a2581e76dac4e187a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 07:04:12 +0000 Subject: [PATCH 0671/1979] chore(main): release 2.6.2 (#784) :robot: I have created a release *beep* *boop* --- ### [2.6.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.1...v2.6.2) (2022-03-14) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.21.2 ([#783](https://github.com/googleapis/java-spanner-jdbc/issues/783)) ([12ebc9d](https://github.com/googleapis/java-spanner-jdbc/commit/12ebc9dd5d1fbdc41f11c4f378fec206c1eb7e3f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 5a00e3afe73f..6dc0f652a32f 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.6.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.1...v2.6.2) (2022-03-14) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.21.2 ([#783](https://github.com/googleapis/java-spanner-jdbc/issues/783)) ([1625ad0](https://github.com/googleapis/java-spanner-jdbc/commit/1625ad0e5a827e6cbf68bf6a3bd18eb4b02fc62b)) + ### [2.6.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.0...v2.6.1) (2022-03-02) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bb46e3c425c5..9710347791f3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.2-SNAPSHOT + 2.6.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4833104146d7..f6f1525ab53c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.2-SNAPSHOT + 2.6.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0b8f32c2b187..8dc56bf5ca1a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.1:2.6.2-SNAPSHOT +google-cloud-spanner-jdbc:2.6.2:2.6.2 From 39cfff0ff0b9c0cd597ca9f906dbe67ee0a4d2f2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 07:20:11 +0000 Subject: [PATCH 0672/1979] chore(main): release 2.6.3-SNAPSHOT (#785) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9710347791f3..5e18bc979fc4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.2 + 2.6.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f6f1525ab53c..3e8283910745 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.2 + 2.6.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8dc56bf5ca1a..4d2c0063a0bb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.2:2.6.2 +google-cloud-spanner-jdbc:2.6.2:2.6.3-SNAPSHOT From 132979acb59e6cf454c87b8f7c308b688457c88d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 14 Mar 2022 22:54:22 +0100 Subject: [PATCH 0673/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v25 (#782) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/GoogleCloudPlatform/cloud-opensource-java)) | `24.3.0` -> `25.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.0.0/compatibility-slim/24.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.0.0/confidence-slim/24.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c61300540cb2..12d07505d969 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 24.3.0 + 25.0.0 pom import From f38891a9bdd2fcb3a1b41dd857e36d672dd7d1ce Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 14 Mar 2022 22:58:21 +0100 Subject: [PATCH 0674/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.6.2 (#775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.6.0` -> `2.6.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.2/compatibility-slim/2.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.2/confidence-slim/2.6.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 4f2c47ba1171..cc8ccf7fab4a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.0 + 2.6.2 From 88de3e7e124b65a784125f5d8d5ef7c394a3f753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 21 Mar 2022 08:29:47 +0100 Subject: [PATCH 0675/1979] test: fixed test case that reset entire mock server instead of only requests (#786) --- .../cloud/spanner/jdbc/PgNumericPreparedStatementTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java index fde7c42e03e2..922c2ec0e28d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericPreparedStatementTest.java @@ -86,7 +86,7 @@ public void setUp() throws Exception { "jdbc:cloudspanner://%s/projects/%s/instances/%s/databases/%s?usePlainText=true;dialect=POSTGRESQL", endpoint, PROJECT, INSTANCE, DATABASE); connection = DriverManager.getConnection(url); - mockSpanner.reset(); + mockSpanner.clearRequests(); } @After From e76b3ba554e19093cb92cfc89df99a5a3ea6496c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 29 Mar 2022 19:00:17 +0200 Subject: [PATCH 0676/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.3.2 (#787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.3.0` -> `1.3.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.2/compatibility-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.2/confidence-slim/1.3.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.3.2`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​132-httpsgithubcomgoogleapisjava-shared-configcomparev131v132-2022-03-28) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.3.1...v1.3.2) ### [`v1.3.1`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​131-httpsgithubcomgoogleapisjava-shared-configcomparev130v131-2022-03-25) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.3.0...v1.3.1)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5e18bc979fc4..396d4968ed05 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.3.0 + 1.3.2 From 7e02773d1b3c1347fe24b3eda51de7a098b64f61 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 29 Mar 2022 20:02:23 +0200 Subject: [PATCH 0677/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.9.0 (#789) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.8.0` -> `2.9.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.9.0/compatibility-slim/2.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.9.0/confidence-slim/2.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.9.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​290-httpsgithubcomgoogleapisjava-shared-dependenciescomparev280v290-2022-03-28) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.8.0...v2.9.0) ##### Dependencies - guava 31.1 ([#​635](https://togithub.com/googleapis/java-shared-dependencies/issues/635)) ([0939b06](https://togithub.com/googleapis/java-shared-dependencies/commit/0939b063a79cd4ffafb49cf04861ce577e35efd6)) - update dependency com.fasterxml.jackson:jackson-bom to v2.13.2 ([#​626](https://togithub.com/googleapis/java-shared-dependencies/issues/626)) ([6014663](https://togithub.com/googleapis/java-shared-dependencies/commit/601466339c9631faa88033d1ff1e31582fb67b7b)) - update dependency com.fasterxml.jackson:jackson-bom to v2.13.2.20220324 ([#​636](https://togithub.com/googleapis/java-shared-dependencies/issues/636)) ([6c833fa](https://togithub.com/googleapis/java-shared-dependencies/commit/6c833faa7815147013999bfc2bb6935fd8fe6b34)) - update dependency com.google.api-client:google-api-client-bom to v1.33.4 ([#​642](https://togithub.com/googleapis/java-shared-dependencies/issues/642)) ([57bd912](https://togithub.com/googleapis/java-shared-dependencies/commit/57bd9124ce8981b7b3b5d0c87b7c1e5f935b7150)) - update dependency com.google.api:api-common to v2.1.5 ([#​637](https://togithub.com/googleapis/java-shared-dependencies/issues/637)) ([d3a00fa](https://togithub.com/googleapis/java-shared-dependencies/commit/d3a00fa5ce9908000122d8365fb2f2d0e388494b)) - update dependency com.google.auth:google-auth-library-bom to v1.6.0 ([#​631](https://togithub.com/googleapis/java-shared-dependencies/issues/631)) ([53dc7c2](https://togithub.com/googleapis/java-shared-dependencies/commit/53dc7c2fe255a6c7ca059dd414449bf96780f936)) - update dependency com.google.cloud:google-cloud-core-bom to v2.5.11 ([#​644](https://togithub.com/googleapis/java-shared-dependencies/issues/644)) ([4331dcc](https://togithub.com/googleapis/java-shared-dependencies/commit/4331dcc331e8377fcc57e5404321611186ca22cb)) - update dependency com.google.http-client:google-http-client-bom to v1.41.5 ([#​638](https://togithub.com/googleapis/java-shared-dependencies/issues/638)) ([e007d23](https://togithub.com/googleapis/java-shared-dependencies/commit/e007d2381bd388a1c199fc3f31d0b965f8ae592d)) - update dependency io.grpc:grpc-bom to v1.45.0 ([#​630](https://togithub.com/googleapis/java-shared-dependencies/issues/630)) ([20334e3](https://togithub.com/googleapis/java-shared-dependencies/commit/20334e30d256897cd7ef52c646e5c4549cd7ae69)) - update dependency org.threeten:threetenbp to v1.6.0 ([#​633](https://togithub.com/googleapis/java-shared-dependencies/issues/633)) ([1a2716d](https://togithub.com/googleapis/java-shared-dependencies/commit/1a2716d22e442c5cd6adea9449756b9ac3ddbf8e)) - update gax.version to v2.13.0 ([#​641](https://togithub.com/googleapis/java-shared-dependencies/issues/641)) ([b863746](https://togithub.com/googleapis/java-shared-dependencies/commit/b863746727fadd45c35198f58eb862f47fe14945)) - update google.common-protos.version to v2.8.0 ([#​639](https://togithub.com/googleapis/java-shared-dependencies/issues/639)) ([252afba](https://togithub.com/googleapis/java-shared-dependencies/commit/252afba1df8e4cfdf2574d127097b0978b7778c0)) - update google.core.version to v2.5.10 ([#​628](https://togithub.com/googleapis/java-shared-dependencies/issues/628)) ([fec6f51](https://togithub.com/googleapis/java-shared-dependencies/commit/fec6f5121384a04a389bad6f6477a9a5ce468016)) - update iam.version to v1.2.10 ([#​625](https://togithub.com/googleapis/java-shared-dependencies/issues/625)) ([0d7ca29](https://togithub.com/googleapis/java-shared-dependencies/commit/0d7ca2924bd24abe14883c173156bb4dc5fb90bf))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 396d4968ed05..133e98ff9060 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.8.0 + 2.9.0 pom import From 0d94ac6a954df7098ad51eb08cf061d93a30383d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:16:12 +0000 Subject: [PATCH 0678/1979] chore(main): release 2.6.3 (#791) :robot: I have created a release *beep* *boop* --- ### [2.6.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.2...v2.6.3) (2022-03-29) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.9.0 ([#789](https://github.com/googleapis/java-spanner-jdbc/issues/789)) ([7e02773](https://github.com/googleapis/java-spanner-jdbc/commit/7e02773d1b3c1347fe24b3eda51de7a098b64f61)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6dc0f652a32f..1e7ff52c57f8 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.6.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.2...v2.6.3) (2022-03-29) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.9.0 ([#789](https://github.com/googleapis/java-spanner-jdbc/issues/789)) ([5fd7287](https://github.com/googleapis/java-spanner-jdbc/commit/5fd7287861029acc1179cac8b604e435aa8b0666)) + ### [2.6.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.1...v2.6.2) (2022-03-14) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 133e98ff9060..2b3037f96494 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.3-SNAPSHOT + 2.6.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3e8283910745..104d2c8d22fb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.3-SNAPSHOT + 2.6.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4d2c0063a0bb..41c2970509a6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.2:2.6.3-SNAPSHOT +google-cloud-spanner-jdbc:2.6.3:2.6.3 From 72586c0453ab2b0618abedd9f696af157ff57846 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:26:12 +0000 Subject: [PATCH 0679/1979] chore(main): release 2.6.4-SNAPSHOT (#792) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2b3037f96494..18aaf746ae46 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.3 + 2.6.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 104d2c8d22fb..09af07bbefcd 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.3 + 2.6.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 41c2970509a6..df5c856e8d99 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.3:2.6.3 +google-cloud-spanner-jdbc:2.6.3:2.6.4-SNAPSHOT From 799a1e7ba1e3cc3e73882b30bf762b45cb27899b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 1 Apr 2022 18:42:15 +0200 Subject: [PATCH 0680/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.6.3 (#793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.6.2` -> `2.6.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.3/compatibility-slim/2.6.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.3/confidence-slim/2.6.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.6.3`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​263-httpsgithubcomgoogleapisjava-spanner-jdbccomparev262v263-2022-03-29) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.2...v2.6.3)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cc8ccf7fab4a..210b64677674 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.2 + 2.6.3 From fff7f7928fb6ebc36451aeb85bb87b6cb74a3ed0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 1 Apr 2022 19:08:16 +0200 Subject: [PATCH 0681/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v25.1.0 (#794) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/GoogleCloudPlatform/cloud-opensource-java)) | `25.0.0` -> `25.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.1.0/compatibility-slim/25.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.1.0/confidence-slim/25.0.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 12d07505d969..84bbc2d802ef 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 25.0.0 + 25.1.0 pom import From b2891432a58c127bc5dd651c7225e53900d26769 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 Apr 2022 18:02:27 +0200 Subject: [PATCH 0682/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.3.0 (#790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-shade-plugin](https://maven.apache.org/plugins/) | `3.2.4` -> `3.3.0` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.3.0/compatibility-slim/3.2.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.3.0/confidence-slim/3.2.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 18aaf746ae46..5a717a4a413a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -270,7 +270,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.3.0 From b1d38d3a9a95f179bd32cf6716b983f140d33d39 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 7 Apr 2022 16:06:14 +0000 Subject: [PATCH 0683/1979] chore: Enable Size-Label bot in all googleapis Java repositories (#1381) (#795) * chore: Enable Size-Label bot in all googleapis Java repositories Auto-label T-shirt size indicator should be assigned on every new pull request in all googleapis Java repositories * Remove product Remove product since it is by default true * add license header Co-authored-by: Neenu Shaji Source-Link: https://github.com/googleapis/synthtool/commit/54b2c6ac75370a4a3582431b4a3080f777ba1f11 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 ++- java-spanner-jdbc/.github/auto-label.yaml | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/.github/auto-label.yaml diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 426cf83e2ec6..f60d774937f6 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:b0b1c1c89570e229b1026372a2b8989ba31495007055b8d30178b7648503eefa + digest: sha256:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813 +# created: 2022-04-06T16:30:03.627422514Z diff --git a/java-spanner-jdbc/.github/auto-label.yaml b/java-spanner-jdbc/.github/auto-label.yaml new file mode 100644 index 000000000000..4caef688b745 --- /dev/null +++ b/java-spanner-jdbc/.github/auto-label.yaml @@ -0,0 +1,15 @@ +# Copyright 2021 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. +requestsize: + enabled: true From dd3cd8be643e9323cde1fa18274fb48125dffafe Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 7 Apr 2022 19:20:12 +0200 Subject: [PATCH 0684/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.2.2 (#765) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.2.1` -> `3.2.2` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.2/compatibility-slim/3.2.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.2/confidence-slim/3.2.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a717a4a413a..81127d80c567 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -400,7 +400,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.2.1 + 3.2.2 From ec910d04537fa0ab7dae8d02cc80a69ef4dbc90f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 15 Apr 2022 21:24:30 +0200 Subject: [PATCH 0685/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 (#798) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.9.0` -> `2.10.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.10.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.10.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.10.0/compatibility-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.10.0/confidence-slim/2.9.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.10.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​2100-httpsgithubcomgoogleapisjava-shared-dependenciescomparev290v2100-2022-04-15) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.9.0...v2.10.0) ##### Dependencies - google-cloud-core 2.6.0 ([#​668](https://togithub.com/googleapis/java-shared-dependencies/issues/668)) ([22f4d18](https://togithub.com/googleapis/java-shared-dependencies/commit/22f4d1809cbb9848174b3569ab527e4bef00d443)) - reverting protobuf to 3.19.4 ([#​657](https://togithub.com/googleapis/java-shared-dependencies/issues/657)) ([8501e6d](https://togithub.com/googleapis/java-shared-dependencies/commit/8501e6d842c10d2370bbd5d5246070134336bddd)) - update dependency com.fasterxml.jackson:jackson-bom to v2.13.2.20220328 ([#​646](https://togithub.com/googleapis/java-shared-dependencies/issues/646)) ([7bfd6d7](https://togithub.com/googleapis/java-shared-dependencies/commit/7bfd6d7073859d1955b91b368c6713a72ffa14b6)) - update dependency com.google.api-client:google-api-client-bom to v1.34.0 ([#​662](https://togithub.com/googleapis/java-shared-dependencies/issues/662)) ([1b8e378](https://togithub.com/googleapis/java-shared-dependencies/commit/1b8e378fe0ccf2a28c759868caaf5ba593a95728)) - update dependency com.google.errorprone:error_prone_annotations to v2.12.1 ([#​652](https://togithub.com/googleapis/java-shared-dependencies/issues/652)) ([1cc80ee](https://togithub.com/googleapis/java-shared-dependencies/commit/1cc80ee984ebcad9bc2a95e2f28c0a49fe924b37)) - update dependency com.google.errorprone:error_prone_annotations to v2.13.0 ([#​669](https://togithub.com/googleapis/java-shared-dependencies/issues/669)) ([61b7834](https://togithub.com/googleapis/java-shared-dependencies/commit/61b78341b34a251722be4805a6bdd895cd64836c)) - update dependency com.google.http-client:google-http-client-bom to v1.41.6 ([#​654](https://togithub.com/googleapis/java-shared-dependencies/issues/654)) ([140ef40](https://togithub.com/googleapis/java-shared-dependencies/commit/140ef405bc17ed83f5ce177df59affca14fbe49c)) - update dependency com.google.http-client:google-http-client-bom to v1.41.7 ([#​658](https://togithub.com/googleapis/java-shared-dependencies/issues/658)) ([f6f93e5](https://togithub.com/googleapis/java-shared-dependencies/commit/f6f93e5b9172c9684623c4c148e4a8fe2fae1e94)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.33.2 ([#​655](https://togithub.com/googleapis/java-shared-dependencies/issues/655)) ([20cd9ed](https://togithub.com/googleapis/java-shared-dependencies/commit/20cd9eda112c96836a5ab7485a4247ed2bc0edb8)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.33.3 ([#​663](https://togithub.com/googleapis/java-shared-dependencies/issues/663)) ([f011a46](https://togithub.com/googleapis/java-shared-dependencies/commit/f011a46c551dba16851b4f8c919c40452fc5d5c3)) - update dependency com.google.protobuf:protobuf-bom to v3.20.0 ([#​651](https://togithub.com/googleapis/java-shared-dependencies/issues/651)) ([ad2ff73](https://togithub.com/googleapis/java-shared-dependencies/commit/ad2ff73207dd6493321c77d8eca0022baf13b4ce)) - update dependency io.grpc:grpc-bom to v1.45.1 ([#​647](https://togithub.com/googleapis/java-shared-dependencies/issues/647)) ([38e46fc](https://togithub.com/googleapis/java-shared-dependencies/commit/38e46fc4f03af0a02f30ce4a2fa222c71797ae15)) - update dependency org.checkerframework:checker-qual to v3.21.4 ([#​650](https://togithub.com/googleapis/java-shared-dependencies/issues/650)) ([125e80a](https://togithub.com/googleapis/java-shared-dependencies/commit/125e80ab2c3225a00c03f5ff5de94872ebb94303)) - update gax.version to v2.15.0 ([#​649](https://togithub.com/googleapis/java-shared-dependencies/issues/649)) ([c7f32a6](https://togithub.com/googleapis/java-shared-dependencies/commit/c7f32a68b14520104432282ac9598643700162eb)) - update gax.version to v2.16.0 ([#​664](https://togithub.com/googleapis/java-shared-dependencies/issues/664)) ([caaf941](https://togithub.com/googleapis/java-shared-dependencies/commit/caaf941643af04295f5527a0144587d7bf040862)) - update google.common-protos.version to v2.8.1 ([#​656](https://togithub.com/googleapis/java-shared-dependencies/issues/656)) ([df4a4a2](https://togithub.com/googleapis/java-shared-dependencies/commit/df4a4a2130a3cdb2965ea42962d1ea6a85506ba7)) - update google.common-protos.version to v2.8.2 ([#​659](https://togithub.com/googleapis/java-shared-dependencies/issues/659)) ([b499e2b](https://togithub.com/googleapis/java-shared-dependencies/commit/b499e2bc99506d48d26e35bf6e68c09409ce8b11)) - update google.common-protos.version to v2.8.3 ([#​660](https://togithub.com/googleapis/java-shared-dependencies/issues/660)) ([461081c](https://togithub.com/googleapis/java-shared-dependencies/commit/461081c0cf73057c1f6e07fc573453ad467a60ae)) - update iam.version to v1.3.0 ([#​648](https://togithub.com/googleapis/java-shared-dependencies/issues/648)) ([6670c4f](https://togithub.com/googleapis/java-shared-dependencies/commit/6670c4f61fcf075c543bfd148eea49796e0662ce)) - update iam.version to v1.3.1 ([#​661](https://togithub.com/googleapis/java-shared-dependencies/issues/661)) ([cc8fbe6](https://togithub.com/googleapis/java-shared-dependencies/commit/cc8fbe6eae03341c2ece7d3356febc843a74a812))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 81127d80c567..984315cb860c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.9.0 + 2.10.0 pom import From 6b3f7e0ed4c8aa08db7de2ea83c4813acabaeab5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 Apr 2022 16:38:26 +0200 Subject: [PATCH 0686/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.4.0 (#804) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-javadoc-plugin](https://maven.apache.org/plugins/) | `3.3.2` -> `3.4.0` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.0/compatibility-slim/3.3.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.0/confidence-slim/3.3.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 984315cb860c..dcb0520e1982 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -427,7 +427,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.2 + 3.4.0 html From 02473579c93809e3dcc633fa8d22033d5f825051 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 21 Apr 2022 15:46:20 +0000 Subject: [PATCH 0687/1979] chore(main): release 2.6.4 (#799) :robot: I have created a release *beep* *boop* --- ### [2.6.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.3...v2.6.4) (2022-04-21) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#798](https://github.com/googleapis/java-spanner-jdbc/issues/798)) ([ec910d0](https://github.com/googleapis/java-spanner-jdbc/commit/ec910d04537fa0ab7dae8d02cc80a69ef4dbc90f)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1e7ff52c57f8..11d150942f48 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.6.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.3...v2.6.4) (2022-04-21) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#798](https://github.com/googleapis/java-spanner-jdbc/issues/798)) ([a77024c](https://github.com/googleapis/java-spanner-jdbc/commit/a77024cd0611e69c501d466c6759329f69cb1953)) + ### [2.6.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.2...v2.6.3) (2022-03-29) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dcb0520e1982..c686777e9e81 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.4-SNAPSHOT + 2.6.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 09af07bbefcd..61de8fe9dcbb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.4-SNAPSHOT + 2.6.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index df5c856e8d99..f032d5995fa4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.3:2.6.4-SNAPSHOT +google-cloud-spanner-jdbc:2.6.4:2.6.4 From b1a3f6407d3514c35ac63d7b058ad708dfbbad56 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 21 Apr 2022 16:22:23 +0000 Subject: [PATCH 0688/1979] chore(main): release 2.6.5-SNAPSHOT (#806) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c686777e9e81..786abc4c3eac 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.4 + 2.6.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 61de8fe9dcbb..680607bb4cb9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.4 + 2.6.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f032d5995fa4..7e376e167ea9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.4:2.6.4 +google-cloud-spanner-jdbc:2.6.4:2.6.5-SNAPSHOT From 4f29ad09ebaefccfa49eb9794cb601c88da69a71 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 Apr 2022 19:44:33 +0200 Subject: [PATCH 0689/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.3.3 (#803) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.3.2` -> `1.3.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.3/compatibility-slim/1.3.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.3.3/confidence-slim/1.3.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.3.3`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​133-httpsgithubcomgoogleapisjava-shared-configcomparev132v133-2022-04-19) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.3.2...v1.3.3)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 786abc4c3eac..6d3892150efe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.3.2 + 1.3.3 From e459039df2d2592cde7d716d21f484bb50cb07fd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 Apr 2022 19:54:18 +0200 Subject: [PATCH 0690/1979] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.6.13 (#805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.sonatype.plugins:nexus-staging-maven-plugin](http://www.sonatype.com/) ([source](https://togithub.com/sonatype/nexus-maven-plugins)) | `1.6.11` -> `1.6.13` | [![age](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.13/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.13/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.13/compatibility-slim/1.6.11)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.13/confidence-slim/1.6.11)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    sonatype/nexus-maven-plugins ### [`v1.6.13`](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.12...release-1.6.13) [Compare Source](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.12...release-1.6.13) ### [`v1.6.12`](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.11...release-1.6.12) [Compare Source](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.11...release-1.6.12)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 41ecbd1459fa..96829cbd057f 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.11 + 1.6.13 true From d490d142247a6622e2d8ae7ccdd4757880206d46 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 Apr 2022 21:36:15 +0200 Subject: [PATCH 0691/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.6.4 (#807) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.6.3` -> `2.6.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.4/compatibility-slim/2.6.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.6.4/confidence-slim/2.6.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.6.4`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​264-httpsgithubcomgoogleapisjava-spanner-jdbccomparev263v264-2022-04-21) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.3...v2.6.4)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 210b64677674..b7f0e754d3c9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.3 + 2.6.4 From f3fc252f0b758a02ee1377b7b5998b28caea2460 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 21 Apr 2022 21:44:24 +0200 Subject: [PATCH 0692/1979] test(deps): update dependency org.mockito:mockito-core to v4.5.1 (#802) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.4.0` -> `4.5.1` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.5.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.5.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.5.1/compatibility-slim/4.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.5.1/confidence-slim/4.4.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.5.1`](https://togithub.com/mockito/mockito/releases/v4.5.1) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.5.0...v4.5.1) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.5.1 - 2022-04-21 - [2 commit(s)](https://togithub.com/mockito/mockito/compare/v4.5.0...v4.5.1) by Jeremy Landis, dependabot\[bot] - Fixes [#​2623](https://togithub.com/mockito/mockito/issues/2623): Use zulu distribution and java 11 for release GHA job [(#​2624)](https://togithub.com/mockito/mockito/pull/2624) - Missing errorprone module for 4.5.0 in central as release was done with jdk 8 [(#​2623)](https://togithub.com/mockito/mockito/issues/2623) - Bump kotlinVersion from 1.6.20 to 1.6.21 [(#​2622)](https://togithub.com/mockito/mockito/pull/2622) ### [`v4.5.0`](https://togithub.com/mockito/mockito/releases/v4.5.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.4.0...v4.5.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.5.0 - 2022-04-19 - [15 commit(s)](https://togithub.com/mockito/mockito/compare/v4.4.0...v4.5.0) by Andrei Silviu Dragnea, Rafael Winterhalter, Rick Ossendrijver, dependabot\[bot] - Bump versions.errorprone from 2.13.0 to 2.13.1 [(#​2621)](https://togithub.com/mockito/mockito/pull/2621) - Bump versions.errorprone from 2.12.1 to 2.13.0 [(#​2619)](https://togithub.com/mockito/mockito/pull/2619) - Groovy inline [(#​2618)](https://togithub.com/mockito/mockito/pull/2618) - Bump actions/setup-java from 2 to 3 [(#​2615)](https://togithub.com/mockito/mockito/pull/2615) - Bump versions.bytebuddy from 1.12.8 to 1.12.9 [(#​2614)](https://togithub.com/mockito/mockito/pull/2614) - Support subclass mocks on Graal VM. [(#​2613)](https://togithub.com/mockito/mockito/pull/2613) - Bump com.diffplug.spotless from 6.4.1 to 6.4.2 [(#​2611)](https://togithub.com/mockito/mockito/pull/2611) - Bump kotlinx-coroutines-core from 1.6.0-native-mt to 1.6.1-native-mt [(#​2609)](https://togithub.com/mockito/mockito/pull/2609) - Bump versions.errorprone from 2.10.0 to 2.12.1 [(#​2608)](https://togithub.com/mockito/mockito/pull/2608) - Bump kotlinVersion from 1.6.10 to 1.6.20 [(#​2607)](https://togithub.com/mockito/mockito/pull/2607) - Bump com.diffplug.spotless from 6.4.0 to 6.4.1 [(#​2606)](https://togithub.com/mockito/mockito/pull/2606) - Bump com.diffplug.spotless from 6.3.0 to 6.4.0 [(#​2605)](https://togithub.com/mockito/mockito/pull/2605) - Bump org.eclipse.osgi from 3.17.100 to 3.17.200 [(#​2597)](https://togithub.com/mockito/mockito/pull/2597) - Deprecate ListUtil and Fields classes [(#​2593)](https://togithub.com/mockito/mockito/pull/2593) - mockito-errorprone seems not compatible with ErrorProne 2.11.0 [(#​2554)](https://togithub.com/mockito/mockito/issues/2554) - NullPointerException from Groovy metaclass methods when using mockito-inline (but not mockito-core) [(#​2522)](https://togithub.com/mockito/mockito/issues/2522)
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6d3892150efe..517f18e78a14 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.4.0 + 4.5.1 2.2 0.31.0 From a5aef84b13027ffb17667d18cc63069a3be6f48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 22 Apr 2022 15:52:14 +0200 Subject: [PATCH 0693/1979] build: execute parallel integration tests (#797) Refactors the integration tests to fix a number of problems: 1. Too much state was kept in the abstract base class for all integration tests. This did not work properly with parameterized tests, as some state leaked from one parameter value (dialect) to another. 2. The emulator cannot use an existing instance for testing, as it always starts without any existing instances. This is now fixed by forcing tests to used a separate instance for each test class when running on the emulator, and by fixing creation and database cleanup before/after tests. In addition the integration tests were not executed by Kokoro, as they were skipped in the default test execution. All integration tests are now executed by default. @ansh0l @mpeddada1 The integration tests are (probably) still failing, but that is because the default test instance (projects/gcloud-devel/instances/spanner-testing-east1) is clogged with old (?) test databases that have not been cleaned up. Some test cases therefore currently fail with an error that they cannot create another database, as the max of 100 databases per instance has been reached. I don't have access to the affected instance, so I cannot clean it up. Hopefully one of you has access to it. I've verified that the integration tests work on a different instance. --- java-spanner-jdbc/pom.xml | 30 +-- .../DatabaseMetaData_GetColumns.sql | 2 +- .../DatabaseMetaData_GetCrossReferences.sql | 8 +- .../DatabaseMetaData_GetExportedKeys.sql | 6 +- .../DatabaseMetaData_GetImportedKeys.sql | 6 +- .../DatabaseMetaData_GetIndexInfo.sql | 4 +- .../DatabaseMetaData_GetPrimaryKeys.sql | 4 +- .../DatabaseMetaData_GetSchemas.sql | 2 +- .../postgresql/DatabaseMetaData_GetTables.sql | 2 +- .../spanner/jdbc/ITAbstractJdbcTest.java | 247 ------------------ .../spanner/jdbc/it/ITAbstractJdbcTest.java | 170 ++++++++++++ .../spanner/jdbc/it/ITJdbcConnectTest.java | 16 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 50 ++-- .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 25 +- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 167 ++++++------ .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 4 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 138 ++++------ .../jdbc/it/ITJdbcQueryOptionsTest.java | 32 ++- .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 33 ++- .../it/ITJdbcReadWriteAutocommitTest.java | 29 +- .../spanner/jdbc/it/ITJdbcScriptTest.java | 79 +++--- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 32 ++- .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 28 +- .../jdbc/it/JdbcIntegrationTestEnv.java | 64 +++++ .../ITSqlScriptTest_TestStatementTimeout.sql | 9 +- ...=> ITScriptTest_TestAutocommitDmlMode.sql} | 0 .../jdbc/it/CreateMusicTables_Emulator.sql | 24 +- 27 files changed, 647 insertions(+), 564 deletions(-) delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/JdbcIntegrationTestEnv.java rename java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/{ITScriptTest_TestAutoCommitDmlMode.sql => ITScriptTest_TestAutocommitDmlMode.sql} (100%) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 517f18e78a14..00bd5787b212 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -237,35 +237,9 @@ 2400 + 8 + true - - - default - - integration-test - - - com.google.cloud.spanner.IntegrationTest - - com.google.cloud.spanner.FlakyTest,com.google.cloud.spanner.ParallelIntegrationTest - - - - - parallel-integration-test - - integration-test - - - com.google.cloud.spanner.ParallelIntegrationTest - - com.google.cloud.spanner.FlakyTest,com.google.cloud.spanner.IntegrationTest - - 8 - true - - -
    org.apache.maven.plugins diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index c932e66769e7..2c3c2e4762bf 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -74,7 +74,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A ELSE 'YES' END AS "IS_GENERATEDCOLUMN" FROM INFORMATION_SCHEMA.COLUMNS C -WHERE UPPER(C.TABLE_CATALOG) LIKE ? +WHERE UPPER(COALESCE(C.TABLE_CATALOG, '')) LIKE ? AND UPPER(C.TABLE_SCHEMA) LIKE ? AND UPPER(C.TABLE_NAME) LIKE ? AND UPPER(C.COLUMN_NAME) LIKE ? diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql index d7542ca6e1fd..33b398dae596 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql @@ -20,12 +20,12 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC 3 AS "DELETE_RULE", CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT -WHERE UPPER(PARENT.TABLE_CATALOG) LIKE ? + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +WHERE UPPER(COALESCE(PARENT.TABLE_CATALOG, '')) LIKE ? AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? AND UPPER(PARENT.TABLE_NAME) LIKE ? - AND UPPER(CHILD.TABLE_CATALOG) LIKE ? + AND UPPER(COALESCE(CHILD.TABLE_CATALOG, '')) LIKE ? AND UPPER(CHILD.TABLE_SCHEMA) LIKE ? AND UPPER(CHILD.TABLE_NAME) LIKE ? ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, CHILD.ORDINAL_POSITION diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql index 7c04349e5039..f2a9fb2f6411 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql @@ -23,9 +23,9 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT -WHERE UPPER(PARENT.TABLE_CATALOG) LIKE ? + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +WHERE UPPER(COALESCE(PARENT.TABLE_CATALOG, '')) LIKE ? AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? AND UPPER(PARENT.TABLE_NAME) LIKE ? ORDER BY CHILD.TABLE_CATALOG, CHILD.TABLE_SCHEMA, CHILD.TABLE_NAME, CHILD.ORDINAL_POSITION diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql index 44481deb0c80..c921b1c10eb3 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql @@ -23,9 +23,9 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT -WHERE UPPER(CHILD.TABLE_CATALOG) LIKE ? + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT +WHERE UPPER(COALESCE(CHILD.TABLE_CATALOG, '')) LIKE ? AND UPPER(CHILD.TABLE_SCHEMA) LIKE ? AND UPPER(CHILD.TABLE_NAME) LIKE ? ORDER BY PARENT.TABLE_CATALOG, PARENT.TABLE_SCHEMA, PARENT.TABLE_NAME, CHILD.ORDINAL_POSITION diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetIndexInfo.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetIndexInfo.sql index 7bffd40bcc96..7fc7e4a76384 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetIndexInfo.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetIndexInfo.sql @@ -24,11 +24,11 @@ SELECT IDX.TABLE_CATALOG AS "TABLE_CAT", IDX.TABLE_SCHEMA AS "TABLE_SCHEM", IDX. NULL AS "FILTER_CONDITION" FROM INFORMATION_SCHEMA.INDEXES IDX INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS COL - ON IDX.TABLE_CATALOG=COL.TABLE_CATALOG + ON COALESCE(IDX.TABLE_CATALOG, '')=COALESCE(COL.TABLE_CATALOG, '') AND IDX.TABLE_SCHEMA=COL.TABLE_SCHEMA AND IDX.TABLE_NAME=COL.TABLE_NAME AND IDX.INDEX_NAME=COL.INDEX_NAME -WHERE UPPER(IDX.TABLE_CATALOG) LIKE ? +WHERE UPPER(COALESCE(IDX.TABLE_CATALOG, '')) LIKE ? AND UPPER(IDX.TABLE_SCHEMA) LIKE ? AND UPPER(IDX.TABLE_NAME) LIKE ? AND UPPER(IDX.INDEX_NAME) LIKE ? diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetPrimaryKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetPrimaryKeys.sql index de9214c641fb..d8ad2e8c6867 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetPrimaryKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetPrimaryKeys.sql @@ -18,12 +18,12 @@ SELECT IDX.TABLE_CATALOG AS "TABLE_CAT", IDX.TABLE_SCHEMA AS "TABLE_SCHEM", IDX. COLS.COLUMN_NAME AS "COLUMN_NAME", ORDINAL_POSITION AS "KEY_SEQ", IDX.INDEX_NAME AS "PK_NAME" FROM INFORMATION_SCHEMA.INDEXES IDX INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS COLS - ON IDX.TABLE_CATALOG=COLS.TABLE_CATALOG + ON COALESCE(IDX.TABLE_CATALOG, '')=COALESCE(COLS.TABLE_CATALOG, '') AND IDX.TABLE_SCHEMA=COLS.TABLE_SCHEMA AND IDX.TABLE_NAME=COLS.TABLE_NAME AND IDX.INDEX_NAME=COLS.INDEX_NAME WHERE IDX.INDEX_TYPE='PRIMARY_KEY' - AND UPPER(IDX.TABLE_CATALOG) LIKE ? + AND UPPER(COALESCE(IDX.TABLE_CATALOG, '')) LIKE ? AND UPPER(IDX.TABLE_SCHEMA) LIKE ? AND UPPER(IDX.TABLE_NAME) LIKE ? ORDER BY COLS.ORDINAL_POSITION \ No newline at end of file diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetSchemas.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetSchemas.sql index 5b93ef4337f9..b645f46bffc0 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetSchemas.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetSchemas.sql @@ -16,6 +16,6 @@ SELECT SCHEMA_NAME AS "TABLE_SCHEM", CATALOG_NAME AS "TABLE_CATALOG" FROM INFORMATION_SCHEMA.SCHEMATA -WHERE UPPER(CATALOG_NAME) LIKE ? +WHERE UPPER(COALESCE(CATALOG_NAME, '')) LIKE ? AND UPPER(SCHEMA_NAME) LIKE ? ORDER BY CATALOG_NAME, SCHEMA_NAME diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetTables.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetTables.sql index 911616cffb66..9ddbb05858ec 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetTables.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetTables.sql @@ -19,7 +19,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A NULL AS "REMARKS", NULL AS "TYPE_CAT", NULL AS "TYPE_SCHEM", NULL AS "TYPE_NAME", NULL AS "SELF_REFERENCING_COL_NAME", NULL AS "REF_GENERATION" FROM INFORMATION_SCHEMA.TABLES AS T -WHERE UPPER(TABLE_CATALOG) LIKE ? +WHERE UPPER(COALESCE(TABLE_CATALOG, '')) LIKE ? AND UPPER(TABLE_SCHEMA) LIKE ? AND UPPER(TABLE_NAME) LIKE ? AND ( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java deleted file mode 100644 index 1a8a6adea6ed..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ITAbstractJdbcTest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2019 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.Database; -import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.GceTestEnvConfig; -import com.google.cloud.spanner.IntegrationTestEnv; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; -import com.google.cloud.spanner.connection.ConnectionOptions; -import com.google.cloud.spanner.connection.ITAbstractSpannerTest; -import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; - -/** Base class for all JDBC integration tests. */ -public class ITAbstractJdbcTest { - protected class ITJdbcConnectionProvider - implements com.google.cloud.spanner.connection.AbstractSqlScriptVerifier - .GenericConnectionProvider { - public ITJdbcConnectionProvider() {} - - @Override - public JdbcGenericConnection getConnection() { - try { - return JdbcGenericConnection.of(createConnection(getDialect())); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - } - - @ClassRule - public static IntegrationTestEnv env = - new IntegrationTestEnv() { - @Override - protected void after() { - super.after(); - ConnectionOptions.closeSpanner(); - } - }; - - private static final String DEFAULT_KEY_FILE = null; - private static Database googleStandardSqlDatabase; - private static Database postgresDatabase; - - protected static String getKeyFile() { - return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); - } - - protected static boolean hasValidKeyFile() { - return getKeyFile() != null && Files.exists(Paths.get(getKeyFile())); - } - - protected static IntegrationTestEnv getTestEnv() { - return env; - } - - protected static Database getDatabase() { - return getDatabase(Dialect.GOOGLE_STANDARD_SQL); - } - - protected static Database getDatabase(Dialect dialect) { - if (dialect == Dialect.POSTGRESQL) { - return postgresDatabase; - } - return googleStandardSqlDatabase; - } - - @BeforeClass - public static void setup() { - googleStandardSqlDatabase = env.getTestHelper().createTestDatabase(); - postgresDatabase = env.getTestHelper().createTestDatabase(Dialect.POSTGRESQL, Arrays.asList()); - } - - @AfterClass - public static void teardown() { - ConnectionOptions.closeSpanner(); - } - - /** - * Creates a new default JDBC connection to a test database. Use the method {@link - * ITAbstractJdbcTest#appendConnectionUri(StringBuilder)} to append additional connection options - * to the connection URI. - * - * @return The newly opened JDBC connection. - */ - public CloudSpannerJdbcConnection createConnection(Dialect dialect) throws SQLException { - // Create a connection URL for the generic connection API. - StringBuilder url = - ITAbstractSpannerTest.extractConnectionUrl( - env.getTestHelper().getOptions(), getDatabase(dialect)); - // Prepend it with 'jdbc:' to make it a valid JDBC connection URL. - url.insert(0, "jdbc:"); - if (hasValidKeyFile()) { - url.append(";credentials=").append(getKeyFile()); - } - appendConnectionUri(url); - - return DriverManager.getConnection(url.toString() + ";dialect=" + dialect.name()) - .unwrap(CloudSpannerJdbcConnection.class); - } - - public CloudSpannerJdbcConnection createConnection() throws SQLException { - return createConnection(Dialect.POSTGRESQL); - } - - protected void appendConnectionUri(StringBuilder uri) {} - - /** - * Override this method to instruct the test to create a default test table in the form: - * - *
    -   * CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)
    -   * 
    - * - * Note that the table is not re-created for each test case, but is preserved between test cases. - * It is the responsibility of the test class to either empty the table at the end of each test - * case, or keep track of the state of the test table and execute the test cases in a specific - * order. - * - * @return true if the default test table should be created. - */ - protected boolean doCreateDefaultTestTable() { - return false; - } - - protected boolean doCreateMusicTables() { - return false; - } - - @Before - public void createTestTable() throws SQLException { - if (doCreateDefaultTestTable()) { - try (Connection connection = createConnection(getDialect())) { - connection.setAutoCommit(true); - if (!tableExists(connection, "TEST")) { - connection.setAutoCommit(false); - String createTableDdl; - if (getDialect() == Dialect.GOOGLE_STANDARD_SQL) { - createTableDdl = - "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)"; - } else { - createTableDdl = - "CREATE TABLE TEST (ID BIGINT PRIMARY KEY, NAME VARCHAR(100) NOT NULL)"; - } - connection.createStatement().execute("START BATCH DDL"); - connection.createStatement().execute(createTableDdl); - connection.createStatement().execute("RUN BATCH"); - } - } - } - } - - public Dialect getDialect() { - return Dialect.GOOGLE_STANDARD_SQL; - } - - public String getDefaultCatalog() { - if (getDialect() == Dialect.POSTGRESQL) { - return getDatabase(Dialect.POSTGRESQL).getId().getDatabase(); - } - return ""; - } - - public String getDefaultSchema() { - if (getDialect() == Dialect.POSTGRESQL) { - return "public"; - } - return ""; - } - - @Before - public void createMusicTables() throws SQLException { - if (doCreateMusicTables()) { - try (Connection connection = createConnection(getDialect())) { - connection.setAutoCommit(true); - if (!tableExists(connection, "Singers")) { - String scriptFile = "CreateMusicTables.sql"; - if (getDialect() == Dialect.POSTGRESQL) { - scriptFile = "CreateMusicTables_PG.sql"; - } - if (EmulatorSpannerHelper.isUsingEmulator()) { - scriptFile = "CreateMusicTables_Emulator.sql"; - } - for (String statement : - AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, getClass())) { - connection.createStatement().execute(statement); - } - } - } - } - } - - protected boolean tableExists(Connection connection, String table) throws SQLException { - try (ResultSet rs = - connection.getMetaData().getTables(getDefaultCatalog(), getDefaultSchema(), table, null)) { - if (rs.next()) { - if (rs.getString("TABLE_NAME").equalsIgnoreCase(table)) { - return true; - } - } - } - return false; - } - - protected boolean indexExists(Connection connection, String table, String index) - throws SQLException { - Preconditions.checkArgument(!Strings.isNullOrEmpty(index)); - try (PreparedStatement ps = - connection.prepareStatement( - "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE UPPER(TABLE_NAME)=? AND UPPER(INDEX_NAME)=?")) { - ps.setString(1, table); - ps.setString(2, index); - try (ResultSet rs = ps.executeQuery()) { - return rs.next(); - } - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java new file mode 100644 index 000000000000..b6fb245c7c66 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java @@ -0,0 +1,170 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.GceTestEnvConfig; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier; +import com.google.cloud.spanner.connection.ITAbstractSpannerTest; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +/** Base class for all JDBC integration tests. */ +public class ITAbstractJdbcTest { + protected class ITJdbcConnectionProvider + implements com.google.cloud.spanner.connection.AbstractSqlScriptVerifier + .GenericConnectionProvider { + private final JdbcIntegrationTestEnv env; + private final Database database; + + public ITJdbcConnectionProvider(JdbcIntegrationTestEnv env, Database database) { + this.env = env; + this.database = database; + } + + @Override + public JdbcGenericConnection getConnection() { + try { + return JdbcGenericConnection.of(createConnection(env, database)); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + private static final String DEFAULT_KEY_FILE = null; + + protected static String getKeyFile() { + return System.getProperty(GceTestEnvConfig.GCE_CREDENTIALS_FILE, DEFAULT_KEY_FILE); + } + + protected static boolean hasValidKeyFile() { + return getKeyFile() != null && Files.exists(Paths.get(getKeyFile())); + } + + /** + * Creates a new default JDBC connection to a test database. Use the method {@link + * ITAbstractJdbcTest#appendConnectionUri(StringBuilder)} to append additional connection options + * to the connection URI. + * + * @return The newly opened JDBC connection. + */ + public CloudSpannerJdbcConnection createConnection(JdbcIntegrationTestEnv env, Database database) + throws SQLException { + // Create a connection URL for the generic connection API. + StringBuilder url = + ITAbstractSpannerTest.extractConnectionUrl(env.getTestHelper().getOptions(), database); + // Prepend it with 'jdbc:' to make it a valid JDBC connection URL. + url.insert(0, "jdbc:"); + if (hasValidKeyFile()) { + url.append(";credentials=").append(getKeyFile()); + } + appendConnectionUri(url); + + return DriverManager.getConnection(url.toString()).unwrap(CloudSpannerJdbcConnection.class); + } + + protected void appendConnectionUri(StringBuilder uri) {} + + static Collection getTestTableDdl(Dialect dialect) { + switch (dialect) { + case POSTGRESQL: + return Collections.singleton( + "CREATE TABLE TEST (ID BIGINT PRIMARY KEY, NAME VARCHAR(100) NOT NULL)"); + case GOOGLE_STANDARD_SQL: + default: + return Collections.singleton( + "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)"); + } + } + + static Collection getMusicTablesDdl(Dialect dialect) { + String scriptFile; + switch (dialect) { + case POSTGRESQL: + scriptFile = "CreateMusicTables_PG.sql"; + break; + case GOOGLE_STANDARD_SQL: + default: + scriptFile = "CreateMusicTables.sql"; + } + if (EmulatorSpannerHelper.isUsingEmulator()) { + scriptFile = "CreateMusicTables_Emulator.sql"; + } + return AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, ITAbstractJdbcTest.class) + .stream() + .filter(sql -> !(sql.contains("START BATCH") || sql.contains("RUN BATCH"))) + .collect(Collectors.toList()); + } + + public Dialect getDialect() { + return Dialect.GOOGLE_STANDARD_SQL; + } + + public String getDefaultCatalog(Database database) { + if (getDialect() == Dialect.POSTGRESQL) { + return database.getId().getDatabase(); + } + return ""; + } + + public String getDefaultSchema() { + if (getDialect() == Dialect.POSTGRESQL) { + return "public"; + } + return ""; + } + + protected boolean tableExists(Connection connection, String table) throws SQLException { + try (ResultSet rs = connection.getMetaData().getTables(null, getDefaultSchema(), table, null)) { + if (rs.next()) { + if (rs.getString("TABLE_NAME").equalsIgnoreCase(table)) { + return true; + } + } + } + return false; + } + + protected boolean indexExists(Connection connection, String table, String index) + throws SQLException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(index)); + try (PreparedStatement ps = + connection.prepareStatement( + "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE UPPER(TABLE_NAME)=? AND UPPER(INDEX_NAME)=?")) { + ps.setString(1, table); + ps.setString(2, index); + try (ResultSet rs = ps.executeQuery()) { + return rs.next(); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 90a7ea8a1c87..c81a6333807a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -20,10 +20,11 @@ import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcDataSource; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.io.FileInputStream; @@ -32,8 +33,11 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collections; import java.util.Properties; import javax.sql.DataSource; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -53,13 +57,21 @@ @Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcConnectTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private Database database; + + @Before + public void setup() { + database = env.getOrCreateDatabase(Dialect.GOOGLE_STANDARD_SQL, Collections.emptyList()); + } private String createBaseUrl() { StringBuilder url = new StringBuilder("jdbc:cloudspanner:"); if (EmulatorSpannerHelper.isUsingEmulator()) { url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST")); } - url.append("/").append(getDatabase().getId().getName()); + url.append("/").append(database.getId().getName()); if (EmulatorSpannerHelper.isUsingEmulator()) { url.append(";usePlainText=true"); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index a8a09fab78b9..ea7c236a4b03 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -27,8 +27,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.ParallelIntegrationTest; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -37,7 +37,8 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; -import org.junit.BeforeClass; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -56,15 +57,13 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; private static final String TABLE_WITH_REF = "TableWithRef"; - @BeforeClass - public static void skipOnEmulator() { - assumeFalse( - "foreign keys are not supported on the emulator", EmulatorSpannerHelper.isUsingEmulator()); - } + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private Database database; - @Override - protected boolean doCreateMusicTables() { - return true; + @Before + public void setup() { + database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); } private static final class Column { @@ -171,7 +170,7 @@ private Column( @Test public void testGetColumns() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() @@ -241,7 +240,7 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() @@ -517,7 +516,7 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() @@ -557,7 +556,7 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() @@ -573,7 +572,7 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() @@ -772,7 +771,7 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { assertThat(rs.next(), is(true)); @@ -807,7 +806,8 @@ public void testGetPrimaryKeys() throws SQLException { @Test public void testGetViews() throws SQLException { - try (Connection connection = createConnection()) { + assumeFalse("Emulator does not yet support views", EmulatorSpannerHelper.isUsingEmulator()); + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getTables("", "", null, new String[] {"VIEW"})) { assertTrue(rs.next()); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); @@ -820,7 +820,7 @@ public void testGetViews() throws SQLException { @Test public void testGetSchemas() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getSchemas()) { assertThat(rs.next(), is(true)); assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); @@ -828,9 +828,12 @@ 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))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("SPANNER_SYS"))); - 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))); + } + assertFalse(rs.next()); } } } @@ -861,10 +864,13 @@ private Table(String name, String type) { @Test public void testGetTables() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { for (Table table : EXPECTED_TABLES) { + if (EmulatorSpannerHelper.isUsingEmulator() && table.name.equals("SingersView")) { + continue; + } assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index 1833fbbd014a..5273cb4d3bf5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -16,14 +16,20 @@ package com.google.cloud.spanner.jdbc.it; +import static org.junit.Assume.assumeFalse; + +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -35,6 +41,8 @@ @Category(ParallelIntegrationTest.class) @RunWith(Parameterized.class) public class ITJdbcDdlTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + @Parameters(name = "Dialect = {0}") public static List data() { List params = new ArrayList<>(); @@ -52,6 +60,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -59,8 +77,9 @@ public Dialect getDialect() { @Test public void testSqlScript() throws Exception { - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + JdbcSqlScriptVerifier verifier = + new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider(env, database)); verifier.verifyStatementsInFile( - dialect.executeQueriesFiles.get("TEST_DDL"), ITAbstractJdbcTest.class, false); + dialect.executeQueriesFiles.get("TEST_DDL"), JdbcSqlScriptVerifier.class, false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index e9b682a20b74..af258ba9e3c0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -23,9 +23,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -34,7 +34,9 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; +import org.junit.Before; import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -45,6 +47,8 @@ @Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + private static final String DEFAULT_SCHEMA = "public"; private static final String SINGERS_TABLE = "Singers"; private static final String ALBUMS_TABLE = "Albums"; @@ -60,9 +64,15 @@ public static void skipOnEmulator() { EmulatorSpannerHelper.isUsingEmulator()); } - @Override - protected boolean doCreateMusicTables() { - return true; + private Database database; + + @Before + public void setup() { + database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + } + + public Dialect getDialect() { + return Dialect.POSTGRESQL; } private static final class Column { @@ -130,21 +140,17 @@ private Column( null), new Column("colnumeric", Types.NUMERIC, "numeric", 15, 16383, 10, false, null)); - public Dialect getDialect() { - return Dialect.POSTGRESQL; - } - @Test public void testGetColumns() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getColumns(getDefaultCatalog(), DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { + .getColumns(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { int pos = 1; for (Column col : EXPECTED_COLUMNS) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("TABLE_NAME")); assertEquals(col.name, rs.getString("COLUMN_NAME")); @@ -205,24 +211,24 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() .getCrossReference( - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE, - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -238,18 +244,18 @@ public void testGetCrossReferences() throws SQLException { connection .getMetaData() .getCrossReference( - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE, - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, SONGS_TABLE)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -262,11 +268,11 @@ public void testGetCrossReferences() throws SQLException { (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); @@ -285,18 +291,18 @@ public void testGetCrossReferences() throws SQLException { connection .getMetaData() .getCrossReference( - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE, - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, CONCERTS_TABLE)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -315,19 +321,19 @@ public void testGetCrossReferences() throws SQLException { connection .getMetaData() .getCrossReference( - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_REF)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); @@ -339,11 +345,11 @@ public void testGetCrossReferences() throws SQLException { (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); @@ -361,10 +367,10 @@ public void testGetCrossReferences() throws SQLException { connection .getMetaData() .getCrossReference( - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE, - getDefaultCatalog(), + getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { assertFalse(rs.next()); @@ -439,19 +445,19 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getIndexInfo(getDefaultCatalog(), DEFAULT_SCHEMA, null, false, false)) { + .getIndexInfo(getDefaultCatalog(database), DEFAULT_SCHEMA, null, false, false)) { for (IndexInfo index : EXPECTED_INDICES) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals(index.tableName, rs.getString("TABLE_NAME")); assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); - assertEquals(getDefaultCatalog(), rs.getString("INDEX_QUALIFIER")); + assertEquals(getDefaultCatalog(database), rs.getString("INDEX_QUALIFIER")); // Foreign key index names are automatically generated. if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { @@ -476,17 +482,17 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getExportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, SINGERS_TABLE)) { + .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { assertExportedKeysSingers(rs); } try (ResultSet rs = connection .getMetaData() - .getExportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, ALBUMS_TABLE)) { + .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { assertKeysAlbumsSongs(rs); } } @@ -494,35 +500,35 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getImportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, SINGERS_TABLE)) { + .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { assertImportedKeysSingers(rs); } try (ResultSet rs = connection .getMetaData() - .getImportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, ALBUMS_TABLE)) { + .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { assertImportedKeysAlbums(rs); } try (ResultSet rs = connection .getMetaData() - .getImportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, CONCERTS_TABLE)) { + .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, CONCERTS_TABLE)) { assertImportedKeysConcerts(rs); } try (ResultSet rs = connection .getMetaData() - .getImportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, SONGS_TABLE)) { + .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SONGS_TABLE)) { assertKeysAlbumsSongs(rs); } try (ResultSet rs = connection .getMetaData() - .getImportedKeys(getDefaultCatalog(), DEFAULT_SCHEMA, TABLE_WITH_REF)) { + .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_REF)) { assertImportedKeysTableWithRef(rs); } } @@ -534,11 +540,11 @@ private void assertImportedKeysSingers(ResultSet rs) throws SQLException { private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); @@ -550,11 +556,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); @@ -570,11 +576,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -590,11 +596,11 @@ private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -609,11 +615,11 @@ private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -625,11 +631,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -645,11 +651,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); @@ -661,11 +667,11 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("PKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(), rs.getString("FKTABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); @@ -681,13 +687,13 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getPrimaryKeys(getDefaultCatalog(), DEFAULT_SCHEMA, SINGERS_TABLE)) { + .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals("singers", rs.getString("TABLE_NAME")); assertEquals("singerid", rs.getString("COLUMN_NAME")); @@ -699,16 +705,16 @@ public void testGetPrimaryKeys() throws SQLException { try (ResultSet rs = connection .getMetaData() - .getPrimaryKeys(getDefaultCatalog(), DEFAULT_SCHEMA, ALBUMS_TABLE)) { + .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals("albums", rs.getString("TABLE_NAME")); assertEquals("singerid", rs.getString("COLUMN_NAME")); assertEquals(1, rs.getInt("KEY_SEQ")); assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals("albums", rs.getString("TABLE_NAME")); assertEquals("albumid", rs.getString("COLUMN_NAME")); @@ -723,13 +729,14 @@ public void testGetPrimaryKeys() throws SQLException { @Ignore("Views are not yet supported for PostgreSQL") @Test public void testGetViews() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection .getMetaData() - .getTables(getDefaultCatalog(), DEFAULT_SCHEMA, null, new String[] {"VIEW"})) { + .getTables( + getDefaultCatalog(database), DEFAULT_SCHEMA, null, new String[] {"VIEW"})) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals("SingersView", rs.getString("TABLE_NAME")); assertFalse(rs.next()); @@ -739,18 +746,18 @@ public void testGetViews() throws SQLException { @Test public void testGetSchemas() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getSchemas()) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CATALOG")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); assertEquals("information_schema", rs.getString("TABLE_SCHEM")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CATALOG")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); assertEquals("public", rs.getString("TABLE_SCHEM")); assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CATALOG")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); assertEquals("spanner_sys", rs.getString("TABLE_SCHEM")); assertFalse(rs.next()); @@ -785,12 +792,14 @@ private Table(String name, String type) { @Test public void testGetTables() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = - connection.getMetaData().getTables(getDefaultCatalog(), DEFAULT_SCHEMA, null, null)) { + connection + .getMetaData() + .getTables(getDefaultCatalog(database), DEFAULT_SCHEMA, null, null)) { for (Table table : EXPECTED_TABLES) { assertTrue(rs.next()); - assertEquals(getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); assertEquals(table.name, rs.getString("TABLE_NAME")); assertEquals(table.type, rs.getString("TABLE_TYPE")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index 0c5159686931..57b3e89820a9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -25,8 +25,8 @@ import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.IntegrationTest; import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; @@ -51,7 +51,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -@Category(IntegrationTest.class) +@Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITJdbcPgNumericTest { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 364ce628bbb2..49491332f7d4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -27,10 +27,10 @@ import static org.junit.Assume.assumeFalse; import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JsonType; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; @@ -58,6 +58,8 @@ import java.util.Scanner; import java.util.TimeZone; import java.util.UUID; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -72,6 +74,7 @@ @RunWith(Parameterized.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcPreparedStatementTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); @Parameters(name = "Dialect = {0}") public static List data() { @@ -83,6 +86,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -327,14 +340,9 @@ private int getConcertExpectedParamCount(Dialect dialect) { return 6; } - @Override - protected boolean doCreateMusicTables() { - return true; - } - @Test public void test01_InsertTestData() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { connection.setAutoCommit(false); try (PreparedStatement ps = connection.prepareStatement( @@ -402,7 +410,7 @@ public void test01_InsertTestData() throws SQLException { @Test public void test02_VerifyTestData() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.createStatement().executeQuery("SELECT COUNT(*) FROM Singers")) { assertTrue(rs.next()); @@ -502,7 +510,7 @@ public void test03_Dates() throws SQLException { calendars.add(Calendar.getInstance(TimeZone.getTimeZone("CET"))); calendars.add(Calendar.getInstance(TimeZone.getTimeZone("PST"))); - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { for (Calendar testCalendar : calendars) { int index = 0; for (Date testDate : testDates) { @@ -599,7 +607,7 @@ public void test04_Timestamps() throws SQLException { calendars.add(Calendar.getInstance(TimeZone.getTimeZone("CET"))); calendars.add(Calendar.getInstance(TimeZone.getTimeZone("PST"))); - try (Connection connection = createConnection()) { + try (Connection connection = createConnection(env, database)) { for (Calendar testCalendar : calendars) { for (Timestamp testTimestamp : testTimestamps) { try (PreparedStatement ps = @@ -664,8 +672,8 @@ public void test04_Timestamps() throws SQLException { @Test public void test05_BatchUpdates() throws SQLException { for (boolean autocommit : new boolean[] {true, false}) { - try (Connection con1 = createConnection(getDialect()); - Connection con2 = createConnection(getDialect())) { + try (Connection con1 = createConnection(env, database); + Connection con2 = createConnection(env, database)) { con1.setAutoCommit(autocommit); int[] updateCounts; String[] params = new String[] {"A%", "B%", "C%"}; @@ -723,8 +731,8 @@ public void test05_BatchUpdates() throws SQLException { @Test public void test06_BatchUpdatesWithException() throws SQLException { for (boolean autocommit : new boolean[] {true, false}) { - try (Connection con1 = createConnection(getDialect()); - Connection con2 = createConnection(getDialect())) { + try (Connection con1 = createConnection(env, database); + Connection con2 = createConnection(env, database)) { con1.setAutoCommit(autocommit); String[] params = new String[] {"A%", "B%", "C%", "D%"}; // Statement number three will fail because the value is too long for the column. @@ -756,7 +764,7 @@ public void test06_BatchUpdatesWithException() throws SQLException { @Test public void test07_StatementBatchUpdateWithException() throws SQLException { - try (Connection con = createConnection(getDialect())) { + try (Connection con = createConnection(env, database)) { // The following statements will fail because the value is too long. try (Statement statement = con.createStatement()) { statement.addBatch( @@ -806,21 +814,12 @@ public void test08_InsertAllColumnTypes() throws SQLException { assumeFalse( "TableWithAllColumnTypes type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); - String sql; - if (EmulatorSpannerHelper.isUsingEmulator()) { - sql = - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - } else { - sql = - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - } - try (Connection con = createConnection()) { + String sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { int index = 0; ps.setLong(++index, 1L); @@ -833,9 +832,8 @@ public void test08_InsertAllColumnTypes() throws SQLException { ps.setDate(++index, new Date(System.currentTimeMillis())); ps.setTimestamp(++index, new Timestamp(System.currentTimeMillis())); ps.setBigDecimal(++index, BigDecimal.TEN); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - ps.setObject(++index, "{\"test_value\": \"foo\"}", JsonType.INSTANCE); - } + ps.setObject(++index, "{\"test_value\": \"foo\"}", JsonType.INSTANCE); + ps.setArray(++index, con.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); ps.setArray(++index, con.createArrayOf("FLOAT64", new Double[] {1.1D, 2.2D, 3.3D})); ps.setArray( @@ -864,12 +862,10 @@ public void test08_InsertAllColumnTypes() throws SQLException { ps.setArray( ++index, con.createArrayOf("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN})); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - ps.setArray( - ++index, - con.createArrayOf( - "JSON", new String[] {"{\"test_value\": \"foo\"}", "{}", "[]", null})); - } + ps.setArray( + ++index, + con.createArrayOf( + "JSON", new String[] {"{\"test_value\": \"foo\"}", "{}", "[]", null})); assertEquals(1, ps.executeUpdate()); } try (ResultSet rs = @@ -887,9 +883,8 @@ public void test08_InsertAllColumnTypes() throws SQLException { assertNotNull(rs.getTimestamp(++index)); assertNotNull(rs.getTime(++index)); // Commit timestamp assertEquals(BigDecimal.TEN, rs.getBigDecimal(++index)); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertEquals("{\"test_value\":\"foo\"}", rs.getString(++index)); - } + assertEquals("{\"test_value\":\"foo\"}", rs.getString(++index)); + assertArrayEquals(new Long[] {1L, 2L, 3L}, (Long[]) rs.getArray(++index).getArray()); assertArrayEquals( new Double[] {1.1D, 2.2D, 3.3D}, (Double[]) rs.getArray(++index).getArray()); @@ -908,11 +903,9 @@ public void test08_InsertAllColumnTypes() throws SQLException { assertArrayEquals( new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}, (BigDecimal[]) rs.getArray(++index).getArray()); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertArrayEquals( - new String[] {"{\"test_value\":\"foo\"}", "{}", "[]", null}, - (String[]) rs.getArray(++index).getArray()); - } + assertArrayEquals( + new String[] {"{\"test_value\":\"foo\"}", "{}", "[]", null}, + (String[]) rs.getArray(++index).getArray()); assertFalse(rs.next()); } } @@ -924,7 +917,7 @@ public void test09_MetaData_FromQuery() throws SQLException { "TableWithAllColumnTypes type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("The emulator does not support PLAN mode", isUsingEmulator()); - try (Connection con = createConnection()) { + try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { ResultSetMetaData metadata = ps.getMetaData(); @@ -963,7 +956,7 @@ public void test10_MetaData_FromDML() throws SQLException { assumeFalse( "TableWithAllColumnTypes type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); - try (Connection con = createConnection()) { + try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement( "UPDATE TableWithAllColumnTypes SET ColBool=FALSE WHERE ColInt64=?")) { @@ -978,21 +971,12 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { assumeFalse( "TableWithAllColumnTypes type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); - String sql; - if (EmulatorSpannerHelper.isUsingEmulator()) { - sql = - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - } else { - sql = - "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - } - try (Connection con = createConnection()) { + String sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { int index = 1; ps.setObject(index++, Value.int64(2L)); @@ -1006,9 +990,8 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { ps.setObject( index++, Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99))); ps.setObject(index++, Value.numeric(BigDecimal.TEN)); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - ps.setObject(index++, Value.json("{\"test_value\": \"foo\"}")); - } + ps.setObject(index++, Value.json("{\"test_value\": \"foo\"}")); + ps.setObject(index++, Value.int64Array(new long[] {1L, 2L, 3L})); ps.setObject(index++, Value.float64Array(new double[] {1.1D, 2.2D, 3.3D})); ps.setObject(index++, Value.boolArray(Arrays.asList(Boolean.TRUE, null, Boolean.FALSE))); @@ -1036,11 +1019,9 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { Arrays.asList(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(99999L, 99), null))); ps.setObject( index++, Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN))); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - ps.setObject( - index++, - Value.jsonArray(Arrays.asList("{\"key1\": \"val1\"}", null, "{\"key2\": \"val2\"}"))); - } + ps.setObject( + index++, + Value.jsonArray(Arrays.asList("{\"key1\": \"val1\"}", null, "{\"key2\": \"val2\"}"))); assertEquals(1, ps.executeUpdate()); } try (ResultSet rs = @@ -1066,9 +1047,8 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { rs.getObject(index++, Value.class)); assertNotNull(rs.getObject(index++, Value.class)); // Commit timestamp assertEquals(Value.numeric(BigDecimal.TEN), rs.getObject(index++, Value.class)); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertEquals(Value.json("{\"test_value\":\"foo\"}"), rs.getObject(index++, Value.class)); - } + assertEquals(Value.json("{\"test_value\":\"foo\"}"), rs.getObject(index++, Value.class)); + assertEquals(Value.int64Array(new long[] {1L, 2L, 3L}), rs.getObject(index++, Value.class)); assertEquals( Value.float64Array(new double[] {1.1D, 2.2D, 3.3D}), @@ -1102,11 +1082,9 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { assertEquals( Value.numericArray(Arrays.asList(BigDecimal.ONE, null, BigDecimal.TEN)), rs.getObject(index++, Value.class)); - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertEquals( - Value.jsonArray(Arrays.asList("{\"key1\":\"val1\"}", null, "{\"key2\":\"val2\"}")), - rs.getObject(index++, Value.class)); - } + assertEquals( + Value.jsonArray(Arrays.asList("{\"key1\":\"val1\"}", null, "{\"key2\":\"val2\"}")), + rs.getObject(index++, Value.class)); assertFalse(rs.next()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index b637a299b5bc..4cdd0e9c85c0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -23,11 +23,11 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.connection.SpannerPool; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlException; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.rpc.Code; @@ -36,10 +36,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -62,6 +64,8 @@ @Category(ParallelIntegrationTest.class) @RunWith(Parameterized.class) public class ITJdbcQueryOptionsTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + private String connectionUriSuffix; @Before @@ -91,6 +95,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -109,7 +123,7 @@ private void verifyOptimizerVersion(Connection connection, String expectedVersio @Test public void connectionUrl() throws SQLException { this.connectionUriSuffix = ";optimizerVersion=1"; - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, "1"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { assertThat(rs.next()).isTrue(); @@ -124,7 +138,7 @@ public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { assumeFalse( "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); this.connectionUriSuffix = ";optimizerVersion=9999999"; - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { fail("missing expected exception"); } catch (SQLException e) { @@ -137,7 +151,7 @@ public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { @Test public void setOptimizerVersion() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, ""); connection.createStatement().execute("SET OPTIMIZER_VERSION='1'"); verifyOptimizerVersion(connection, "1"); @@ -151,7 +165,7 @@ public void setOptimizerVersion() throws SQLException { @Test public void setLatestOptimizerVersion() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, ""); connection.createStatement().execute("SET OPTIMIZER_VERSION='LATEST'"); verifyOptimizerVersion(connection, "LATEST"); @@ -167,7 +181,7 @@ public void setLatestOptimizerVersion() throws SQLException { public void setInvalidOptimizerVersion() throws SQLException { assumeFalse( "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { connection.createStatement().execute("SET OPTIMIZER_VERSION='9999999'"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { fail("missing expected exception"); @@ -187,7 +201,7 @@ public void optimizerVersionInQueryHint() throws SQLException { assumeFalse( "optimizer version in query hint is not supported on POSTGRESQL", getDialect() == Dialect.POSTGRESQL); - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, ""); try (ResultSet rs = connection.createStatement().executeQuery("@{optimizer_version=1} SELECT 1")) { @@ -223,7 +237,7 @@ public String getOptimizerStatisticsPackage() { return "latest"; } }); - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { // Environment query options are not visible to the connection. verifyOptimizerVersion(connection, ""); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { @@ -250,7 +264,7 @@ public String getOptimizerStatisticsPackage() { return "latest"; } }); - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { SQLException e = assertThrows( SQLException.class, () -> connection.createStatement().executeQuery("SELECT 1")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 2c1aadd774e3..7e13532c9d6e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -17,20 +17,23 @@ package com.google.cloud.spanner.jdbc.it; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.math.BigInteger; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -38,6 +41,7 @@ import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -51,6 +55,8 @@ public class ITJdbcReadOnlyTest extends ITAbstractJdbcTest { private static final long TEST_ROWS_COUNT = 1000L; + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + @Parameters(name = "Dialect = {0}") public static List data() { List params = new ArrayList<>(); @@ -75,6 +81,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -87,11 +103,13 @@ protected void appendConnectionUri(StringBuilder url) { @Before public void createTestTables() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(getDialect())) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { if (!(tableExists(connection, "NUMBERS") && tableExists(connection, "PRIME_NUMBERS"))) { // create tables - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); - verifier.verifyStatementsInFile(dialect.createTableFile, ITAbstractJdbcTest.class, false); + JdbcSqlScriptVerifier verifier = + new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider(env, database)); + verifier.verifyStatementsInFile( + dialect.createTableFile, JdbcSqlScriptVerifier.class, false); // fill tables with data connection.setAutoCommit(false); @@ -130,14 +148,15 @@ public void closeSpanner() { public void testSqlScript() throws Exception { // Wait 100ms to ensure that staleness tests in the script succeed. Thread.sleep(100L); - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + JdbcSqlScriptVerifier verifier = + new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider(env, database)); verifier.verifyStatementsInFile( - dialect.executeQueriesFiles.get("TEST_READ_ONLY"), ITAbstractJdbcTest.class, false); + dialect.executeQueriesFiles.get("TEST_READ_ONLY"), JdbcSqlScriptVerifier.class, false); } @Test public void testMultipleOpenResultSets() throws InterruptedException, SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { List resultSets = new ArrayList(); ExecutorService exec = Executors.newFixedThreadPool(2); for (String query : dialect.queries) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 29a652019f74..5f81ce23e415 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -19,17 +19,21 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -43,6 +47,7 @@ @RunWith(Parameterized.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcReadWriteAutocommitTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); @Parameters(name = "Dialect = {0}") public static List data() { @@ -60,6 +65,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), getTestTableDdl(getDialect())); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -70,23 +85,19 @@ protected void appendConnectionUri(StringBuilder uri) { uri.append(";autocommit=true"); } - @Override - public boolean doCreateDefaultTestTable() { - return true; - } - @Test public void test01_SqlScript() throws Exception { - JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider()); + JdbcSqlScriptVerifier verifier = + new JdbcSqlScriptVerifier(new ITJdbcConnectionProvider(env, database)); verifier.verifyStatementsInFile( dialect.executeQueriesFiles.get("TEST_READ_WRITE_AUTO_COMMIT"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } @Test public void test02_WriteMutation() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(getDialect())) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { connection.write( Mutation.newInsertBuilder("TEST").set("ID").to(9999L).set("NAME").to("FOO").build()); java.sql.Statement statement = connection.createStatement(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java index b6c29a3fdde3..a6e44358e4a7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java @@ -22,21 +22,25 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -54,6 +58,8 @@ @RunWith(Parameterized.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ITJdbcScriptTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + private static final String CREATE_TABLES_FILE_SQL = "ITSqlScriptTest_CreateTables.sql"; private static final String INSERT_AND_VERIFY_TEST_DATA_SQL = "ITSqlScriptTest_InsertTestData.sql"; @@ -153,14 +159,24 @@ public static List data() { @Parameterized.Parameter(0) public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + /** Create test tables and verify their existence */ @Test public void test01_CreateTables() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.createTableFile, - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @@ -168,11 +184,11 @@ public void test01_CreateTables() throws Exception { /** Insert some test data */ @Test public void test02_InsertTestData() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("INSERT_AND_VERIFY_TEST_DATA"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } catch (SQLException e) { if (env.getTestHelper().isEmulator() @@ -190,11 +206,11 @@ public void test02_InsertTestData() throws Exception { @Test public void test03_TestGetReadTimestamp() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_GET_READ_TIMESTAMP"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @@ -203,11 +219,11 @@ public void test03_TestGetReadTimestamp() throws Exception { public void test04_TestGetCommitTimestamp() throws Exception { // Skipping test as Commit Timestamp not supported in POSTGRES assumeFalse(dialect.dialect == Dialect.POSTGRESQL); - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_GET_COMMIT_TIMESTAMP"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } catch (SQLException e) { if (env.getTestHelper().isEmulator() @@ -224,66 +240,66 @@ public void test04_TestGetCommitTimestamp() throws Exception { @Test public void test05_TestTemporaryTransactions() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_TEMPORARY_TRANSACTIONS"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test06_TestTransactionMode() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_TRANSACTION_MODE"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test07_TestTransactionModeReadOnly() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_TRANSACTION_MODE_READ_ONLY"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test08_TestReadOnlyStaleness() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_READ_ONLY_STALENESS"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test09_TestAutocommitDmlMode() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_AUTOCOMMIT_DML_MODE"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test10_TestAutocommitReadOnly() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_AUTOCOMMIT_READ_ONLY"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @@ -292,14 +308,17 @@ public void test10_TestAutocommitReadOnly() throws Exception { public void test11_TestStatementTimeout() throws Exception { // Statements with set operations in subqueries are not supported assumeFalse(dialect.dialect == Dialect.POSTGRESQL); - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + assumeFalse( + "The emulator is too quick for timeouts to be reliable", + EmulatorSpannerHelper.isUsingEmulator()); + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_STATEMENT_TIMEOUT"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } - try (Connection connection = createConnection(dialect.dialect)) { + try (Connection connection = createConnection(env, database)) { // Create a statement with a query timeout, but do not set a statement timeout on the // connection. SHOW STATEMENT_TIMEOUT should then return a null value. Statement statement = connection.createStatement(); @@ -333,33 +352,33 @@ public void test11_TestStatementTimeout() throws Exception { @Test public void test12_TestSetStatements() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_SET_STATEMENTS"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test13_TestInvalidStatements() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_INVALID_STATEMENTS"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } @Test public void test14_TestQueryOptions() throws Exception { - try (CloudSpannerJdbcConnection connection = createConnection(dialect.dialect)) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_QUERY_OPTIONS"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index 0da6da151708..b7fbc6956c5a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -24,11 +24,12 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Array; import java.sql.Connection; import java.sql.PreparedStatement; @@ -37,7 +38,10 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.Statement; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -49,6 +53,8 @@ @RunWith(Parameterized.class) @Category(ParallelIntegrationTest.class) public class ITJdbcSimpleStatementsTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + @Parameters(name = "Dialect = {0}") public static List data() { List params = new ArrayList<>(); @@ -59,6 +65,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -66,7 +82,7 @@ public Dialect getDialect() { @Test public void testSelect1() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.createStatement().executeQuery("select 1")) { assertThat(rs.next()).isTrue(); assertThat(rs.getInt(1)).isEqualTo(1); @@ -77,7 +93,7 @@ public void testSelect1() throws SQLException { @Test public void testSelect1PreparedStatement() throws SQLException { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (PreparedStatement ps = connection.prepareStatement("select 1")) { try (ResultSet rs = ps.executeQuery()) { assertThat(rs.next()).isTrue(); @@ -98,7 +114,7 @@ public void testPreparedStatement() throws SQLException { dialect.dialect == Dialect.POSTGRESQL); String sql = "select * from (select 1 as number union all select 2 union all select 3) numbers where number=?"; - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (PreparedStatement ps = connection.prepareStatement(sql)) { for (int i = 1; i <= 3; i++) { ps.setInt(1, i); @@ -129,7 +145,7 @@ public void testBatchedDdlStatements() throws SQLException { countTable = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'foo%'"; } // Execute a successful batch of DDL statements. - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (Statement statement = connection.createStatement()) { statement.addBatch(createTableFoo1); statement.addBatch(createTableFoo2); @@ -144,7 +160,7 @@ public void testBatchedDdlStatements() throws SQLException { } } // Execute a batch of DDL statements that contains a statement that will fail. - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { // First create a couple of test records that will cause the index creation to fail. try (Statement statement = connection.createStatement()) { statement.executeUpdate("INSERT INTO FOO1 (ID, NAME) VALUES (1,'TEST')"); @@ -177,7 +193,7 @@ public void testBatchedDdlStatements() throws SQLException { @Test public void testAddBatchWhenAlreadyInBatch() { - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { connection.createStatement().execute("START BATCH DML"); connection.createStatement().addBatch("INSERT INTO Singers (SingerId) VALUES (-1)"); fail("missing expected exception"); @@ -207,7 +223,7 @@ public void testSelectArrayOfStructs() throws SQLException { + " SELECT STRUCT(point)\n" + " FROM points)\n" + " AS coordinates"; - try (Connection connection = createConnection(getDialect())) { + try (Connection connection = createConnection(env, database)) { try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { assertTrue(resultSet.next()); assertEquals(resultSet.getMetaData().getColumnCount(), 1); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 4ae00347b1ba..7c8c7aeb53f9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -16,26 +16,34 @@ package com.google.cloud.spanner.jdbc.it; +import static org.junit.Assume.assumeFalse; + +import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; -import com.google.cloud.spanner.jdbc.ITAbstractJdbcTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITJdbcSqlMusicScriptTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + @Parameters(name = "Dialect = {0}") public static List data() { List params = new ArrayList<>(); @@ -51,6 +59,16 @@ public static List data() { @Parameter public DialectTestParameter dialect; + private Database database; + + @Before + public void setup() { + assumeFalse( + "Emulator does not support PostgreSQL", + dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); + database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); + } + @Override public Dialect getDialect() { return dialect.dialect; @@ -59,11 +77,11 @@ public Dialect getDialect() { @Test public void testRunScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(); - try (CloudSpannerJdbcConnection connection = createConnection(getDialect())) { + try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_SQL_MUSIC_SCRIPT"), - ITAbstractJdbcTest.class, + JdbcSqlScriptVerifier.class, false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/JdbcIntegrationTestEnv.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/JdbcIntegrationTestEnv.java new file mode 100644 index 000000000000..475716b1c162 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/JdbcIntegrationTestEnv.java @@ -0,0 +1,64 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import java.util.HashMap; +import java.util.Map; + +public class JdbcIntegrationTestEnv extends IntegrationTestEnv { + /** + * The test database(s) that have been created for this test run. The cleanup of these databases + * is handled by {@link com.google.cloud.spanner.testing.RemoteSpannerHelper}. + */ + private final Map databases = new HashMap<>(); + + Database getOrCreateDatabase(Dialect dialect, Iterable ddlStatements) { + if (databases.containsKey(dialect)) { + return databases.get(dialect); + } + Database database = getTestHelper().createTestDatabase(dialect, ddlStatements); + databases.put(dialect, database); + + return database; + } + + @Override + protected void initializeConfig() + throws ClassNotFoundException, InstantiationException, IllegalAccessException { + if (EmulatorSpannerHelper.isUsingEmulator()) { + // Make sure that we use an owned instance on the emulator. + System.setProperty(TEST_INSTANCE_PROPERTY, ""); + } + super.initializeConfig(); + } + + @Override + protected void after() { + super.after(); + try { + ConnectionOptions.closeSpanner(); + } catch (SpannerException e) { + // ignore + } + } +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql index 9a9894fafa96..fc76bcbd0813 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITSqlScriptTest_TestStatementTimeout.sql @@ -70,7 +70,7 @@ SET STATEMENT_TIMEOUT='1ns'; SHOW VARIABLE STATEMENT_TIMEOUT; -- Do a somewhat complex query that should now timeout -@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +@EXPECT EXCEPTION DEADLINE_EXCEEDED SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED FROM ( SELECT * @@ -97,7 +97,7 @@ FROM ( ; -- Try to execute an update that should also timeout -@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +@EXPECT EXCEPTION DEADLINE_EXCEEDED UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1 OR LastName IN ( @@ -176,7 +176,7 @@ SET STATEMENT_TIMEOUT='1ns'; SHOW VARIABLE STATEMENT_TIMEOUT; -- Do a somewhat complex query that should now timeout -@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +@EXPECT EXCEPTION DEADLINE_EXCEEDED SELECT COUNT(*) AS ACTUAL, 0 AS EXPECTED FROM ( SELECT * @@ -202,11 +202,10 @@ FROM ( ) RES ; -- We need to rollback the transaction as it is no longer usable. -@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' ROLLBACK; -- Try to execute an update that should also timeout -@EXPECT EXCEPTION DEADLINE_EXCEEDED 'DEADLINE_EXCEEDED: Statement execution timeout occurred' +@EXPECT EXCEPTION DEADLINE_EXCEEDED UPDATE Singers SET LastName='Some Other Last Name' /* It used to be 'Last 1' */ WHERE SingerId=1 OR LastName IN ( diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutoCommitDmlMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql similarity index 100% rename from java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutoCommitDmlMode.sql rename to java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql index d1e73bba2009..aaba70c19884 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql @@ -63,17 +63,18 @@ CREATE TABLE Concerts ( ) PRIMARY KEY(VenueId, SingerId, ConcertDate); CREATE TABLE TableWithAllColumnTypes ( - ColInt64 INT64 NOT NULL, - ColFloat64 FLOAT64 NOT NULL, - ColBool BOOL NOT NULL, - ColString STRING(100) NOT NULL, - ColStringMax STRING(MAX) NOT NULL, - ColBytes BYTES(100) NOT NULL, - ColBytesMax BYTES(MAX) NOT NULL, - ColDate DATE NOT NULL, - ColTimestamp TIMESTAMP NOT NULL, - ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), - ColNumeric NUMERIC NOT NULL, + ColInt64 INT64 NOT NULL, + ColFloat64 FLOAT64 NOT NULL, + ColBool BOOL NOT NULL, + ColString STRING(100) NOT NULL, + ColStringMax STRING(MAX) NOT NULL, + ColBytes BYTES(100) NOT NULL, + ColBytesMax BYTES(MAX) NOT NULL, + ColDate DATE NOT NULL, + ColTimestamp TIMESTAMP NOT NULL, + ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), + ColNumeric NUMERIC NOT NULL, + ColJson JSON NOT NULL, ColInt64Array ARRAY, ColFloat64Array ARRAY, @@ -85,6 +86,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColDateArray ARRAY, ColTimestampArray ARRAY, ColNumericArray ARRAY, + ColJsonArray ARRAY, ColComputed STRING(MAX) AS (CONCAT(COALESCE(ColString, ''), ' ', COALESCE(ColStringMax, ''))) STORED, ) PRIMARY KEY (ColInt64) From c0225bc62d67f2bd895008a73a9bcc234665dcea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 25 Apr 2022 12:21:57 +0200 Subject: [PATCH 0694/1979] test: add pg_catalog as an expected schema (#821) Adds `pg_catalog` as an expected schema to the JDBC metadata tests. Fixes #810 --- .../cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index af258ba9e3c0..ca13ea2c2b14 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -752,6 +752,10 @@ public void testGetSchemas() throws SQLException { assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); assertEquals("information_schema", rs.getString("TABLE_SCHEM")); + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); + assertEquals("pg_catalog", rs.getString("TABLE_SCHEM")); + assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); assertEquals("public", rs.getString("TABLE_SCHEM")); From 798e67c811fe58b1b7315659a14a9ea4e5c290d9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 27 Apr 2022 17:58:11 +0200 Subject: [PATCH 0695/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v25.2.0 (#835) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/GoogleCloudPlatform/cloud-opensource-java)) | `25.1.0` -> `25.2.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.2.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.2.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.2.0/compatibility-slim/25.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.2.0/confidence-slim/25.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 84bbc2d802ef..fdd2b2329e6c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 25.1.0 + 25.2.0 pom import From d0831222a69824627657b9eb04ab0af345df585c Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 29 Apr 2022 13:13:21 +0530 Subject: [PATCH 0696/1979] chore: reduce fork count to 4 (#864) Reducing fork count to 4 to check if that helps reduce the flakes. --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 00bd5787b212..6ce1efee3ee4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -237,7 +237,7 @@ 2400 - 8 + 4 true
    From 4041fb44e0d3ee86da6b3903fddf50f5b8823086 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 29 Apr 2022 22:14:37 +0200 Subject: [PATCH 0697/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.4.0 (#863) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.3.3` -> `1.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.4.0/compatibility-slim/1.3.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.4.0/confidence-slim/1.3.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.4.0`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​140-httpsgithubcomgoogleapisjava-shared-configcomparev133v140-2022-04-28) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.3.3...v1.4.0) ##### Features - **java:** remove native image module ([#​471](https://togithub.com/googleapis/java-shared-config/issues/471)) ([7fcba01](https://togithub.com/googleapis/java-shared-config/commit/7fcba016b3138d7beaa4e962853f9bc80f59438c)) ##### [1.3.3](https://togithub.com/googleapis/java-shared-config/compare/v1.3.2...v1.3.3) (2022-04-19) ##### Bug Fixes - **java:** remove protobuf feature from native profile ([#​461](https://togithub.com/googleapis/java-shared-config/issues/461)) ([ffd07cb](https://togithub.com/googleapis/java-shared-config/commit/ffd07cb18ee7d45d4daee1d9ea6f6d321fdca874)) ##### Dependencies - update dependency com.google.cloud:native-image-support to v0.12.11 ([#​459](https://togithub.com/googleapis/java-shared-config/issues/459)) ([d20008d](https://togithub.com/googleapis/java-shared-config/commit/d20008df15209708fdf9d06828b567778190f4d0)) - update dependency com.google.cloud:native-image-support to v0.13.1 ([#​465](https://togithub.com/googleapis/java-shared-config/issues/465)) ([b202064](https://togithub.com/googleapis/java-shared-config/commit/b2020648816feb4740ad70acedfed470d7da5bcf)) ##### [1.3.2](https://togithub.com/googleapis/java-shared-config/compare/v1.3.1...v1.3.2) (2022-03-28) ##### Dependencies - revert google-java-format to 1.7 ([#​453](https://togithub.com/googleapis/java-shared-config/issues/453)) ([cbc777f](https://togithub.com/googleapis/java-shared-config/commit/cbc777f3e9ab75edb6fa2e0268a7446ae4111725)) ##### [1.3.1](https://togithub.com/googleapis/java-shared-config/compare/v1.3.0...v1.3.1) (2022-03-25) ##### Dependencies - update dependency com.google.cloud:native-image-support to v0.12.10 ([#​443](https://togithub.com/googleapis/java-shared-config/issues/443)) ([5b39d5e](https://togithub.com/googleapis/java-shared-config/commit/5b39d5ee15121f052226ff873b6ab101e9c71de5)) - update dependency com.google.googlejavaformat:google-java-format to v1.15.0 ([#​426](https://togithub.com/googleapis/java-shared-config/issues/426)) ([4c3c4b6](https://togithub.com/googleapis/java-shared-config/commit/4c3c4b66129632181e6bc363a0ecccf4f5aac914)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.11 ([#​448](https://togithub.com/googleapis/java-shared-config/issues/448)) ([f7f518e](https://togithub.com/googleapis/java-shared-config/commit/f7f518e87d1d9feb9ac54d7c099f97d8751ee3da)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.11 ([#​449](https://togithub.com/googleapis/java-shared-config/issues/449)) ([3e1c0b5](https://togithub.com/googleapis/java-shared-config/commit/3e1c0b5a1d2f4a0db88c06a0d683ed90cbc745e2))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6ce1efee3ee4..14363e952829 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.3.3 + 1.4.0 From 138a58e0afa880a6986b596566254f124daf47c1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 6 May 2022 00:28:11 +0200 Subject: [PATCH 0698/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.3.0 (#861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) ([source](https://togithub.com/apache/maven-project-info-reports-plugin)) | `3.2.2` -> `3.3.0` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.3.0/compatibility-slim/3.2.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.3.0/confidence-slim/3.2.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14363e952829..8e47faac6416 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -374,7 +374,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.2.2 + 3.3.0 From 5d47d780806b15525738850d7a554889125de606 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 14 May 2022 19:18:11 +0200 Subject: [PATCH 0699/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v25.3.0 (#872) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/GoogleCloudPlatform/cloud-opensource-java)) | `25.2.0` -> `25.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.3.0/compatibility-slim/25.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/25.3.0/confidence-slim/25.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fdd2b2329e6c..501c08391f53 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 25.2.0 + 25.3.0 pom import From c24eb4b46aaded9947a9850ec564b7fc93a5fdeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 14 May 2022 20:46:03 +0200 Subject: [PATCH 0700/1979] fix: executeBatch did not respect statement timeout (#871) The Statement#executeBatch() method did not respect the statement timeout that had been set on a statement. This meant that a batch like the following would always use the default timeout that is set in the Gapic generated client, and ignore the timeout set in Statement#setTimeout(int): statement.setTimeout(120); statement.addBatch("insert into foo (id) values (1)"); statement.executeBatch(); // This ignored the statement timeout Fixes #870 --- java-spanner-jdbc/pom.xml | 5 +- .../spanner/jdbc/AbstractJdbcStatement.java | 6 +- .../cloud/spanner/jdbc/JdbcStatement.java | 2 + .../jdbc/JdbcStatementTimeoutTest.java | 121 ++++++++++++++++++ 4 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8e47faac6416..ca292797766a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -220,7 +220,10 @@ org.apache.maven.plugins maven-surefire-plugin - com.google.cloud.spanner.IntegrationTest + + com.google.cloud.spanner.jdbc.it.** + com.google.cloud.spanner.jdbc.JdbcStatementTimeoutTest + sponge_log diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 6b5848a4aabc..2ee68afb2f42 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -104,7 +104,7 @@ private TimeUnit getAppropriateTimeUnit() { * specified for a JDBC statement, and then after executing the JDBC statement setting the timeout * on the Spanner {@link Connection} again. */ - private static class StatementTimeout { + static class StatementTimeout { private final long timeout; private final TimeUnit unit; @@ -123,7 +123,7 @@ private StatementTimeout(long timeout, TimeUnit unit) { * {@link Statement} and returns the original timeout of the Spanner {@link Connection} so it can * be reset after the execution of a statement */ - private StatementTimeout setTemporaryStatementTimeout() throws SQLException { + StatementTimeout setTemporaryStatementTimeout() throws SQLException { StatementTimeout originalTimeout = null; if (getQueryTimeout() > 0) { if (connection.getSpannerConnection().hasStatementTimeout()) { @@ -140,7 +140,7 @@ private StatementTimeout setTemporaryStatementTimeout() throws SQLException { * Resets the statement timeout of the Spanner {@link Connection} after a JDBC {@link Statement} * has been executed. */ - private void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLException { + void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLException { if (getQueryTimeout() > 0) { if (originalTimeout == null) { connection.getSpannerConnection().clearStatementTimeout(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 5c4bbed9e656..f37eb21a80d3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -265,6 +265,7 @@ public long[] executeLargeBatch() throws SQLException { private long[] executeBatch(boolean large) throws SQLException { checkClosed(); checkConnectionHasNoActiveBatch(); + StatementTimeout originalTimeout = setTemporaryStatementTimeout(); try { switch (this.currentBatchType) { case DML: @@ -310,6 +311,7 @@ private long[] executeBatch(boolean large) throws SQLException { String.format("Unknown batch type: %s", this.currentBatchType.name())); } } finally { + resetStatementTimeout(originalTimeout); batchedStatements.clear(); this.currentBatchType = BatchType.NONE; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java new file mode 100644 index 000000000000..a9d1840068f0 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2022 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.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; + +import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlTimeoutException; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests setting a statement timeout. This test is by default not included in unit test runs, as the + * minimum timeout value in JDBC is 1 second, which again makes this test relatively slow. + */ +@RunWith(JUnit4.class) +public class JdbcStatementTimeoutTest extends AbstractMockServerTest { + + @Test + public void testExecuteTimeout() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + // First verify that execute does not time out by default. + assertFalse(statement.execute(INSERT_STATEMENT.getSql())); + int result = statement.getUpdateCount(); + assertEquals(1, result); + + // Simulate that executeSql takes 2 seconds and set a statement timeout of 1 second. + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); + statement.setQueryTimeout(1); + assertThrows( + JdbcSqlTimeoutException.class, () -> statement.execute(INSERT_STATEMENT.getSql())); + } + } + } + + @Test + public void testExecuteQueryTimeout() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + // First verify that executeQuery does not time out by default. + try (ResultSet resultSet = statement.executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + + // Simulate that executeStreamingSql takes 2 seconds and set a statement timeout of 1 + // second. + mockSpanner.setExecuteStreamingSqlExecutionTime( + SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); + statement.setQueryTimeout(1); + assertThrows( + JdbcSqlTimeoutException.class, + () -> statement.executeQuery(SELECT_RANDOM_STATEMENT.getSql())); + } + } + } + + @Test + public void testExecuteUpdateTimeout() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + // First verify that executeUpdate does not time out by default. + assertEquals(1, statement.executeUpdate(INSERT_STATEMENT.getSql())); + + // Simulate that executeSql takes 2 seconds and set a statement timeout of 1 second. + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); + statement.setQueryTimeout(1); + assertThrows( + JdbcSqlTimeoutException.class, + () -> statement.executeUpdate(INSERT_STATEMENT.getSql())); + } + } + } + + @Test + public void testExecuteBatchTimeout() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + // First verify that batch dml does not time out by default. + statement.addBatch(INSERT_STATEMENT.getSql()); + int[] result = statement.executeBatch(); + assertArrayEquals(new int[] {1}, result); + + // Simulate that executeBatchDml takes 2 seconds and set a statement timeout of 1 second. + mockSpanner.setExecuteBatchDmlExecutionTime( + SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); + statement.setQueryTimeout(1); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertThrows(JdbcSqlTimeoutException.class, statement::executeBatch); + } + } + } +} From 870c56ccc1d4bcc270f312197b7ea71800a34393 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 19 May 2022 17:01:31 -0400 Subject: [PATCH 0701/1979] feat: add build scripts for native image testing in Java 17 (#1440) (#875) Source-Link: https://github.com/googleapis/synthtool/commit/505ce5a7edb58bf6d9d4de10b4bb4e81000ae324 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:2567a120ce90fadb6201999b87d649d9f67459de28815ad239bce9ebfaa18a74 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +-- java-spanner-jdbc/.kokoro/build.sh | 5 +++ .../.kokoro/presubmit/graalvm-native-17.cfg | 33 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index f60d774937f6..a79f06271b60 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813 -# created: 2022-04-06T16:30:03.627422514Z + digest: sha256:2567a120ce90fadb6201999b87d649d9f67459de28815ad239bce9ebfaa18a74 +# created: 2022-05-19T15:12:45.278246753Z diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 5e9d243d15ff..5ca4fd4bcd90 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -74,6 +74,11 @@ graalvm) mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test RETURN_CODE=$? ;; +graalvm17) + # Run Unit and Integration Tests with Native Image + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test + RETURN_CODE=$? + ;; samples) SAMPLES_DIR=samples # only run ITs in snapshot/ on presubmit PRs. run ITs in all 3 samples/ subdirectories otherwise. diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg new file mode 100644 index 000000000000..a3f7fb9d4943 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -0,0 +1,33 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm17" +} + +env_vars: { + key: "JOB_TYPE" + value: "graalvm17" +} + +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-it-service-account" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" +} \ No newline at end of file From c5742d9a49a2af793ef3ff30ec0a0aee780998cb Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 20 May 2022 02:00:22 +0200 Subject: [PATCH 0702/1979] deps: update opencensus.version to v0.31.1 (#865) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opencensus:opencensus-contrib-grpc-util](https://togithub.com/census-instrumentation/opencensus-java) | `0.31.0` -> `0.31.1` | [![age](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-contrib-grpc-util/0.31.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-contrib-grpc-util/0.31.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-contrib-grpc-util/0.31.1/compatibility-slim/0.31.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-contrib-grpc-util/0.31.1/confidence-slim/0.31.0)](https://docs.renovatebot.com/merge-confidence/) | | [io.opencensus:opencensus-api](https://togithub.com/census-instrumentation/opencensus-java) | `0.31.0` -> `0.31.1` | [![age](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-api/0.31.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-api/0.31.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-api/0.31.1/compatibility-slim/0.31.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/io.opencensus:opencensus-api/0.31.1/confidence-slim/0.31.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    census-instrumentation/opencensus-java ### [`v0.31.1`](https://togithub.com/census-instrumentation/opencensus-java/releases/v0.31.1) [Compare Source](https://togithub.com/census-instrumentation/opencensus-java/compare/v0.31.0...v0.31.1) #### What's Changed - \[v0.31.x] Fix retry stat measures to match those in grpc-java exactly ([#​2097](https://togithub.com/census-instrumentation/opencensus-java/issues/2097)) by [@​mackenziestarr](https://togithub.com/mackenziestarr) in [https://github.com/census-instrumentation/opencensus-java/pull/2102](https://togithub.com/census-instrumentation/opencensus-java/pull/2102) **Full Changelog**: https://github.com/census-instrumentation/opencensus-java/compare/v0.31.0...v0.31.1
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ca292797766a..ca0bc4740e57 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -54,7 +54,7 @@ 1.1.3 4.5.1 2.2 - 0.31.0 + 0.31.1 From 25687c4575345c2dae25dab08d92eca7d8cf99de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 24 May 2022 03:18:15 +0200 Subject: [PATCH 0703/1979] deps: bump Spanner to 6.23.3 (#862) Bumps Spanner to 6.23.3 and modifies SQL script test files to reflect the changes for client side statements for PG. Replaces #788 --- java-spanner-jdbc/pom.xml | 2 +- .../JdbcConnectionGeneratedSqlScriptTest.java | 6 +- .../spanner/jdbc/JdbcConnectionTest.java | 11 +- .../spanner/jdbc/JdbcTimeoutSqlTest.java | 3 +- .../jdbc/it/ITJdbcQueryOptionsTest.java | 23 +- .../it/ITJdbcReadWriteAutocommitTest.java | 5 +- .../ConnectionImplGeneratedSqlScriptTest.sql | 9387 ++++++----- .../ConnectionImplGeneratedSqlScriptTest.sql | 13788 ++++++++++++++++ .../spanner/jdbc/PostgreSQL/ITDdlTest.sql | 8 +- .../jdbc/PostgreSQL/ITReadOnlySpannerTest.sql | 54 +- .../ITReadOnlySpannerTest_CreateTables.sql | 2 +- .../ITReadWriteAutocommitSpannerTest.sql | 46 +- .../PostgreSQL/ITScriptTest_CreateTables.sql | 10 +- .../ITScriptTest_InsertTestData.sql | 2 +- .../ITScriptTest_TestAutocommitDmlMode.sql | 42 +- .../ITScriptTest_TestAutocommitReadOnly.sql | 4 +- .../ITScriptTest_TestGetReadTimestamp.sql | 42 +- .../ITScriptTest_TestQueryOptions.sql | 32 +- .../ITScriptTest_TestReadOnlyStaleness.sql | 240 +- .../ITScriptTest_TestSetStatements.sql | 40 +- ...ITScriptTest_TestTemporaryTransactions.sql | 2 +- .../ITScriptTest_TestTransactionMode.sql | 14 +- ...criptTest_TestTransactionMode_ReadOnly.sql | 14 +- .../jdbc/PostgreSQL/ITSqlMusicScriptTest.sql | 26 +- .../jdbc/PostgreSQL/TimeoutSqlScriptTest.sql | 54 + 25 files changed, 19569 insertions(+), 4288 deletions(-) create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ca0bc4740e57..afb192dd433f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.21.2 + 6.23.3 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index c1c90e8f6cd5..5844feefbaae 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -26,7 +26,6 @@ import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.connection.ConnectionImplTest; import com.google.cloud.spanner.connection.ConnectionOptions; -import com.google.cloud.spanner.connection.SqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; import java.sql.SQLException; import org.junit.Test; @@ -62,7 +61,7 @@ public GenericConnection getConnection() { ConnectionOptions options = mock(ConnectionOptions.class); when(options.getUri()).thenReturn(ConnectionImplTest.URI); com.google.cloud.spanner.connection.Connection spannerConnection = - ConnectionImplTest.createConnection(options); + ConnectionImplTest.createConnection(options, dialect); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); try { @@ -82,7 +81,8 @@ public GenericConnection getConnection() { @Test public void testGeneratedScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider(dialect)); + String prefix = dialect == Dialect.POSTGRESQL ? "PostgreSQL/" : ""; verifier.verifyStatementsInFile( - "ConnectionImplGeneratedSqlScriptTest.sql", SqlScriptVerifier.class, false); + prefix + "ConnectionImplGeneratedSqlScriptTest.sql", getClass(), false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 79eafe01c42d..8010c2151901 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -76,7 +76,7 @@ private com.google.cloud.spanner.ResultSet createSelect1ResultSet() { private JdbcConnection createConnection(ConnectionOptions options) throws SQLException { com.google.cloud.spanner.connection.Connection spannerConnection = - ConnectionImplTest.createConnection(options); + ConnectionImplTest.createConnection(options, dialect); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); return new JdbcConnection( @@ -157,10 +157,13 @@ public void testRollback() throws SQLException { // verify that there is no transaction started anymore assertThat(connection.getSpannerConnection().isTransactionStarted()).isFalse(); // verify that there is no commit timestamp - try (ResultSet rs = - connection.createStatement().executeQuery("show variable commit_timestamp")) { + String showCommitTimestamp = + dialect == Dialect.POSTGRESQL + ? "show spanner.commit_timestamp" + : "show variable commit_timestamp"; + try (ResultSet rs = connection.createStatement().executeQuery(showCommitTimestamp)) { assertThat(rs.next()).isTrue(); - assertThat(rs.getTimestamp("COMMIT_TIMESTAMP")).isNull(); + assertThat(rs.getTimestamp(1)).isNull(); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java index cd462b431826..0ecb01f87e0d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTimeoutSqlTest.java @@ -46,6 +46,7 @@ public static Object[] data() { @Test public void testTimeoutScript() throws Exception { JdbcSqlScriptVerifier verifier = new JdbcSqlScriptVerifier(new TestConnectionProvider(dialect)); - verifier.verifyStatementsInFile("TimeoutSqlScriptTest.sql", getClass(), false); + String prefix = dialect == Dialect.POSTGRESQL ? "PostgreSQL/" : ""; + verifier.verifyStatementsInFile(prefix + "TimeoutSqlScriptTest.sql", getClass(), false); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 4cdd0e9c85c0..46251ac9e28d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -110,12 +110,19 @@ public Dialect getDialect() { return dialect.dialect; } + private String getNamespace() { + return getDialect() == Dialect.POSTGRESQL ? "SPANNER." : ""; + } + private void verifyOptimizerVersion(Connection connection, String expectedVersion) throws SQLException { try (ResultSet rs = - connection.createStatement().executeQuery("SHOW VARIABLE OPTIMIZER_VERSION")) { + connection + .createStatement() + .executeQuery(String.format("SHOW VARIABLE %sOPTIMIZER_VERSION", getNamespace()))) { assertThat(rs.next()).isTrue(); - assertThat(rs.getString("OPTIMIZER_VERSION")).isEqualTo(expectedVersion); + assertThat(rs.getString(String.format("%sOPTIMIZER_VERSION", getNamespace()))) + .isEqualTo(expectedVersion); assertThat(rs.next()).isFalse(); } } @@ -153,7 +160,9 @@ public void connectionUrlWithInvalidOptimizerVersion() throws SQLException { public void setOptimizerVersion() throws SQLException { try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, ""); - connection.createStatement().execute("SET OPTIMIZER_VERSION='1'"); + connection + .createStatement() + .execute(String.format("SET %sOPTIMIZER_VERSION='1'", getNamespace())); verifyOptimizerVersion(connection, "1"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { assertThat(rs.next()).isTrue(); @@ -167,7 +176,9 @@ public void setOptimizerVersion() throws SQLException { public void setLatestOptimizerVersion() throws SQLException { try (Connection connection = createConnection(env, database)) { verifyOptimizerVersion(connection, ""); - connection.createStatement().execute("SET OPTIMIZER_VERSION='LATEST'"); + connection + .createStatement() + .execute(String.format("SET %sOPTIMIZER_VERSION='LATEST'", getNamespace())); verifyOptimizerVersion(connection, "LATEST"); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { assertThat(rs.next()).isTrue(); @@ -182,7 +193,9 @@ public void setInvalidOptimizerVersion() throws SQLException { assumeFalse( "optimizer version is ignored on emulator", EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection(env, database)) { - connection.createStatement().execute("SET OPTIMIZER_VERSION='9999999'"); + connection + .createStatement() + .execute(String.format("SET %sOPTIMIZER_VERSION='9999999'", getNamespace())); try (ResultSet rs = connection.createStatement().executeQuery("SELECT 1")) { fail("missing expected exception"); } catch (SQLException e) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 5f81ce23e415..7076563b3f14 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -101,7 +101,10 @@ public void test02_WriteMutation() throws Exception { connection.write( Mutation.newInsertBuilder("TEST").set("ID").to(9999L).set("NAME").to("FOO").build()); java.sql.Statement statement = connection.createStatement(); - statement.execute("SHOW VARIABLE COMMIT_TIMESTAMP"); + statement.execute( + String.format( + "SHOW VARIABLE %sCOMMIT_TIMESTAMP", + getDialect() == Dialect.POSTGRESQL ? "SPANNER." : "")); try (java.sql.ResultSet rs = statement.getResultSet()) { assertThat(rs.next(), is(true)); assertThat(rs.getTimestamp(1), is(notNullValue())); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql index a4d68cda077a..be5a1671ae02 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql @@ -1,194 +1,212 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z' +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:57.888000000Z'; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -204,29 +222,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -270,54 +302,85 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -327,124 +390,172 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -454,53 +565,77 @@ SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.128000000Z' +COMMIT; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -516,29 +651,59 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -582,29 +747,61 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -616,210 +813,206 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z' +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.214000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -835,29 +1028,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -901,61 +1108,70 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -965,124 +1181,124 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -1092,53 +1308,59 @@ SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z' +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.271000000Z' +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1154,29 +1376,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1220,29 +1456,45 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1254,35 +1506,27 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -1292,172 +1536,124 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -1467,69 +1663,59 @@ SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.339000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1545,41 +1731,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1623,39 +1811,45 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1667,9 +1861,7 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -1804,14 +1996,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.423000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1834,6 +2026,11 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -1869,6 +2066,18 @@ SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1925,11 +2134,24 @@ COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1942,231 +2164,210 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=FALSE; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; ROLLBACK; NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.470000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2180,37 +2381,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2252,237 +2461,263 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.514000000Z'; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2496,31 +2731,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2562,56 +2811,90 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2619,140 +2902,196 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -2760,55 +3099,86 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.580000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2822,31 +3192,69 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2888,66 +3296,117 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2955,164 +3414,196 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -3120,63 +3611,86 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.663000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3190,37 +3704,69 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3262,265 +3808,282 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -ABORT BATCH; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.751000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3534,31 +4097,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3600,230 +4177,283 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.797000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.238000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.797000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.238000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3837,31 +4467,53 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3903,325 +4555,255 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.477000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.850000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.477000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4235,43 +4817,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4313,74 +4897,68 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; -BEGIN TRANSACTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; -COMMIT; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -4388,140 +4966,100 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -4529,55 +5067,50 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.947000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4591,31 +5124,37 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4657,143 +5196,167 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT UPDATE_COUNT 1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; @@ -4801,79 +5364,75 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.897000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2020-03-05T17:56:58.985000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.897000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4889,23 +5448,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4949,229 +5528,283 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT UPDATE_COUNT 1 +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=TRUE; +SET READONLY=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z' +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.013000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5186,30 +5819,52 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5252,66 +5907,87 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -BEGIN TRANSACTION; +SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -5321,166 +5997,150 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -5492,10 +6152,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -5507,18 +6166,17 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -5528,75 +6186,77 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.061000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -5612,47 +6272,59 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -5695,44 +6367,62 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -5743,149 +6433,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -5896,67 +6575,69 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z' +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.106000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5971,30 +6652,44 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6037,68 +6732,70 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -6107,146 +6804,109 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6257,10 +6917,8 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6271,17 +6929,14 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -6290,68 +6945,60 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.155000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -6366,42 +7013,44 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6444,39 +7093,46 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -RUN BATCH; +SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -6486,42 +7142,28 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -6530,167 +7172,109 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6701,11 +7285,8 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6716,19 +7297,14 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -6737,76 +7313,60 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z' +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.218000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -6821,48 +7381,44 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6905,44 +7461,46 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -6952,165 +7510,175 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; START BATCH DML; @@ -7123,67 +7691,85 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.279000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.279000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @@ -7200,34 +7786,50 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @@ -7272,170 +7874,208 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -7447,58 +8087,75 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.328000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.328000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -7514,29 +8171,43 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -7580,55 +8251,73 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -7637,104 +8326,88 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7745,8 +8418,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7757,13 +8429,12 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -7772,52 +8443,51 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z' +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.396000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7832,30 +8502,36 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7898,29 +8574,38 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -7930,198 +8615,222 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.425000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8137,29 +8846,43 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8203,222 +8926,343 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.451000000Z'; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.451000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8435,28 +9279,58 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8501,350 +9375,302 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -BEGIN TRANSACTION; +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT UPDATE_COUNT 1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.570000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.493000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.570000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8860,47 +9686,51 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8944,57 +9774,54 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -BEGIN TRANSACTION; +SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -9004,34 +9831,33 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; @@ -9039,186 +9865,162 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.539000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.779000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.539000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.779000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -9235,34 +10037,42 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9307,55 +10117,81 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -9365,82 +10201,166 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -9452,6 +10372,10 @@ START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -9463,10 +10387,18 @@ START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -9476,43 +10408,84 @@ SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z' +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.575000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -9528,23 +10501,67 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9588,23 +10605,67 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -9615,197 +10676,206 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z' +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.601000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -9819,31 +10889,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9885,56 +10969,72 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -BEGIN TRANSACTION; +SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -9942,124 +11042,134 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -10067,53 +11177,59 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z' +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.621000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10127,31 +11243,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10193,51 +11323,65 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10246,7 +11390,7 @@ ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10255,7 +11399,7 @@ ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10268,7 +11412,7 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10276,16 +11420,15 @@ SELECT 1 AS TEST; ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10294,51 +11437,51 @@ ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10347,14 +11490,14 @@ ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10363,21 +11506,21 @@ ROLLBACK; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10386,14 +11529,14 @@ ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10401,23 +11544,22 @@ SELECT 1 AS TEST; ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10426,25 +11568,37 @@ ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10452,7 +11606,7 @@ SELECT 1 AS TEST; ROLLBACK; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10465,7 +11619,7 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10475,26 +11629,26 @@ SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.654000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10504,7 +11658,7 @@ SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10513,7 +11667,7 @@ ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10523,14 +11677,23 @@ SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10549,35 +11712,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10586,7 +11749,27 @@ ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10633,7 +11816,7 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10642,14 +11825,14 @@ ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10657,7 +11840,23 @@ SELECT 1 AS TEST; ROLLBACK; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10666,7 +11865,15 @@ ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 @@ -10674,243 +11881,344 @@ SELECT 1 AS TEST; ROLLBACK; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.711000000Z'; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.711000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10924,37 +12232,69 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10996,230 +12336,284 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' -SHOW VARIABLE READ_ONLY_STALENESS; +COMMIT; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.762000000Z'; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.762000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11233,31 +12627,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11299,235 +12707,287 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -COMMIT; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.388000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.805000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.388000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11541,31 +13001,53 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11607,349 +13089,260 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.635000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.849000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.635000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11963,49 +13356,45 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12047,75 +13436,67 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -BEGIN TRANSACTION; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -12124,99 +13505,109 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -12225,44 +13616,49 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2020-03-05T17:56:59.879000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -12277,24 +13673,36 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +SET OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -12337,33 +13745,44 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql new file mode 100644 index 000000000000..ac9528cc83d5 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql @@ -0,0 +1,13788 @@ +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.355000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.355000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.594000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.594000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.980000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.980000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.448000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.448000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.449000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.677000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.677000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.887000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.887000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.509000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.509000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.756000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.756000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +ABORT BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT UPDATE_COUNT 1 +UPDATE foo SET bar=1; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ WRITE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DML; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +ROLLBACK; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.OPTIMIZER_VERSION='1'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='2'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','2' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION='latest'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','latest' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +SET SPANNER.OPTIMIZER_VERSION=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1us' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0us'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT='1ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ns' +SHOW VARIABLE STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=DEFAULT; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0ns'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW VARIABLE STATEMENT_TIMEOUT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +COMMIT; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' +SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +RUN BATCH; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=FALSE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITDdlTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITDdlTest.sql index 9ee98a4489e8..d5377a73ed09 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITDdlTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITDdlTest.sql @@ -19,8 +19,8 @@ NEW_CONNECTION; @EXPECT RESULT_SET 'AUTOCOMMIT',true SHOW VARIABLE AUTOCOMMIT; -@EXPECT RESULT_SET 'READONLY',false -SHOW VARIABLE READONLY; +@EXPECT RESULT_SET 'SPANNER.READONLY',false +SHOW VARIABLE SPANNER.READONLY; @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 0 AS "EXPECTED" @@ -40,8 +40,8 @@ NEW_CONNECTION; @EXPECT RESULT_SET 'AUTOCOMMIT',true SHOW VARIABLE AUTOCOMMIT; -@EXPECT RESULT_SET 'READONLY',false -SHOW VARIABLE READONLY; +@EXPECT RESULT_SET 'SPANNER.READONLY',false +SHOW VARIABLE SPANNER.READONLY; @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 0 AS "EXPECTED" diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest.sql index 4c8a514751f1..c03c8ae6f225 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest.sql @@ -17,8 +17,8 @@ NEW_CONNECTION; -- Test a couple of count queries to ensure the presence of the data -@EXPECT RESULT_SET 'READONLY',true -SHOW VARIABLE READONLY; +@EXPECT RESULT_SET 'SPANNER.READONLY',true +SHOW VARIABLE SPANNER.READONLY; -- Check initial contents. @EXPECT RESULT_SET @@ -29,13 +29,13 @@ SELECT COUNT(*) AS "ACTUAL", 1000 AS "EXPECTED" FROM NUMBERS; SELECT COUNT(*) AS "ACTUAL", 168 AS "EXPECTED" FROM PRIME_NUMBERS; -- Assert that there is a read timestamp -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -- Test two selects in one temporary transaction -@EXPECT RESULT_SET 'READONLY',true -SHOW VARIABLE READONLY; +@EXPECT RESULT_SET 'SPANNER.READONLY',true +SHOW VARIABLE SPANNER.READONLY; BEGIN; @@ -45,7 +45,7 @@ FROM NUMBERS WHERE NUMBER=1; @PUT 'READ_TIMESTAMP1' -SHOW VARIABLE READ_TIMESTAMP; +SHOW VARIABLE SPANNER.READ_TIMESTAMP; @EXPECT RESULT_SET 'prime_number',13 SELECT PRIME_NUMBER @@ -53,93 +53,93 @@ FROM PRIME_NUMBERS WHERE PRIME_NUMBER=13; @PUT 'READ_TIMESTAMP2' -SHOW VARIABLE READ_TIMESTAMP; +SHOW VARIABLE SPANNER.READ_TIMESTAMP; COMMIT; NEW_CONNECTION; --TimestampBound.ofExactStaleness(1, TimeUnit.MILLISECONDS), -SET READ_ONLY_STALENESS = 'EXACT_STALENESS 1ms'; +SET SPANNER.READ_ONLY_STALENESS = 'EXACT_STALENESS 1ms'; -- Check SELECT with EXACT_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 1000 AS "EXPECTED" FROM NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Check SELECT with EXACT_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 168 AS "EXPECTED" FROM PRIME_NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; --TimestampBound.ofMaxStaleness(100, TimeUnit.MILLISECONDS) -SET READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; +SET SPANNER.READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; -- Check SELECT with MAX_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 1000 AS "EXPECTED" FROM NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Check SELECT with MAX_STALENESS @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 168 AS "EXPECTED" FROM PRIME_NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; --TimestampBound.strong() -SET READ_ONLY_STALENESS = 'STRONG'; +SET SPANNER.READ_ONLY_STALENESS = 'STRONG'; -- Check SELECT with STRONG @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 1000 AS "EXPECTED" FROM NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Check SELECT with STRONG @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 168 AS "EXPECTED" FROM PRIME_NUMBERS; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; --TimestampBound.ofMaxStaleness(100, TimeUnit.MILLISECONDS) SET AUTOCOMMIT = FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; +SET SPANNER.READ_ONLY_STALENESS = 'MAX_STALENESS 100ms'; NEW_CONNECTION; --TimestampBound.strong() SET AUTOCOMMIT = FALSE; -SET READ_ONLY_STALENESS = 'STRONG'; +SET SPANNER.READ_ONLY_STALENESS = 'STRONG'; -- Check SELECT with STRONG in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 1000 AS "EXPECTED" FROM NUMBERS; @PUT 'READ_TIMESTAMP1' -SHOW VARIABLE READ_TIMESTAMP; +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Check SELECT with STRONG in a transaction. @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 168 AS "EXPECTED" FROM PRIME_NUMBERS; @PUT 'READ_TIMESTAMP2' -SHOW VARIABLE READ_TIMESTAMP; +SHOW VARIABLE SPANNER.READ_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest_CreateTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest_CreateTables.sql index 40246f6cde1c..b1499f86817d 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest_CreateTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadOnlySpannerTest_CreateTables.sql @@ -16,7 +16,7 @@ NEW_CONNECTION; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; START BATCH DDL; CREATE TABLE NUMBERS (NUMBER BIGINT PRIMARY KEY, NAME VARCHAR(200) NOT NULL); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql index c7dfb76d7c72..ae7ee898cfad 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql @@ -19,15 +19,15 @@ NEW_CONNECTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS "TEST"; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; INSERT INTO TEST (ID, NAME) VALUES (1, 'test'); -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; @@ -36,31 +36,31 @@ NEW_CONNECTION; SELECT * FROM TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; @EXPECT UPDATE_COUNT 1 INSERT INTO TEST (ID, NAME) VALUES (2, 'FOO'); -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 2 AS "EXPECTED" FROM TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Do an update in partioned_non_atomic mode -SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT UPDATE_COUNT 1 UPDATE TEST SET NAME = 'partitioned' WHERE ID=2; -- Reset dml mode to transactional -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; @EXPECT RESULT_SET 'name','partitioned' SELECT NAME FROM TEST WHERE ID=2; @@ -71,8 +71,8 @@ SET STATEMENT_TIMEOUT = '10000s'; @EXPECT RESULT_SET 'name','partitioned' SELECT NAME FROM TEST WHERE ID=2; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Set a statement timeout that should always be exceeded SET STATEMENT_TIMEOUT = '1ns'; @@ -81,10 +81,10 @@ SET STATEMENT_TIMEOUT = '1ns'; SELECT NAME FROM TEST WHERE ID=2; -- Turn off statement timeouts -SET STATEMENT_TIMEOUT = null; +SET STATEMENT_TIMEOUT = default; -- There should be no read timestamp available -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Set a statement timeout that should never be reached SET STATEMENT_TIMEOUT = '10000s'; @@ -92,8 +92,8 @@ SET STATEMENT_TIMEOUT = '10000s'; @EXPECT UPDATE_COUNT 1 INSERT INTO TEST (ID, NAME) VALUES (3, 'test'); -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; -- Set a statement timeout that should always be exceeded SET STATEMENT_TIMEOUT = '1ns'; @@ -102,7 +102,7 @@ SET STATEMENT_TIMEOUT = '1ns'; INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); -- Turn off statement timeouts -SET STATEMENT_TIMEOUT = null; +set statement_timeout = default; -- Delete record with id 4 if it exists (even though the statement timed out, -- there is still a small chance that the statement did succeed) DELETE FROM TEST WHERE ID=4; @@ -113,10 +113,10 @@ SET STATEMENT_TIMEOUT = '1ns'; @EXPECT EXCEPTION DEADLINE_EXCEEDED INSERT INTO TEST (ID, NAME) VALUES (4, 'test'); -SET STATEMENT_TIMEOUT = null; +set statement_timeout = default; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_CreateTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_CreateTables.sql index 2367518d86ac..c35e8393fd3b 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_CreateTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_CreateTables.sql @@ -26,9 +26,9 @@ SHOW VARIABLE AUTOCOMMIT; -- Turn off readonly (and verify) @EXPECT NO_RESULT -SET READONLY = FALSE; -@EXPECT RESULT_SET 'READONLY',false -SHOW VARIABLE READONLY; +SET SPANNER.READONLY = FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',false +SHOW VARIABLE SPANNER.READONLY; -- Start a DDL batch to execute a number of DDL statements as one operation. @EXPECT NO_RESULT @@ -61,7 +61,7 @@ CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle); RUN BATCH; -- Reset the statement timeout -SET STATEMENT_TIMEOUT=null; +SET STATEMENT_TIMEOUT=default; /* * Verify that the test tables have been created @@ -69,7 +69,7 @@ SET STATEMENT_TIMEOUT=null; @EXPECT NO_RESULT SET AUTOCOMMIT = TRUE; @EXPECT NO_RESULT -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; -- Check that the table has been created @EXPECT RESULT_SET diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_InsertTestData.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_InsertTestData.sql index 733820c2e14b..7fea8b1f413e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_InsertTestData.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_InsertTestData.sql @@ -21,7 +21,7 @@ @EXPECT NO_RESULT SET AUTOCOMMIT = FALSE; @EXPECT NO_RESULT -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; @EXPECT UPDATE_COUNT 6 INSERT INTO Singers (SingerId, FirstName, LastName) diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql index 961f85c88544..59dc80ed7ce4 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitDmlMode.sql @@ -19,20 +19,20 @@ */ SET AUTOCOMMIT = FALSE; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; -- First verify that the mode cannot be set when not in autocommit mode @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode while not in autocommit mode or while a transaction is active' -SET AUTOCOMMIT_DML_MODE = 'Transactional'; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'Transactional'; -- Turn on autocommit and set mode to transactional SET AUTOCOMMIT = TRUE; @EXPECT NO_RESULT -SET AUTOCOMMIT_DML_MODE = 'Transactional'; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'Transactional'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; -- Verify that executing an update statement is possible @EXPECT UPDATE_COUNT 1 @@ -46,10 +46,10 @@ WHERE SingerId=1; -- Reset to original value in partioned mode @EXPECT NO_RESULT -SET AUTOCOMMIT_DML_MODE = 'partitioned_non_atomic'; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'partitioned_non_atomic'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; @EXPECT UPDATE_COUNT 1 UPDATE Singers SET LastName='Last 1' @@ -61,27 +61,27 @@ FROM Singers WHERE SingerId=1; -- Verify that trying to set the mode to an invalid value will throw an exception -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT_DML_MODE: 'None'' -SET AUTOCOMMIT_DML_MODE = 'None'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.AUTOCOMMIT_DML_MODE: 'None'' +SET SPANNER.AUTOCOMMIT_DML_MODE = 'None'; -- Verify that setting the mode in read-only mode will throw an exception -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode for a read-only connection' -SET AUTOCOMMIT_DML_MODE = 'Transactional'; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'Transactional'; -- Back to read-write mode -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; --- Verify that turning off autocommit and on again will not reset the AUTOCOMMIT_DML_MODE value -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +-- Verify that turning off autocommit and on again will not reset the SPANNER.AUTOCOMMIT_DML_MODE value +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT = FALSE; SET AUTOCOMMIT = TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; -- Reset to default value -SET AUTOCOMMIT_DML_MODE = 'Transactional'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'Transactional'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitReadOnly.sql index 7b4b08fa7cc5..752a7c03b2d5 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitReadOnly.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestAutocommitReadOnly.sql @@ -19,11 +19,11 @@ */ SET AUTOCOMMIT = TRUE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; -- First verify that the autocommit dml mode cannot be set when in read-only mode @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set autocommit DML mode for a read-only connection' -SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'; +SET SPANNER.AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'; -- Verify that executing an update statement fails @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed in read-only mode' diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql index bd0b2fb60dd9..00fa78c3f7b0 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql @@ -15,56 +15,56 @@ */ /* - * Test SHOW VARIABLE READ_TIMESTAMP in different modes + * Test SHOW VARIABLE SPANNER.READ_TIMESTAMP in different modes */ -- Select query in autocommit and read-only mode should yield a read timestamp SET AUTOCOMMIT = TRUE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; @EXPECT RESULT_SET SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM Singers WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Select query in autocommit and read-write mode should yield a read timestamp -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; @EXPECT RESULT_SET SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM Singers WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Select query in transactional and read-only mode should yield a read timestamp SET AUTOCOMMIT = FALSE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; @EXPECT RESULT_SET SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM Singers WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; COMMIT; -- Select query in transactional and read-write mode should NOT yield a read timestamp -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; @EXPECT RESULT_SET SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM Singers WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; COMMIT; @@ -75,8 +75,8 @@ SET AUTOCOMMIT = FALSE; UPDATE Singers SET LastName='New Last 1' WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; ROLLBACK; @@ -90,23 +90,23 @@ COMMIT; -- Invalid select query in autocommit and read-only mode should not yield a read timestamp SET AUTOCOMMIT = TRUE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; @EXPECT EXCEPTION INVALID_ARGUMENT SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM NonExistentTable WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Invalid select query in autocommit and read-write mode should not yield a read timestamp -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; @EXPECT EXCEPTION INVALID_ARGUMENT SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" FROM NonExistentTable WHERE SingerId=1; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestQueryOptions.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestQueryOptions.sql index 146c93643a44..9ce944d42a97 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestQueryOptions.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestQueryOptions.sql @@ -20,32 +20,32 @@ -- Set and get valid values. @EXPECT NO_RESULT -SET OPTIMIZER_VERSION = '1'; +SET SPANNER.OPTIMIZER_VERSION = '1'; -@EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' -SHOW VARIABLE OPTIMIZER_VERSION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @EXPECT NO_RESULT -SET OPTIMIZER_VERSION = '555'; +SET SPANNER.OPTIMIZER_VERSION = '555'; -@EXPECT RESULT_SET 'OPTIMIZER_VERSION','555' -SHOW VARIABLE OPTIMIZER_VERSION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','555' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @EXPECT NO_RESULT -SET OPTIMIZER_VERSION = 'LATEST'; +SET SPANNER.OPTIMIZER_VERSION = 'LATEST'; -@EXPECT RESULT_SET 'OPTIMIZER_VERSION','LATEST' -SHOW VARIABLE OPTIMIZER_VERSION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','LATEST' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @EXPECT NO_RESULT -SET OPTIMIZER_VERSION = ''; +SET SPANNER.OPTIMIZER_VERSION = ''; -@EXPECT RESULT_SET 'OPTIMIZER_VERSION','' -SHOW VARIABLE OPTIMIZER_VERSION; +@EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' +SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; -- Try to set invalid values. -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for OPTIMIZER_VERSION: 'None'' -SET OPTIMIZER_VERSION = 'None'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.OPTIMIZER_VERSION: 'None'' +SET SPANNER.OPTIMIZER_VERSION = 'None'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for OPTIMIZER_VERSION: 'v1'' -SET OPTIMIZER_VERSION = 'v1'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.OPTIMIZER_VERSION: 'v1'' +SET SPANNER.OPTIMIZER_VERSION = 'v1'; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestReadOnlyStaleness.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestReadOnlyStaleness.sql index 1839bdcd1ea2..85f494cf3793 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestReadOnlyStaleness.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestReadOnlyStaleness.sql @@ -18,129 +18,129 @@ * Script that tests the different possible read-only staleness modes */ --- First test in autocommit mode. READONLY mode is not strictly necessary +-- First test in autocommit mode. SPANNER.READONLY mode is not strictly necessary SET AUTOCOMMIT = TRUE; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; --------------------- STRONG ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Strong'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Strong'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='strong'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set STRONG with a timestamp value -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' -SET READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' +SET SPANNER.READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; -- Try to set STRONG with a duration value -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 10s'' -SET READ_ONLY_STALENESS='STRONG 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'STRONG 10s'' +SET SPANNER.READ_ONLY_STALENESS='STRONG 10s'; --------------------- MIN_READ_TIMESTAMP ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Min_Read_Timestamp 2018-11-15T13:09:25-08:00'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T21:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Min_Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='min_read_timestamp 2018-11-15T13:09:25+07:45'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T05:24:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='min_read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set MIN_READ_TIMESTAMP without a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP'; -- Try to set MIN_READ_TIMESTAMP with a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 10s'; --------------------- READ_TIMESTAMP ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set READ_TIMESTAMP without a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP'' -SET READ_ONLY_STALENESS='READ_TIMESTAMP'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'READ_TIMESTAMP'' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP'; -- Try to set READ_TIMESTAMP with a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' -SET READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; --------------------- MAX_STALENESS ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Max_Staleness 1000ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Max_Staleness 1000ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='max_staleness 10001ns'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 10001ns' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='max_staleness 10001ns'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 10001ns' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set MAX_STALENESS without a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS'' -SET READ_ONLY_STALENESS='MAX_STALENESS'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MAX_STALENESS'' +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS'; -- Try to set MAX_STALENESS with a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25+07:45'' -SET READ_ONLY_STALENESS='MAX_STALENESS 2018-11-15T13:09:25+07:45'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25+07:45'' +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 2018-11-15T13:09:25+07:45'; --------------------- EXACT_STALENESS ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Exact_Staleness 1001ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Exact_Staleness 1001ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='exact_staleness 1000000000ns'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='exact_staleness 1000000000ns'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set EXACT_STALENESS without a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS'' -SET READ_ONLY_STALENESS='EXACT_STALENESS'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'EXACT_STALENESS'' +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS'; -- Try to set EXACT_STALENESS with a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' -SET READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; ------------------------------------------------------------------------------------------------------------------------------ @@ -148,105 +148,105 @@ SET READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; -- Then test in transactional read-only mode. SET AUTOCOMMIT = FALSE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; --------------------- STRONG ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Strong'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Strong'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='strong'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='strong'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set STRONG with a timestamp value -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' -SET READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'STRONG 2018-11-15T13:09:25Z'' +SET SPANNER.READ_ONLY_STALENESS='STRONG 2018-11-15T13:09:25Z'; -- Try to set STRONG with a duration value -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'STRONG 10s'' -SET READ_ONLY_STALENESS='STRONG 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'STRONG 10s'' +SET SPANNER.READ_ONLY_STALENESS='STRONG 10s'; --------------------- MIN_READ_TIMESTAMP ---------------------------- -- This is not allowed in transactional mode @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode' -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; --------------------- READ_TIMESTAMP ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2018-11-15T13:09:25Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T13:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Read_Timestamp 2018-11-15T13:09:25-08:00'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T21:09:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='read_timestamp 2018-11-15T13:09:25+07:45'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set READ_TIMESTAMP without a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP'' -SET READ_ONLY_STALENESS='READ_TIMESTAMP'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'READ_TIMESTAMP'' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP'; -- Try to set READ_TIMESTAMP with a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' -SET READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'READ_TIMESTAMP 10s'' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 10s'; --------------------- MAX_STALENESS ---------------------------- -- only allowed in autocommit mode @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: MAX_STALENESS and MIN_READ_TIMESTAMP are only allowed in autocommit mode' -SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2018-11-15T05:24:25Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; --------------------- EXACT_STALENESS ---------------------------- @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='Exact_Staleness 1001ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='Exact_Staleness 1001ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1001ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='exact_staleness 1000000000ns'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='exact_staleness 1000000000ns'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Try to set EXACT_STALENESS without a duration -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS'' -SET READ_ONLY_STALENESS='EXACT_STALENESS'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'EXACT_STALENESS'' +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS'; -- Try to set EXACT_STALENESS with a timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' -SET READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'EXACT_STALENESS 2018-11-15T13:09:25+07:45'' +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 2018-11-15T13:09:25+07:45'; ---------------------------------------------------------------------------------------------------------------- -- Then test in transactional read-write mode. This should also work, although it has no effect on the current transaction, unless the transaction mode is explicitly set to read only SET AUTOCOMMIT = FALSE; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; @EXPECT NO_RESULT -SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; -- Then test while in an active transaction. This should not be allowed. SET TRANSACTION READ ONLY; @@ -254,9 +254,9 @@ SELECT * FROM Singers; @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Cannot set read-only staleness when a transaction has been started' -SET READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1000ms'; -- Check that the staleness mode is still 'STRONG' -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; COMMIT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestSetStatements.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestSetStatements.sql index bd9d82916199..d8363d29039e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestSetStatements.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestSetStatements.sql @@ -20,34 +20,34 @@ @EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT: on' set autocommit = on; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READONLY: on' -set readonly = on; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READONLY: on' +set spanner.readonly = on; SET AUTOCOMMIT = TRUE; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for AUTOCOMMIT_DML_MODE: 'non_atomic'' -set autocommit_dml_mode='non_atomic'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.AUTOCOMMIT_DML_MODE: 'non_atomic'' +set spanner.autocommit_dml_mode='non_atomic'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'weak'' -set read_only_staleness='weak'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'weak'' +set spanner.read_only_staleness='weak'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'strong 2018-11-15T13:09:25Z'' -set read_only_staleness='strong 2018-11-15T13:09:25Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'strong 2018-11-15T13:09:25Z'' +set spanner.read_only_staleness='strong 2018-11-15T13:09:25Z'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' -set read_only_staleness='MIN_READ_TIMESTAMP'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' -set read_only_staleness='MIN_READ_TIMESTAMP 10s'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP'' +set spanner.read_only_staleness='MIN_READ_TIMESTAMP'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 10s'' +set spanner.read_only_staleness='MIN_READ_TIMESTAMP 10s'; -- Missing timezone in timestamp -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 2018-11-15T13:09:25'' -set read_only_staleness='MIN_READ_TIMESTAMP 2018-11-15T13:09:25'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MIN_READ_TIMESTAMP 2018-11-15T13:09:25'' +set spanner.read_only_staleness='MIN_READ_TIMESTAMP 2018-11-15T13:09:25'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS'' -set read_only_staleness='MAX_STALENESS'; -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25Z'' -set read_only_staleness='MAX_STALENESS 2018-11-15T13:09:25Z'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MAX_STALENESS'' +set spanner.read_only_staleness='MAX_STALENESS'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MAX_STALENESS 2018-11-15T13:09:25Z'' +set spanner.read_only_staleness='MAX_STALENESS 2018-11-15T13:09:25Z'; -- Missing time unit -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for READ_ONLY_STALENESS: 'MAX_STALENESS 10'' -set read_only_staleness='MAX_STALENESS 10'; +@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for SPANNER.READ_ONLY_STALENESS: 'MAX_STALENESS 10'' +set spanner.read_only_staleness='MAX_STALENESS 10'; @EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown value for STATEMENT_TIMEOUT: -1' set statement_timeout=-1; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql index d0fd2b54333c..0aa9e205aace 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql @@ -19,7 +19,7 @@ */ SET AUTOCOMMIT = TRUE; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; -- Insert a new singer in a temporary transaction and commit BEGIN; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode.sql index be724771296d..32f7ca54bbbb 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode.sql @@ -19,7 +19,7 @@ */ SET AUTOCOMMIT = FALSE; -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; -- Insert a test record @EXPECT UPDATE_COUNT 1 @@ -40,15 +40,15 @@ WHERE SingerId=9999; UPDATE Singers SET FirstName='New First Name' WHERE SingerId=9999; -- We are in a read-only transaction that has returned a query, so there should be a read-timestamp -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Finish the transaction with a rollback. This removes the read timestamp ROLLBACK; -- Read timestamp from the previous transaction should no longer be available as it rolled back -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Start a new read only transaction and SHOW VARIABLE the read timestamp after a commit SET TRANSACTION READ ONLY; @@ -60,8 +60,8 @@ WHERE SingerId=9999; COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Try to execute DDL in a read-only transaction SET TRANSACTION READ ONLY; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode_ReadOnly.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode_ReadOnly.sql index b84d0ee54b57..c7a9577f37ce 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode_ReadOnly.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestTransactionMode_ReadOnly.sql @@ -19,7 +19,7 @@ */ SET AUTOCOMMIT = FALSE; -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; -- Verify that trying to insert a test record will fail @EXPECT EXCEPTION FAILED_PRECONDITION 'FAILED_PRECONDITION: Update statements are not allowed for read-only transactions' @@ -40,15 +40,15 @@ WHERE SingerId=1; UPDATE Singers SET FirstName='New First Name' WHERE SingerId=9999; -- We are in a read-only transaction that has returned a query, so there should be a read-timestamp -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Finish the transaction with a rollback. This removes the read timestamp ROLLBACK; -- Read timestamp from the previous transaction should no longer be available as it rolled back -@EXPECT RESULT_SET 'READ_TIMESTAMP',null -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Start a new read only transaction and SHOW VARIABLE the read timestamp after a commit SET TRANSACTION READ ONLY; @@ -60,8 +60,8 @@ WHERE SingerId=1; COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- Try to execute DDL in a read-only transaction SET TRANSACTION READ ONLY; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlMusicScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlMusicScriptTest.sql index d175b34490e9..5a192743e6a1 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlMusicScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlMusicScriptTest.sql @@ -483,7 +483,7 @@ FROM Concerts; COMMIT; -- Switch to read-only mode -SET READONLY = TRUE; +SET SPANNER.READONLY = TRUE; -- Do a query that should also generate a read timestamp @EXPECT RESULT_SET 'number_of_singers',30 @@ -491,14 +491,14 @@ SELECT COUNT(*) AS NUMBER_OF_SINGERS FROM Singers; -- Check that the read-timestamp is there -@EXPECT RESULT_SET 'READ_TIMESTAMP' -SHOW VARIABLE READ_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SHOW VARIABLE SPANNER.READ_TIMESTAMP; -- End the read-only transaction and try to get a commit timestamp. COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; -- Try to do an update in read-only mode @EXPECT EXCEPTION FAILED_PRECONDITION @@ -513,7 +513,7 @@ WHERE SingerId=1; COMMIT; -- Switch to autocommit and read/write mode -SET READONLY = FALSE; +SET SPANNER.READONLY = FALSE; SET AUTOCOMMIT = TRUE; -- Try to insert a record that already exists @@ -521,8 +521,8 @@ SET AUTOCOMMIT = TRUE; INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (1,'First 1','Last 1'); -- Ensure there was no commit timestamp -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; -- Delete a record that will also cascade to other records -- First verify the actual number of records @@ -545,8 +545,8 @@ WHERE SingerId=1; @EXPECT UPDATE_COUNT 1 DELETE FROM Singers WHERE SingerId=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 0 AS "EXPECTED" @@ -627,14 +627,14 @@ COMMIT; -- Switch to autocommit and partitioned_non_atomic mode and redo the delete SET AUTOCOMMIT = TRUE; -SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT UPDATE_COUNT 1 DELETE FROM Singers WHERE SingerId=2; -- There should be no commit timestamp for PARTITIONED_NON_ATOMIC -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_TIMESTAMP; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; @EXPECT RESULT_SET SELECT COUNT(*) AS "ACTUAL", 0 AS "EXPECTED" diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql new file mode 100644 index 000000000000..60a8f247698e --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql @@ -0,0 +1,54 @@ +/* + * Copyright 2019 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. + */ + +-- check that the default is null +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW STATEMENT_TIMEOUT; +-- set a new value +SET STATEMENT_TIMEOUT='1000ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW STATEMENT_TIMEOUT; +-- do a simple select and verify that the timeout does not change +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW STATEMENT_TIMEOUT; +-- set a value that contains a fraction of a second +SET STATEMENT_TIMEOUT='1800ms'; +-- check that the jdbc driver reports the value that is set, although under water the JDBC connection will round it to a whole second +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1800ms' +SHOW STATEMENT_TIMEOUT; +-- set a value that is just above a whole second +SET STATEMENT_TIMEOUT='1ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1ms' +SHOW STATEMENT_TIMEOUT; +-- set a value that contains a whole second +SET STATEMENT_TIMEOUT='3s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','3s' +SHOW STATEMENT_TIMEOUT; +-- set a value to a higher value +SET STATEMENT_TIMEOUT='2999ms'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','2999ms' +SHOW STATEMENT_TIMEOUT; +-- Check that setting the value to 0 is not allowed +@EXPECT EXCEPTION INVALID_ARGUMENT +SET STATEMENT_TIMEOUT='0s'; +-- Set a timeout value and then reset it to null +SET STATEMENT_TIMEOUT='1s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' +SHOW STATEMENT_TIMEOUT; +SET STATEMENT_TIMEOUT=default; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW STATEMENT_TIMEOUT; From 0b381faa85a35a463bf967b04f4ebecad58ae66f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 24 May 2022 03:44:11 +0200 Subject: [PATCH 0704/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.12.0 (#874) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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/java-shared-dependencies) | `2.10.0` -> `2.12.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.12.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.12.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.12.0/compatibility-slim/2.10.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.12.0/confidence-slim/2.10.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.12.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​2120-httpsgithubcomgoogleapisjava-shared-dependenciescomparev2110v2120-2022-05-19) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.11.0...v2.12.0) ##### Features - add build scripts for native image testing in Java 17 ([#​1440](https://togithub.com/googleapis/java-shared-dependencies/issues/1440)) ([#​697](https://togithub.com/googleapis/java-shared-dependencies/issues/697)) ([f10ec4e](https://togithub.com/googleapis/java-shared-dependencies/commit/f10ec4e664d8fde868effe366b7182a5fad08dd0)) ##### Dependencies - update gax.version to v2.18.1 ([#​695](https://togithub.com/googleapis/java-shared-dependencies/issues/695)) ([09bc61c](https://togithub.com/googleapis/java-shared-dependencies/commit/09bc61c9152a99bfe87554a07324f15ae6217d6e)) - update google.core.version to v2.7.1 ([#​698](https://togithub.com/googleapis/java-shared-dependencies/issues/698)) ([43de259](https://togithub.com/googleapis/java-shared-dependencies/commit/43de2593f1a6e8fa5e34799364ab683246ddd449)) ### [`v2.11.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​2110-httpsgithubcomgoogleapisjava-shared-dependenciescomparev2100v2110-2022-05-18) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.10.0...v2.11.0) ##### Features - next release from main branch is 2.11.0 ([#​674](https://togithub.com/googleapis/java-shared-dependencies/issues/674)) ([611e3b7](https://togithub.com/googleapis/java-shared-dependencies/commit/611e3b7c50108a71efc94415166b85d2bf8647e5)) ##### Dependencies - update dependency com.fasterxml.jackson:jackson-bom to v2.13.3 ([#​689](https://togithub.com/googleapis/java-shared-dependencies/issues/689)) ([03897e3](https://togithub.com/googleapis/java-shared-dependencies/commit/03897e30a71f8f1aa37233da2433ee5afccc1d61)) - update dependency com.google.api-client:google-api-client-bom to v1.34.1 ([#​685](https://togithub.com/googleapis/java-shared-dependencies/issues/685)) ([9bc0557](https://togithub.com/googleapis/java-shared-dependencies/commit/9bc0557d8ce2f3d8dc7c8ffafdd36fd4c03e2df5)) - update dependency com.google.api:api-common to v2.2.0 ([#​690](https://togithub.com/googleapis/java-shared-dependencies/issues/690)) ([47a8736](https://togithub.com/googleapis/java-shared-dependencies/commit/47a87365e51f73132b15b054d85f8c9baa8e89f6)) - update dependency com.google.auth:google-auth-library-bom to v1.7.0 ([#​691](https://togithub.com/googleapis/java-shared-dependencies/issues/691)) ([ec6aab7](https://togithub.com/googleapis/java-shared-dependencies/commit/ec6aab72eaed43574efe47a696bba6a612f161bb)) - update dependency com.google.errorprone:error_prone_annotations to v2.13.1 ([#​672](https://togithub.com/googleapis/java-shared-dependencies/issues/672)) ([8c7e530](https://togithub.com/googleapis/java-shared-dependencies/commit/8c7e530d3c7170b2fb76cc27a05164524ba4e00b)) - update dependency com.google.http-client:google-http-client-bom to v1.41.8 ([#​684](https://togithub.com/googleapis/java-shared-dependencies/issues/684)) ([1305356](https://togithub.com/googleapis/java-shared-dependencies/commit/1305356775247dbb641b60654ac56da43513088e)) - update dependency com.google.protobuf:protobuf-bom to v3.20.1 ([#​678](https://togithub.com/googleapis/java-shared-dependencies/issues/678)) ([3e6d4a1](https://togithub.com/googleapis/java-shared-dependencies/commit/3e6d4a1a8e5d45723071a62c99bb1ab87d2b2b84)) - update dependency io.grpc:grpc-bom to v1.46.0 ([#​680](https://togithub.com/googleapis/java-shared-dependencies/issues/680)) ([b8a052b](https://togithub.com/googleapis/java-shared-dependencies/commit/b8a052b75a1bc2703500b4f31c5c6dac887ab8be)) - update dependency org.checkerframework:checker-qual to v3.22.0 ([#​683](https://togithub.com/googleapis/java-shared-dependencies/issues/683)) ([b0a30cd](https://togithub.com/googleapis/java-shared-dependencies/commit/b0a30cdecae8dcfb3a6d36e3f194c39a0086673e)) - update gax.version to v2.17.0 ([#​687](https://togithub.com/googleapis/java-shared-dependencies/issues/687)) ([e0e89ea](https://togithub.com/googleapis/java-shared-dependencies/commit/e0e89eade481effc723c9c7261f2ebf4e5883621)) - update gax.version to v2.18.0 ([#​692](https://togithub.com/googleapis/java-shared-dependencies/issues/692)) ([9536612](https://togithub.com/googleapis/java-shared-dependencies/commit/9536612c77af1e4d912c5b63515ea6f750e53810)) - update google.core.version to v2.6.1 ([#​671](https://togithub.com/googleapis/java-shared-dependencies/issues/671)) ([e3d1aeb](https://togithub.com/googleapis/java-shared-dependencies/commit/e3d1aebed31f8e91109d5865afd9525ac3595c90)) - update google.core.version to v2.7.0 ([#​693](https://togithub.com/googleapis/java-shared-dependencies/issues/693)) ([2171677](https://togithub.com/googleapis/java-shared-dependencies/commit/2171677e16190de9f37dc16c924d829ea8ccd86c)) - update iam.version to v1.3.2 ([#​673](https://togithub.com/googleapis/java-shared-dependencies/issues/673)) ([9882baa](https://togithub.com/googleapis/java-shared-dependencies/commit/9882baa3ecc8d7584788af1916f0d8c5ec670b5c)) - update iam.version to v1.3.3 ([#​679](https://togithub.com/googleapis/java-shared-dependencies/issues/679)) ([9fe34c8](https://togithub.com/googleapis/java-shared-dependencies/commit/9fe34c89eabed5eeebad986bffeeeb64dbbc38c1)) - update iam.version to v1.3.4 ([#​686](https://togithub.com/googleapis/java-shared-dependencies/issues/686)) ([4e95b3a](https://togithub.com/googleapis/java-shared-dependencies/commit/4e95b3a1d4302812338c220df316391c19ef7473)) - update opencensus.version to v0.31.1 ([#​682](https://togithub.com/googleapis/java-shared-dependencies/issues/682)) ([5d25746](https://togithub.com/googleapis/java-shared-dependencies/commit/5d25746bc6c9329b240204cbe7b83e2fee4c6cb3))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index afb192dd433f..80f229cd0355 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.10.0 + 2.12.0 pom import @@ -83,6 +83,11 @@ opencensus-contrib-grpc-util ${opencensus.version} + + io.perfmark + perfmark-api + 0.25.0 +
    From 847c9cb21146daee8e492eefbb7e2346a606d967 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 24 May 2022 03:48:31 +0000 Subject: [PATCH 0705/1979] chore(main): release 2.7.0 (#876) :robot: I have created a release *beep* *boop* --- ## [2.7.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.4...v2.7.0) (2022-05-24) ### Features * add build scripts for native image testing in Java 17 ([#1440](https://github.com/googleapis/java-spanner-jdbc/issues/1440)) ([#875](https://github.com/googleapis/java-spanner-jdbc/issues/875)) ([870c56c](https://github.com/googleapis/java-spanner-jdbc/commit/870c56ccc1d4bcc270f312197b7ea71800a34393)) ### Dependencies * bump Spanner to 6.23.3 ([#862](https://github.com/googleapis/java-spanner-jdbc/issues/862)) ([25687c4](https://github.com/googleapis/java-spanner-jdbc/commit/25687c4575345c2dae25dab08d92eca7d8cf99de)), closes [#788](https://github.com/googleapis/java-spanner-jdbc/issues/788) * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.12.0 ([#874](https://github.com/googleapis/java-spanner-jdbc/issues/874)) ([0b381fa](https://github.com/googleapis/java-spanner-jdbc/commit/0b381faa85a35a463bf967b04f4ebecad58ae66f)) * update opencensus.version to v0.31.1 ([#865](https://github.com/googleapis/java-spanner-jdbc/issues/865)) ([c5742d9](https://github.com/googleapis/java-spanner-jdbc/commit/c5742d9a49a2af793ef3ff30ec0a0aee780998cb)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 11d150942f48..97e9387af19f 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.7.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.4...v2.7.0) (2022-05-24) + + +### Features + +* add build scripts for native image testing in Java 17 ([#1440](https://github.com/googleapis/java-spanner-jdbc/issues/1440)) ([#875](https://github.com/googleapis/java-spanner-jdbc/issues/875)) ([600e401](https://github.com/googleapis/java-spanner-jdbc/commit/600e4017e0b2e52e7a2f42ffca88b1326be03a31)) + + +### Dependencies + +* bump Spanner to 6.23.3 ([#862](https://github.com/googleapis/java-spanner-jdbc/issues/862)) ([b7b8efa](https://github.com/googleapis/java-spanner-jdbc/commit/b7b8efa80cdef9a827c85d469176463001c14b94)), closes [#788](https://github.com/googleapis/java-spanner-jdbc/issues/788) +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.12.0 ([#874](https://github.com/googleapis/java-spanner-jdbc/issues/874)) ([d403f54](https://github.com/googleapis/java-spanner-jdbc/commit/d403f5414cf593e239140f5bbf89b06608167fbf)) +* update opencensus.version to v0.31.1 ([#865](https://github.com/googleapis/java-spanner-jdbc/issues/865)) ([61ba9be](https://github.com/googleapis/java-spanner-jdbc/commit/61ba9be15018c198a00d8f2e69121470c3da2ce0)) + ### [2.6.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.3...v2.6.4) (2022-04-21) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 80f229cd0355..2deb47a7d356 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.6.5-SNAPSHOT + 2.7.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 680607bb4cb9..086fcdf0eef8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.5-SNAPSHOT + 2.7.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7e376e167ea9..560c695cc53b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.6.4:2.6.5-SNAPSHOT +google-cloud-spanner-jdbc:2.7.0:2.7.0 From 063c1c6112766bda389a5157cf70fd879cfc11f2 Mon Sep 17 00:00:00 2001 From: ansh0l Date: Wed, 25 May 2022 11:16:06 +0530 Subject: [PATCH 0706/1979] chore: change repo maintainer (#877) --- java-spanner-jdbc/.github/blunderbuss.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml index 4ad6c6606496..5e0aa64f7251 100644 --- a/java-spanner-jdbc/.github/blunderbuss.yml +++ b/java-spanner-jdbc/.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: - - ansh0l + - rajatbhatta assign_prs_by: - labels: - samples From 61c100d74acad90921d15fcdd1e1e9b0084b095e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 25 May 2022 07:48:15 +0200 Subject: [PATCH 0707/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.0 (#880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource 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.6.4` -> `2.7.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.0/compatibility-slim/2.6.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.0/confidence-slim/2.6.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​270-httpsgithubcomgoogleapisjava-spanner-jdbccomparev264v270-2022-05-24) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.4...v2.7.0) ##### Features - add build scripts for native image testing in Java 17 ([#​1440](https://togithub.com/googleapis/java-spanner-jdbc/issues/1440)) ([#​875](https://togithub.com/googleapis/java-spanner-jdbc/issues/875)) ([870c56c](https://togithub.com/googleapis/java-spanner-jdbc/commit/870c56ccc1d4bcc270f312197b7ea71800a34393)) ##### Dependencies - bump Spanner to 6.23.3 ([#​862](https://togithub.com/googleapis/java-spanner-jdbc/issues/862)) ([25687c4](https://togithub.com/googleapis/java-spanner-jdbc/commit/25687c4575345c2dae25dab08d92eca7d8cf99de)), closes [#​788](https://togithub.com/googleapis/java-spanner-jdbc/issues/788) - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.12.0 ([#​874](https://togithub.com/googleapis/java-spanner-jdbc/issues/874)) ([0b381fa](https://togithub.com/googleapis/java-spanner-jdbc/commit/0b381faa85a35a463bf967b04f4ebecad58ae66f)) - update opencensus.version to v0.31.1 ([#​865](https://togithub.com/googleapis/java-spanner-jdbc/issues/865)) ([c5742d9](https://togithub.com/googleapis/java-spanner-jdbc/commit/c5742d9a49a2af793ef3ff30ec0a0aee780998cb)) ##### [2.6.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.3...v2.6.4) (2022-04-21) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#​798](https://togithub.com/googleapis/java-spanner-jdbc/issues/798)) ([ec910d0](https://togithub.com/googleapis/java-spanner-jdbc/commit/ec910d04537fa0ab7dae8d02cc80a69ef4dbc90f)) ##### [2.6.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.2...v2.6.3) (2022-03-29) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.9.0 ([#​789](https://togithub.com/googleapis/java-spanner-jdbc/issues/789)) ([7e02773](https://togithub.com/googleapis/java-spanner-jdbc/commit/7e02773d1b3c1347fe24b3eda51de7a098b64f61)) ##### [2.6.2](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.1...v2.6.2) (2022-03-14) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.21.2 ([#​783](https://togithub.com/googleapis/java-spanner-jdbc/issues/783)) ([12ebc9d](https://togithub.com/googleapis/java-spanner-jdbc/commit/12ebc9dd5d1fbdc41f11c4f378fec206c1eb7e3f)) ##### [2.6.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.6.0...v2.6.1) (2022-03-02) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.8.0 ([#​770](https://togithub.com/googleapis/java-spanner-jdbc/issues/770)) ([d4e7132](https://togithub.com/googleapis/java-spanner-jdbc/commit/d4e71325c2603bfda3a8b1114b2027f8557e51ad))
    --- ### Configuration 📅 **Schedule**: 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, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b7f0e754d3c9..bdb3cb97d599 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.6.4 + 2.7.0 From b42432623bfd848b6618cb6048dfb73d8834bbaa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 May 2022 11:20:36 -0400 Subject: [PATCH 0708/1979] chore(main): release 2.7.1-SNAPSHOT (#878) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2deb47a7d356..42fcdf9dbd59 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.0 + 2.7.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 086fcdf0eef8..b83b0dcf2487 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.0 + 2.7.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 560c695cc53b..b6ff7ab7991e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.0:2.7.0 +google-cloud-spanner-jdbc:2.7.0:2.7.1-SNAPSHOT From 0abe2b54bf1c7847d3a180438626c817dc654ecf Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 27 May 2022 19:02:18 +0200 Subject: [PATCH 0709/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.25.2 (#881) 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.23.3` -> `6.25.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.25.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.25.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.25.4/compatibility-slim/6.23.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.25.4/confidence-slim/6.23.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. ⚠ **Warning**: custom changes will be lost. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- .../com/google/cloud/spanner/jdbc/JdbcDriverTest.java | 4 +++- .../PostgreSQL/ITScriptTest_TestInvalidStatements.sql | 10 ---------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 42fcdf9dbd59..f8dfba011bd0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.23.3 + 6.25.2 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index dd988ca7107d..36c97fa5e44f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -132,7 +132,9 @@ public void testConnectWithCredentialsAndOAuthToken() { server.getPort(), TEST_KEY_PATH, "some-token"))) { fail("missing expected exception"); } catch (SQLException e) { - assertThat(e.getMessage()).contains("Cannot specify both credentials and an OAuth token"); + assertThat(e.getMessage()) + .contains( + "Specify only one of credentialsUrl, encodedCredentials, credentialsProvider and OAuth token"); } } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestInvalidStatements.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestInvalidStatements.sql index 4dd5e7bde89a..dc22a64a7398 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestInvalidStatements.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestInvalidStatements.sql @@ -17,16 +17,6 @@ /* * Script for testing invalid/unrecognized statements */ --- EXPLAIN statement -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: EXPLAIN' -EXPLAIN SELECT * - FROM Singers; - --- EXPLAIN ANALYZE statement -@EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: EXPLAIN ANALYZE' -EXPLAIN ANALYZE SELECT * - FROM Singers; - -- SET unknown property @EXPECT EXCEPTION INVALID_ARGUMENT 'INVALID_ARGUMENT: Unknown statement: SET some_property' SET some_property='value'; From 4f1e33b6eaf28a6e40e5897bdcffc96bc9bd4a42 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 May 2022 17:20:12 +0000 Subject: [PATCH 0710/1979] chore(main): release 2.7.1 (#883) :robot: I have created a release *beep* *boop* --- ### [2.7.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.0...v2.7.1) (2022-05-27) ### Dependencies * update dependency com.google.cloud:google-cloud-spanner-bom to v6.25.2 ([#881](https://github.com/googleapis/java-spanner-jdbc/issues/881)) ([0abe2b5](https://github.com/googleapis/java-spanner-jdbc/commit/0abe2b54bf1c7847d3a180438626c817dc654ecf)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 97e9387af19f..4ed9459fcb62 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [2.7.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.0...v2.7.1) (2022-05-27) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.25.2 ([#881](https://github.com/googleapis/java-spanner-jdbc/issues/881)) ([b1980b6](https://github.com/googleapis/java-spanner-jdbc/commit/b1980b68ec73bcf137546d167679bb7ae063cebf)) + ## [2.7.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.6.4...v2.7.0) (2022-05-24) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f8dfba011bd0..ccff3eadc411 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.1-SNAPSHOT + 2.7.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b83b0dcf2487..a0be985d9725 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.1-SNAPSHOT + 2.7.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b6ff7ab7991e..e0285c069319 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.0:2.7.1-SNAPSHOT +google-cloud-spanner-jdbc:2.7.1:2.7.1 From e55ba0db9def31ff1d00d4a0095b7bc908197621 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 May 2022 17:40:12 +0000 Subject: [PATCH 0711/1979] chore(main): release 2.7.2-SNAPSHOT (#884) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ccff3eadc411..579b6fff3757 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.1 + 2.7.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a0be985d9725..49f244019cfb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.1 + 2.7.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e0285c069319..a412c952c3a6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.1:2.7.1 +google-cloud-spanner-jdbc:2.7.1:2.7.2-SNAPSHOT From bb3bb41d1ea1d5eabd76b3775b81ba63ecf43380 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 31 May 2022 12:41:41 +0200 Subject: [PATCH 0712/1979] test(deps): update dependency org.mockito:mockito-core to v4.6.0 (#886) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 579b6fff3757..7fcd8ae4ed9b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.5.1 + 4.6.0 2.2 0.31.1 From 7d67fc9084d89183eebac5ba7f270ad16f425723 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 31 May 2022 12:42:21 +0200 Subject: [PATCH 0713/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.1 (#885) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index bdb3cb97d599..33b34939dad6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.0 + 2.7.1 From 7762b3100cd793fd02250437df8ce6b7226991af Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Tue, 31 May 2022 15:36:53 -0400 Subject: [PATCH 0714/1979] deps: google-cloud-spanner-bom 6.25.5 (#887) I'm acting as the RenovateBot. --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7fcd8ae4ed9b..24edda5db663 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.25.2 + 6.25.5 pom import From 6b950398b707f586c2a7d50e0ff44b33ada19567 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 31 May 2022 19:54:55 +0000 Subject: [PATCH 0715/1979] chore(main): release 2.7.2 (#888) :robot: I have created a release *beep* *boop* --- ## [2.7.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.1...v2.7.2) (2022-05-31) ### Dependencies * google-cloud-spanner-bom 6.25.5 ([#887](https://github.com/googleapis/java-spanner-jdbc/issues/887)) ([7762b31](https://github.com/googleapis/java-spanner-jdbc/commit/7762b3100cd793fd02250437df8ce6b7226991af)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4ed9459fcb62..afbcdc646f59 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.1...v2.7.2) (2022-05-31) + + +### Dependencies + +* google-cloud-spanner-bom 6.25.5 ([#887](https://github.com/googleapis/java-spanner-jdbc/issues/887)) ([2ec08bf](https://github.com/googleapis/java-spanner-jdbc/commit/2ec08bf722d68013b72d648c7facf80a7342dafc)) + ### [2.7.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.0...v2.7.1) (2022-05-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 24edda5db663..368f7d4bc78d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.2-SNAPSHOT + 2.7.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 49f244019cfb..bb1a8ff0f67d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.2-SNAPSHOT + 2.7.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a412c952c3a6..06e5d69ad678 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.1:2.7.2-SNAPSHOT +google-cloud-spanner-jdbc:2.7.2:2.7.2 From 84959695990990c03a9bf09f28bf2db6bd6f677e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 31 May 2022 20:10:51 +0000 Subject: [PATCH 0716/1979] chore(main): release 2.7.3-SNAPSHOT (#889) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 368f7d4bc78d..5bf345fb7da1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.2 + 2.7.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index bb1a8ff0f67d..f0985b3f2ee7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.2 + 2.7.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 06e5d69ad678..86d0da330f19 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.2:2.7.2 +google-cloud-spanner-jdbc:2.7.2:2.7.3-SNAPSHOT From 7dcced0eda517c7aa5f7b45af9dba939f566bd61 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Tue, 31 May 2022 17:18:22 -0400 Subject: [PATCH 0717/1979] fix(java): adding resource and reflection configurations for native image testing (#809) * fix(java): adding resource and reflection configurations for native image testing (#809) --- java-spanner-jdbc/.kokoro/build.sh | 4 ++-- java-spanner-jdbc/owlbot.py | 3 ++- java-spanner-jdbc/pom.xml | 14 ++++++++++++++ .../native-image.properties | 3 +++ .../google-cloud-spanner-jdbc/resource-config.json | 9 +++++++++ .../jdbc/it/ITJdbcPreparedStatementTest.java | 11 +++++------ 6 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties create mode 100644 java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/resource-config.json diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 5ca4fd4bcd90..8318273ed097 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -71,12 +71,12 @@ integration) ;; graalvm) # Run Unit and Integration Tests with Native Image - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; graalvm17) # Run Unit and Integration Tests with Native Image - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; samples) diff --git a/java-spanner-jdbc/owlbot.py b/java-spanner-jdbc/owlbot.py index 5beca6a87af0..05f32bb6d596 100644 --- a/java-spanner-jdbc/owlbot.py +++ b/java-spanner-jdbc/owlbot.py @@ -21,5 +21,6 @@ '.github/release-please.yml', '.github/sync-repo-settings.yaml', '.github/blunderbuss.yml', - '.kokoro/nightly/integration.cfg' + '.kokoro/nightly/integration.cfg', + '.kokoro/build.sh' ]) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5bf345fb7da1..d2860960bbdb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -230,6 +230,14 @@ com.google.cloud.spanner.jdbc.JdbcStatementTimeoutTest sponge_log + + + com.google.cloud.spanner.GceTestEnvConfig + + + projects/gcloud-devel/instances/spanner-testing-east1 + +
    @@ -319,6 +327,12 @@ org.apache.maven.plugins maven-dependency-plugin + + org.graalvm.sdk:graal-sdk + com.google.api.grpc:grpc-google-cloud-spanner-v1 + com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1 + com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1 + io.grpc:grpc-alts diff --git a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties new file mode 100644 index 000000000000..f211d3a26461 --- /dev/null +++ b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties @@ -0,0 +1,3 @@ +Args = --initialize-at-build-time==com.google.cloud.spanner.IntegrationTestEnv,\ + com.google.cloud.spanner.jdbc.it.JdbcIntegrationTestEnv,\ + com.google.common.collect.RegularImmutableMap \ No newline at end of file diff --git a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/resource-config.json b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/resource-config.json new file mode 100644 index 000000000000..2a215e4434c5 --- /dev/null +++ b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/resource-config.json @@ -0,0 +1,9 @@ +{ + "resources":{ + "includes":[ + {"pattern":".*.sql"}, + {"pattern":".*.json"}, + {"pattern":".*.txt"} + ] + } +} \ No newline at end of file diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 49491332f7d4..c473b6e96c2b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -35,8 +35,8 @@ import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; -import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.io.StringReader; import java.math.BigDecimal; import java.sql.BatchUpdateException; @@ -54,7 +54,6 @@ import java.util.Arrays; import java.util.Calendar; import java.util.List; -import java.util.Objects; import java.util.Scanner; import java.util.TimeZone; import java.util.UUID; @@ -1106,14 +1105,14 @@ private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedP } private List readValuesFromFile(String filename) { - File file = new File(Objects.requireNonNull(getClass().getResource(filename)).getFile()); StringBuilder builder = new StringBuilder(); - try (Scanner scanner = new Scanner(file)) { + try (InputStream stream = ITJdbcPreparedStatementTest.class.getResourceAsStream(filename)) { + Scanner scanner = new Scanner(stream); while (scanner.hasNextLine()) { String line = scanner.nextLine(); builder.append(line).append("\n"); } - } catch (FileNotFoundException e) { + } catch (IOException e) { throw new RuntimeException(e); } String[] array = builder.toString().split(";"); From 07adc512a57f24277f1bad7cabab3d9de24f4c91 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 Jun 2022 10:15:51 -0400 Subject: [PATCH 0718/1979] chore(main): release 2.7.3 (#890) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index afbcdc646f59..b0302f04ccbc 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.2...v2.7.3) (2022-05-31) + + +### Bug Fixes + +* **java:** adding resource and reflection configurations for native image testing ([#809](https://github.com/googleapis/java-spanner-jdbc/issues/809)) ([6126d4f](https://github.com/googleapis/java-spanner-jdbc/commit/6126d4f55dde76c8b945999008bbee78203a1b75)) + ## [2.7.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.1...v2.7.2) (2022-05-31) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d2860960bbdb..2b9f1a28ea91 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.3-SNAPSHOT + 2.7.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f0985b3f2ee7..671500b54528 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.3-SNAPSHOT + 2.7.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 86d0da330f19..ee89e2ce21d6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.2:2.7.3-SNAPSHOT +google-cloud-spanner-jdbc:2.7.3:2.7.3 From 8d5833546b8e93b0cf7d8aa6b005034a78dd5d06 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 Jun 2022 14:34:11 +0000 Subject: [PATCH 0719/1979] chore(main): release 2.7.4-SNAPSHOT (#892) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2b9f1a28ea91..be56fce5dcd0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.3 + 2.7.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 671500b54528..343468092bdf 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.3 + 2.7.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ee89e2ce21d6..035e3fea3b54 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.3:2.7.3 +google-cloud-spanner-jdbc:2.7.3:2.7.4-SNAPSHOT From 3fcfa1bdf4f25e5c92a30961a37527c129a24677 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 2 Jun 2022 19:48:29 +0200 Subject: [PATCH 0720/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.3 (#891) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 33b34939dad6..9c61a8cda927 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.1 + 2.7.3 From fffd0b7fc5808056e3962bc97fa225c64073e85c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 3 Jun 2022 09:04:58 +0200 Subject: [PATCH 0721/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v25.4.0 (#895) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 501c08391f53..ebe32e886241 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 25.3.0 + 25.4.0 pom import From c2bcdba98487a707351af7e982faaf0abf1593ca Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 3 Jun 2022 09:05:30 +0200 Subject: [PATCH 0722/1979] test(deps): update dependency org.mockito:mockito-core to v4.6.1 (#894) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index be56fce5dcd0..f174ab468360 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.6.0 + 4.6.1 2.2 0.31.1 From 3888e68554e4a4f03f252252088eafe8aa874136 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 13 Jun 2022 19:04:23 +0200 Subject: [PATCH 0723/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.0 (#897) 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.4.0` -> `1.5.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.0/compatibility-slim/1.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.0/confidence-slim/1.4.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.5.0`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​150-httpsgithubcomgoogleapisjava-shared-configcomparev140v150-2022-06-10) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.4.0...v1.5.0) ##### Features - add build scripts for native image testing in Java 17 ([#​1440](https://togithub.com/googleapis/java-shared-config/issues/1440)) ([#​475](https://togithub.com/googleapis/java-shared-config/issues/475)) ([e4dfc1b](https://togithub.com/googleapis/java-shared-config/commit/e4dfc1ba29295158c78c8fcf94467d2a6a33538a)) - to produce Java 8 compatible bytecode when using JDK 9+ ([2468276](https://togithub.com/googleapis/java-shared-config/commit/2468276145cdfe1ca911b52f765e026e77661a09)) ##### Dependencies - update surefire.version to v3.0.0-m7 ([bbfe663](https://togithub.com/googleapis/java-shared-config/commit/bbfe66393af3e49612c9c1e4334ba39c133ea1d0))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f174ab468360..c25bdb8a7e8f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.4.0 + 1.5.0 From aa6a1b23e1261f3e5b5179753d09b5a2eeaf9d94 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 23 Jun 2022 17:34:11 +0200 Subject: [PATCH 0724/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v2.13.0 (#899) 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/java-shared-dependencies) | `2.12.0` -> `2.13.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.13.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.13.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.13.0/compatibility-slim/2.12.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/2.13.0/confidence-slim/2.12.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v2.13.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​2130-httpsgithubcomgoogleapisjava-shared-dependenciescomparev2120v2130-2022-06-22) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.12.0...v2.13.0) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.35.0 ([#​709](https://togithub.com/googleapis/java-shared-dependencies/issues/709)) ([239f8c3](https://togithub.com/googleapis/java-shared-dependencies/commit/239f8c33a11e233e6af79aee8c7e68cd156a0554)) - update dependency com.google.api-client:google-api-client-bom to v1.35.1 ([#​713](https://togithub.com/googleapis/java-shared-dependencies/issues/713)) ([6559b45](https://togithub.com/googleapis/java-shared-dependencies/commit/6559b45b027dba783a9525d35e32183d78773cbe)) - update dependency com.google.api:api-common to v2.2.1 ([#​710](https://togithub.com/googleapis/java-shared-dependencies/issues/710)) ([650d4c5](https://togithub.com/googleapis/java-shared-dependencies/commit/650d4c5f8c3cfce711257d47280ad773cd2e2414)) - update dependency com.google.errorprone:error_prone_annotations to v2.14.0 ([#​701](https://togithub.com/googleapis/java-shared-dependencies/issues/701)) ([d24730f](https://togithub.com/googleapis/java-shared-dependencies/commit/d24730f78669f80b109e590b903446e5552e3e36)) - update dependency com.google.http-client:google-http-client-bom to v1.42.0 ([#​711](https://togithub.com/googleapis/java-shared-dependencies/issues/711)) ([5168a18](https://togithub.com/googleapis/java-shared-dependencies/commit/5168a181722128d434a0d0d2ab5cc485686bbc78)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.34.0 ([#​708](https://togithub.com/googleapis/java-shared-dependencies/issues/708)) ([620336e](https://togithub.com/googleapis/java-shared-dependencies/commit/620336e6733e2017116e5e8a7b403b183a728bc1)) - update dependency com.google.oauth-client:google-oauth-client-bom to v1.34.1 ([#​712](https://togithub.com/googleapis/java-shared-dependencies/issues/712)) ([a2c18a5](https://togithub.com/googleapis/java-shared-dependencies/commit/a2c18a5bc4152cc9034cec691a29f54a35c38a51)) - update dependency com.google.protobuf:protobuf-bom to v3.21.0 ([#​703](https://togithub.com/googleapis/java-shared-dependencies/issues/703)) ([5f9fe12](https://togithub.com/googleapis/java-shared-dependencies/commit/5f9fe1200b4bdf4c54bf947c21bd3ed02f26f990)) - update dependency com.google.protobuf:protobuf-bom to v3.21.1 ([#​705](https://togithub.com/googleapis/java-shared-dependencies/issues/705)) ([c68edfb](https://togithub.com/googleapis/java-shared-dependencies/commit/c68edfbe7e1993e1112640b867b29aa2fbcf7579)) - update dependency io.grpc:grpc-bom to v1.47.0 ([#​707](https://togithub.com/googleapis/java-shared-dependencies/issues/707)) ([d02918a](https://togithub.com/googleapis/java-shared-dependencies/commit/d02918a0418cd65d1d247f27afb0637f1f8f5666)) - update dependency org.checkerframework:checker-qual to v3.22.1 ([#​706](https://togithub.com/googleapis/java-shared-dependencies/issues/706)) ([545843b](https://togithub.com/googleapis/java-shared-dependencies/commit/545843b492cead230b8cc72a1dae7d4922f33b39)) - update dependency org.checkerframework:checker-qual to v3.22.2 ([#​717](https://togithub.com/googleapis/java-shared-dependencies/issues/717)) ([142852a](https://togithub.com/googleapis/java-shared-dependencies/commit/142852a37140f221197f5c71aed451def353b1e0)) - update gax.version to v2.18.2 ([#​718](https://togithub.com/googleapis/java-shared-dependencies/issues/718)) ([5f8156e](https://togithub.com/googleapis/java-shared-dependencies/commit/5f8156e55c6a07b018a8c5efafa68be781b4288b)) - update google.common-protos.version to v2.9.0 ([#​714](https://togithub.com/googleapis/java-shared-dependencies/issues/714)) ([9e5591e](https://togithub.com/googleapis/java-shared-dependencies/commit/9e5591ec3035350450ecbfebd00e08216433b06c)) - update google.core.version to v2.8.0 ([#​719](https://togithub.com/googleapis/java-shared-dependencies/issues/719)) ([4023c60](https://togithub.com/googleapis/java-shared-dependencies/commit/4023c6063a2c5b5308da531df1a08c90c491965d)) - update iam.version to v1.4.0 ([#​700](https://togithub.com/googleapis/java-shared-dependencies/issues/700)) ([c1097a4](https://togithub.com/googleapis/java-shared-dependencies/commit/c1097a46ab0739b0b7234bc510e4c3d9ce2c2861)) - update iam.version to v1.4.1 ([#​716](https://togithub.com/googleapis/java-shared-dependencies/issues/716)) ([e2dc7c2](https://togithub.com/googleapis/java-shared-dependencies/commit/e2dc7c21c39e007878841e2664d548ec44a72d54))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c25bdb8a7e8f..cae2431f80b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 2.12.0 + 2.13.0 pom import From 8a9aa26edc43e3e08ab18ee703af20b1482079c9 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 27 Jun 2022 19:30:18 +0000 Subject: [PATCH 0725/1979] chore: update dependencies for regapic (#1467) (#901) * chore: update dependencies for regapic * add more dependencies and trigger comment * update goldens * fix indentation * remove duplicate gax-httpjson dependency * remove duplicated dependencies Source-Link: https://github.com/googleapis/synthtool/commit/fa54eb2a78c6ee48613fd33152e2130e949dcbd9 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:1ec28a46062b19135b11178ceee60231e5f5a92dab454e23ae0aab72cd875906 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/common.sh | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index a79f06271b60..f0625e4d9459 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:2567a120ce90fadb6201999b87d649d9f67459de28815ad239bce9ebfaa18a74 -# created: 2022-05-19T15:12:45.278246753Z + digest: sha256:1ec28a46062b19135b11178ceee60231e5f5a92dab454e23ae0aab72cd875906 +# created: 2022-06-27T15:01:06.405564326Z diff --git a/java-spanner-jdbc/.kokoro/common.sh b/java-spanner-jdbc/.kokoro/common.sh index ace89f45a9de..f8f957af1112 100644 --- a/java-spanner-jdbc/.kokoro/common.sh +++ b/java-spanner-jdbc/.kokoro/common.sh @@ -55,4 +55,6 @@ function retry_with_backoff { ## Helper functionss function now() { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n'; } function msg() { println "$*" >&2; } -function println() { printf '%s\n' "$(now) $*"; } \ No newline at end of file +function println() { printf '%s\n' "$(now) $*"; } + +## Helper comment to trigger updated repo dependency release \ No newline at end of file From 6926b634c6370408133dc83b8824bb5d76cca901 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 30 Jun 2022 02:14:25 +0000 Subject: [PATCH 0726/1979] chore: Disable CLIRR checks on releas (#1474) (#903) Source-Link: https://github.com/googleapis/synthtool/commit/7a220e27993a25ab3cda26510d5619d97b6952a9 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:6d4e3a15c62cfdcb823d60e16da7521e7c6fc00eba07c8ff12e4de9924a57d28 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/release/stage.sh | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index f0625e4d9459..a454a61e8dc2 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:1ec28a46062b19135b11178ceee60231e5f5a92dab454e23ae0aab72cd875906 -# created: 2022-06-27T15:01:06.405564326Z + digest: sha256:6d4e3a15c62cfdcb823d60e16da7521e7c6fc00eba07c8ff12e4de9924a57d28 +# created: 2022-06-29T23:17:33.110417661Z diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 77dc4e8f0f3a..1dba8de10857 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -32,6 +32,7 @@ retry_with_backoff 3 10 \ mvn clean deploy -B \ --settings ${MAVEN_SETTINGS_FILE} \ -DskipTests=true \ + -Dclirr.skip=true \ -DperformRelease=true \ -Dgpg.executable=gpg \ -Dgpg.passphrase=${GPG_PASSPHRASE} \ @@ -42,4 +43,4 @@ then mvn nexus-staging:release -B \ -DperformRelease=true \ --settings=settings.xml -fi \ No newline at end of file +fi From 176420825d328c13ac62d6712a7d2601095a5a2a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 1 Jul 2022 17:30:28 +0000 Subject: [PATCH 0727/1979] chore(main): release 2.7.4 (#900) :robot: I have created a release *beep* *boop* --- ## [2.7.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.3...v2.7.4) (2022-06-30) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v2.13.0 ([#899](https://github.com/googleapis/java-spanner-jdbc/issues/899)) ([aa6a1b2](https://github.com/googleapis/java-spanner-jdbc/commit/aa6a1b23e1261f3e5b5179753d09b5a2eeaf9d94)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b0302f04ccbc..eee7cceefd49 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.3...v2.7.4) (2022-06-30) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.13.0 ([#899](https://github.com/googleapis/java-spanner-jdbc/issues/899)) ([0286068](https://github.com/googleapis/java-spanner-jdbc/commit/02860683f00678804c58ae2c0b213bc934441397)) + ## [2.7.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.2...v2.7.3) (2022-05-31) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cae2431f80b5..206411a41d1f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.4-SNAPSHOT + 2.7.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 343468092bdf..d6a31d44c61e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.4-SNAPSHOT + 2.7.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 035e3fea3b54..d6d88ff1fd9e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.3:2.7.4-SNAPSHOT +google-cloud-spanner-jdbc:2.7.4:2.7.4 From 5ee683492c5b4ca8da953cfb24175d886e10b1f3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 1 Jul 2022 17:56:27 +0000 Subject: [PATCH 0728/1979] chore(main): release 2.7.5-SNAPSHOT (#904) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 206411a41d1f..9b2818571387 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.4 + 2.7.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d6a31d44c61e..3d5e03c0957d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.4 + 2.7.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d6d88ff1fd9e..155cb99b192c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.4:2.7.4 +google-cloud-spanner-jdbc:2.7.4:2.7.5-SNAPSHOT From b5a79da2e71ea58c042a7b3c17b006db0533872e Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 2 Jul 2022 12:06:55 +0200 Subject: [PATCH 0729/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.4 (#906) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9c61a8cda927..d84e1a193665 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.3 + 2.7.4 From ecdb87b1ce78ed297d9fc66f1b78e5bd3b2a6301 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 6 Jul 2022 19:01:06 +0200 Subject: [PATCH 0730/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.1 (#905) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9b2818571387..03d041fbac24 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.0 + 1.5.1 From ab0b78d469e6d5a60e57a47569622a971601aea4 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Mon, 11 Jul 2022 15:42:33 -0400 Subject: [PATCH 0731/1979] chore: mark native image checks as required (#902) --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index f9649fb057e9..19bc1242ab7d 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -38,6 +38,8 @@ branchProtectionRules: - "Kokoro - Test: Integration" - "cla/google" - OwlBot Post Processor + - 'Kokoro - Test: Java GraalVM Native Image' + - 'Kokoro - Test: Java 17 GraalVM Native Image' # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `main` From f3e6be4409f7ec12c0a9284e352de0532999a3c1 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Mon, 18 Jul 2022 11:35:29 -0400 Subject: [PATCH 0732/1979] fix: pr to troubleshoot native image tests (#912) * fix: pr to troubleshoot native image tests * use shared-config 1.5.0 --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 03d041fbac24..9b2818571387 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.1 + 1.5.0 From c1eef2fe99b863af07f650e24e87900debc0150a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 18 Jul 2022 22:06:13 +0200 Subject: [PATCH 0733/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.0 (#913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) ([source](https://togithub.com/apache/maven-project-info-reports-plugin)) | `3.3.0` -> `3.4.0` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.0/compatibility-slim/3.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.0/confidence-slim/3.3.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9b2818571387..729f2c7a2d32 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -396,7 +396,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.3.0 + 3.4.0 From ecb65b6317d56fcfa85db0b48feb561b40eea1cd Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 18 Jul 2022 20:52:13 +0000 Subject: [PATCH 0734/1979] build: marking dependencies (8) non-required (#1472) (#911) Co-authored-by: Anthonios Partheniou Source-Link: https://github.com/googleapis/synthtool/commit/72c64b725262e1c7e5e28f3f07681afc77347dab Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:b2e8f445ca0e605d4bbefbfdbdf7335692d75cf1647af62243828dcc0ea4e690 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.github/workflows/ci.yaml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index a454a61e8dc2..6bf3e92e78e7 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:6d4e3a15c62cfdcb823d60e16da7521e7c6fc00eba07c8ff12e4de9924a57d28 -# created: 2022-06-29T23:17:33.110417661Z + digest: sha256:b2e8f445ca0e605d4bbefbfdbdf7335692d75cf1647af62243828dcc0ea4e690 +# created: 2022-07-14T21:08:10.768472192Z diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 83ef7f9c2cf3..e3bb26e37719 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -39,6 +39,8 @@ jobs: windows: runs-on: windows-latest steps: + - name: Support longpaths + run: git config --system core.longpaths true - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: From 2dafbf0bb874c6ca96eb5d27bb4b21fbe574ae8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 19 Jul 2022 01:24:13 +0200 Subject: [PATCH 0735/1979] test: modify tests to use correct quote escaping (#909) Some tests used invalid escaping of quotes in PostgreSQL queries. They assumed that a quote in a quoted string could be escaped by prefixing it with a backslash. This is however not allowed in PostgreSQL, and instead the quote must be escaped by including the same quote twice in the string. The Spanner Java client library contained a bug that allowed the backslash-escaped quotes to be accepted. This bug has been fixed in 6.25.7 and these tests therefore need to be modified to be able to update to that version. Fixes the build error in #898 --- .../spanner/jdbc/JdbcParameterStoreTest.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 03aa1dde9f4f..d886598ec46a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -895,35 +895,35 @@ public void testPostgresDialectConvertPositionalParametersToNamedParameters() { parser.convertPositionalParametersToNamedParameters('?', "?'?test?\"?test?\"?'?") .sqlWithNamedParameters); assertEquals( - "$1'?it\\'?s'$2", - parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s'?") + "$1'?it''?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?it''?s'?") .sqlWithNamedParameters); assertEquals( "$1'?it\\\"?s'$2", parser.convertPositionalParametersToNamedParameters('?', "?'?it\\\"?s'?") .sqlWithNamedParameters); assertEquals( - "$1\"?it\\\"?s\"$2", - parser.convertPositionalParametersToNamedParameters('?', "?\"?it\\\"?s\"?") + "$1\"?it\"\"?s\"$2", + parser.convertPositionalParametersToNamedParameters('?', "?\"?it\"\"?s\"?") .sqlWithNamedParameters); assertEquals( - "$1'''?it\\'?s'''$2", - parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s'''?") + "$1'''?it''?s'''$2", + parser.convertPositionalParametersToNamedParameters('?', "?'''?it''?s'''?") .sqlWithNamedParameters); assertEquals( - "$1\"\"\"?it\\\"?s\"\"\"$2", - parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") + "$1\"\"\"?it\"\"?s\"\"\"$2", + parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\"\"?s\"\"\"?") .sqlWithNamedParameters); // PostgreSQL allows newlines inside string literals. assertEquals( - "$1'?it\\'?s \n ?it\\'?s'$2", - parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s \n ?it\\'?s'?") + "$1'?it''?s \n ?it''?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'?it''?s \n ?it''?s'?") .sqlWithNamedParameters); assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); assertEquals( - "$1'''?it\\'?s \n ?it\\'?s'$2", - parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s \n ?it\\'?s'?") + "$1'''?it''?s \n ?it''?s'$2", + parser.convertPositionalParametersToNamedParameters('?', "?'''?it''?s \n ?it''?s'?") .sqlWithNamedParameters); assertEquals( From 523395dd0a4552e9e814375829dc91ae788f0b5d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 19 Jul 2022 04:26:11 +0200 Subject: [PATCH 0736/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26 (#907) 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)) | `25.4.0` -> `26.0.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.0.0/compatibility-slim/25.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.0.0/confidence-slim/25.4.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ebe32e886241..a7dacec26deb 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 25.4.0 + 26.0.0 pom import From 519c6013d270bb18b74ad94550cad1cb77e8aeb9 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 19 Jul 2022 13:38:16 +0000 Subject: [PATCH 0737/1979] ci: update template so GAPIC_AUTO repos do not require special approvers for Java code (#1494) (#916) Source-Link: https://github.com/googleapis/synthtool/commit/da89e53878d92467eb648c610e64f94a614915cc Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:04f254abfe5f47fe73ae6f91d68d55c3b76e722a4943066c3bb0ce03573b4ad9 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.github/CODEOWNERS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 6bf3e92e78e7..6610882f836f 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:b2e8f445ca0e605d4bbefbfdbdf7335692d75cf1647af62243828dcc0ea4e690 -# created: 2022-07-14T21:08:10.768472192Z + digest: sha256:04f254abfe5f47fe73ae6f91d68d55c3b76e722a4943066c3bb0ce03573b4ad9 +# created: 2022-07-18T21:44:23.94208526Z diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index da6403b346e0..8ec690b49dcc 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -6,7 +6,10 @@ # The @googleapis/api-spanner-java is the default owner for changes in this repo * @googleapis/yoshi-java @googleapis/api-spanner-java + +# for handwritten libraries, keep codeowner_team in .repo-metadata.json as owner **/*.java @googleapis/api-spanner-java + # The java-samples-reviewers team is the default owner for samples changes samples/**/*.java @googleapis/java-samples-reviewers From 66bfec893ed3ca5fe69ff1b5e11d393b3405e6bc Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 19 Jul 2022 20:10:15 +0200 Subject: [PATCH 0738/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3 (#917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-deploy-plugin](https://maven.apache.org/plugins/) | `2.8.2` -> `3.0.0` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-deploy-plugin/3.0.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-deploy-plugin/3.0.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-deploy-plugin/3.0.0/compatibility-slim/2.8.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-deploy-plugin/3.0.0/confidence-slim/2.8.2)](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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 96829cbd057f..9b3403e44c4f 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -38,7 +38,7 @@ org.apache.maven.plugins maven-deploy-plugin - 2.8.2 + 3.0.0 true From 51712cf85d50f41c3ece18057a050362b1eb0f8a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 19 Jul 2022 18:34:14 +0000 Subject: [PATCH 0739/1979] fix: enable longpaths support for windows test (#1485) (#908) Source-Link: https://github.com/googleapis/synthtool/commit/73365620c41d96e97ff474b2c4d39b890ad51967 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:d4b80feffe1579818cdc39466152e9de95789a193408506cd4a1ffbe8804dc00 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 6610882f836f..d99cbbc27f08 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -14,4 +14,4 @@ docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest digest: sha256:04f254abfe5f47fe73ae6f91d68d55c3b76e722a4943066c3bb0ce03573b4ad9 -# created: 2022-07-18T21:44:23.94208526Z +# created: 2022-07-18T21:44:23.94208526Z \ No newline at end of file From d6f2fd979eaeef500a24f70adee531d2ae0621de Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 20 Jul 2022 20:24:12 +0200 Subject: [PATCH 0740/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.27.0 (#898) 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.25.5` -> `6.27.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.27.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.27.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.27.0/compatibility-slim/6.25.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.27.0/confidence-slim/6.25.5)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.27.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6270-httpsgithubcomgoogleapisjava-spannercomparev6260v6270-2022-07-19) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.26.0...v6.27.0) ##### Features - Adding new fields for Instance Create Time and Update Time ([#​1913](https://togithub.com/googleapis/java-spanner/issues/1913)) ([2c71e02](https://togithub.com/googleapis/java-spanner/commit/2c71e0233333803f271931f6ef471b7eacfa52d7)) ##### Dependencies - update dependency com.google.cloud:google-cloud-monitoring to v3.3.1 ([#​1933](https://togithub.com/googleapis/java-spanner/issues/1933)) ([e3d646b](https://togithub.com/googleapis/java-spanner/commit/e3d646bae4abf2215d44f282d4faf722c638b823)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.13 ([#​1944](https://togithub.com/googleapis/java-spanner/issues/1944)) ([765d11b](https://togithub.com/googleapis/java-spanner/commit/765d11b2e5ee7b1f12d2d27a139f92efbc1caa07)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.13 ([#​1945](https://togithub.com/googleapis/java-spanner/issues/1945)) ([0da75b8](https://togithub.com/googleapis/java-spanner/commit/0da75b819d6e9d0f7c6850d77656e46b76ddad6d)) - update dependency org.graalvm.sdk:graal-sdk to v22.2.0 ([#​1953](https://togithub.com/googleapis/java-spanner/issues/1953)) ([c7f1040](https://togithub.com/googleapis/java-spanner/commit/c7f1040d849901194e5672b270ccee7fbc695d17)) ### [`v6.26.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6260-httpsgithubcomgoogleapisjava-spannercomparev6257v6260-2022-07-13) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.25.7...v6.26.0) ##### Features - Adding two new fields for Instance create_time and update_time ([#​1908](https://togithub.com/googleapis/java-spanner/issues/1908)) ([00b3817](https://togithub.com/googleapis/java-spanner/commit/00b38178e851401e293aa457f7ba5ea593a7b7c5)) - changes to support data, timestamp and arrays in IT tests ([#​1840](https://togithub.com/googleapis/java-spanner/issues/1840)) ([c667653](https://togithub.com/googleapis/java-spanner/commit/c667653ec380dccbf205e7b419843da11cf4155a)) - Error Details Improvement ([c8a2184](https://togithub.com/googleapis/java-spanner/commit/c8a2184c51cc92ec35c759eff68e614fc78fb2e6)) - Error Details Improvement ([#​1929](https://togithub.com/googleapis/java-spanner/issues/1929)) ([c8a2184](https://togithub.com/googleapis/java-spanner/commit/c8a2184c51cc92ec35c759eff68e614fc78fb2e6)) ##### Bug Fixes - enable longpaths support for windows test ([#​1485](https://togithub.com/googleapis/java-spanner/issues/1485)) ([#​1946](https://togithub.com/googleapis/java-spanner/issues/1946)) ([fd0b845](https://togithub.com/googleapis/java-spanner/commit/fd0b84523535ba583a1b56acbea98835191daa06)) ##### Dependencies - update dependency com.google.cloud:google-cloud-trace to v2.3.0 ([#​1934](https://togithub.com/googleapis/java-spanner/issues/1934)) ([2813eb2](https://togithub.com/googleapis/java-spanner/commit/2813eb21c9f168e8dea149e40dac188933c7e2db)) ### [`v6.25.7`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6257-httpsgithubcomgoogleapisjava-spannercomparev6256v6257-2022-06-30) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.25.6...v6.25.7) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.13.0 ([#​1924](https://togithub.com/googleapis/java-spanner/issues/1924)) ([dde5ee8](https://togithub.com/googleapis/java-spanner/commit/dde5ee8c5fcef36b415929aa32931dc811036eb4)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.12 ([#​1906](https://togithub.com/googleapis/java-spanner/issues/1906)) ([1800cd9](https://togithub.com/googleapis/java-spanner/commit/1800cd917c26934768296253cbbcf7c91c54afef)) ### [`v6.25.6`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6256-httpsgithubcomgoogleapisjava-spannercomparev6255v6256-2022-06-22) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.25.5...v6.25.6) ##### Bug Fixes - PostgreSQL parser should not treat \ as an escape char ([#​1921](https://togithub.com/googleapis/java-spanner/issues/1921)) ([260bbe3](https://togithub.com/googleapis/java-spanner/commit/260bbe3cb78e0583975d7085ae5a95dbfd3efd73)), closes [#​1920](https://togithub.com/googleapis/java-spanner/issues/1920) ##### Documentation - **sample:** relocate native image sample from old repo ([#​1758](https://togithub.com/googleapis/java-spanner/issues/1758)) ([ef187f4](https://togithub.com/googleapis/java-spanner/commit/ef187f4fccaf1c5550e9f6795228e6c7361030db)) ##### Dependencies - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.11 ([#​1907](https://togithub.com/googleapis/java-spanner/issues/1907)) ([01f8a07](https://togithub.com/googleapis/java-spanner/commit/01f8a07c64358368615d8c729c7c47c4b2c687fd)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.12 ([#​1918](https://togithub.com/googleapis/java-spanner/issues/1918)) ([be8b50b](https://togithub.com/googleapis/java-spanner/commit/be8b50b56e51245d941c52445498600025e26ba9))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 729f2c7a2d32..8f4cde5ff89e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.25.5 + 6.27.0 pom import From 0cab4c81ac1935133be816c6897eef5454bc440f Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Tue, 2 Aug 2022 15:28:39 -0400 Subject: [PATCH 0741/1979] ci: temporarily using native-maven-plugin 0.9.11 for testing (#915) ci: temporarily using native-maven-plugin 0.9.11 for testing --- java-spanner-jdbc/.kokoro/build.sh | 8 ++-- java-spanner-jdbc/pom.xml | 62 ++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 8318273ed097..f66c99f85e56 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -70,13 +70,13 @@ integration) RETURN_CODE=$? ;; graalvm) - # Run Unit and Integration Tests with Native Image - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + # Run Unit and Integration Tests with Native Image. Use native-maven-plugin until https://github.com/graalvm/native-build-tools/issues/279 is fixed. + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.11 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; graalvm17) - # Run Unit and Integration Tests with Native Image - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + # Run Unit and Integration Tests with Native Image. Use native-maven-plugin 0.9.11 until https://github.com/graalvm/native-build-tools/issues/279 is fixed. + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.11 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; samples) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8f4cde5ff89e..6a3d1cbf462a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -349,6 +349,68 @@ + + native-0.9.11 + + + + + org.junit.vintage + junit-vintage-engine + 5.8.2 + test + + + + org.graalvm.buildtools + junit-platform-native + 0.9.11 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.22.2 + + + + + **/IT*.java + + **/*ClientTest.java + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.11 + true + + + test-native + + test + + test + + + + + --no-fallback + + + + + + + shade From 7fdf57e7337421fe1fd0bf6cf0f2cb6404b0d7ce Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 3 Aug 2022 03:40:17 +0200 Subject: [PATCH 0742/1979] deps: update dependency org.graalvm.buildtools:junit-platform-native to v0.9.13 (#922) 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.graalvm.buildtools:junit-platform-native](https://togithub.com/graalvm/native-build-tools) | `0.9.11` -> `0.9.13` | [![age](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.13/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.13/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.13/compatibility-slim/0.9.11)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.13/confidence-slim/0.9.11)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    graalvm/native-build-tools ### [`v0.9.13`](https://togithub.com/graalvm/native-build-tools/releases/tag/0.9.13) [Compare Source](https://togithub.com/graalvm/native-build-tools/compare/0.9.12...0.9.13) #### What's Changed Read what's new in the [documentation](https://graalvm.github.io/native-build-tools/latest/index.html#changelog). - Restore `NativeImagePlugin.NATIVE_TEST_EXTENSION` by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/256](https://togithub.com/graalvm/native-build-tools/pull/256) - Fix JUnit annotation scanning during the image build by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/258](https://togithub.com/graalvm/native-build-tools/pull/258) - Change reachability metadata fallback path by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/257](https://togithub.com/graalvm/native-build-tools/pull/257) - Add a DSL option that enables the native-image agent by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/263](https://togithub.com/graalvm/native-build-tools/pull/263) - Bump dependency versions by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/264](https://togithub.com/graalvm/native-build-tools/pull/264) - Rename `jvm-reachability-metadata` -> `graalvm-reachability-metadata` by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/265](https://togithub.com/graalvm/native-build-tools/pull/265) - Final PR for the metadata repo by [@​vjovanov](https://togithub.com/vjovanov) in [https://github.com/graalvm/native-build-tools/pull/266](https://togithub.com/graalvm/native-build-tools/pull/266) #### New Contributors - [@​vjovanov](https://togithub.com/vjovanov) made their first contribution in [https://github.com/graalvm/native-build-tools/pull/266](https://togithub.com/graalvm/native-build-tools/pull/266) **Full Changelog**: https://github.com/graalvm/native-build-tools/compare/0.9.12...0.9.13 ### [`v0.9.12`](https://togithub.com/graalvm/native-build-tools/releases/tag/0.9.12) [Compare Source](https://togithub.com/graalvm/native-build-tools/compare/0.9.11...0.9.12) #### What's Changed Read what's new in the [documentation](https://graalvm.github.io/native-build-tools/latest/index.html#changelog). - Add Mockito / Byte Buddy support documentation by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/236](https://togithub.com/graalvm/native-build-tools/pull/236) - Prevent builds from failing if no test list is present by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/239](https://togithub.com/graalvm/native-build-tools/pull/239) - Support different agent modes in the native-image Gradle plugin by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/230](https://togithub.com/graalvm/native-build-tools/pull/230) - JVM Reachability Metadata support for Maven by [@​alvarosanchez](https://togithub.com/alvarosanchez) in [https://github.com/graalvm/native-build-tools/pull/240](https://togithub.com/graalvm/native-build-tools/pull/240) - Warn about deprecated agent DSL by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/242](https://togithub.com/graalvm/native-build-tools/pull/242) - Rework Maven plugin by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/247](https://togithub.com/graalvm/native-build-tools/pull/247) - Add Gradle rich output support, configure default metadata URL on Maven by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/249](https://togithub.com/graalvm/native-build-tools/pull/249) - Fix wrong scope for test dependencies by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/251](https://togithub.com/graalvm/native-build-tools/pull/251) - Add documentation for alternative build systems. by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/248](https://togithub.com/graalvm/native-build-tools/pull/248) **Full Changelog**: https://github.com/graalvm/native-build-tools/compare/0.9.11...0.9.12
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6a3d1cbf462a..7ef4227e7fab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -364,7 +364,7 @@ org.graalvm.buildtools junit-platform-native - 0.9.11 + 0.9.13 test From 6ea233272f86db8f01bf407e8040959438358061 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 3 Aug 2022 03:42:16 +0200 Subject: [PATCH 0743/1979] deps: update dependency org.junit.vintage:junit-vintage-engine to v5.9.0 (#924) 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.junit.vintage:junit-vintage-engine](https://junit.org/junit5/) ([source](https://togithub.com/junit-team/junit5)) | `5.8.2` -> `5.9.0` | [![age](https://badges.renovateapi.com/packages/maven/org.junit.vintage:junit-vintage-engine/5.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.junit.vintage:junit-vintage-engine/5.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.junit.vintage:junit-vintage-engine/5.9.0/compatibility-slim/5.8.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.junit.vintage:junit-vintage-engine/5.9.0/confidence-slim/5.8.2)](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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ef4227e7fab..c3142108f07e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -357,7 +357,7 @@ org.junit.vintage junit-vintage-engine - 5.8.2 + 5.9.0 test From d7938a2deea2dcff33b62b6cf3164e1867a7fcd5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 5 Aug 2022 19:20:11 +0200 Subject: [PATCH 0744/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.3 (#918) 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.0` -> `1.5.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.3/compatibility-slim/1.5.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.5.3/confidence-slim/1.5.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-config ### [`v1.5.3`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​153-httpsgithubcomgoogleapisjava-shared-configcomparev152v153-2022-07-27) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.5.2...v1.5.3) ##### Dependencies - update dependency org.junit.vintage:junit-vintage-engine to v5.9.0 ([#​497](https://togithub.com/googleapis/java-shared-config/issues/497)) ([1fc6ab4](https://togithub.com/googleapis/java-shared-config/commit/1fc6ab445624cd4f9c8b161d109f346a9e5ed09a)) - Update doclet to latest version 1.6.0 ([38fb7c3](https://togithub.com/googleapis/java-shared-config/commit/38fb7c3957fb6c9b2da10f9e463cc93a8b80a3a4)) ### [`v1.5.2`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​152-httpsgithubcomgoogleapisjava-shared-configcomparev151v152-2022-07-25) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.5.1...v1.5.2) ##### Dependencies - update dependency com.puppycrawl.tools:checkstyle to v10 ([#​435](https://togithub.com/googleapis/java-shared-config/issues/435)) ([bfc8ce1](https://togithub.com/googleapis/java-shared-config/commit/bfc8ce1deca6292147d002d3afe22a09840aa5d6)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.13 ([#​488](https://togithub.com/googleapis/java-shared-config/issues/488)) ([39b91ee](https://togithub.com/googleapis/java-shared-config/commit/39b91ee1283f0a5fbbe63e8bfd1ec97ab4ab377e)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.13 ([#​489](https://togithub.com/googleapis/java-shared-config/issues/489)) ([cc3bcfa](https://togithub.com/googleapis/java-shared-config/commit/cc3bcfa2d6717441a8d5b5048fa78c2cf7aabf2b)) ### [`v1.5.1`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​151-httpsgithubcomgoogleapisjava-shared-configcomparev150v151-2022-06-30) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.5.0...v1.5.1) ##### Dependencies - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.12 ([#​482](https://togithub.com/googleapis/java-shared-config/issues/482)) ([fbfc6dc](https://togithub.com/googleapis/java-shared-config/commit/fbfc6dc1329faaead3a3114c8599d9267722e7f0)) - update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.12 ([#​483](https://togithub.com/googleapis/java-shared-config/issues/483)) ([336cb78](https://togithub.com/googleapis/java-shared-config/commit/336cb7827b36583228c9e2b85871ae72f4c55975))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c3142108f07e..21b024887257 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.0 + 1.5.3 @@ -107,10 +107,6 @@ com.google.api.grpc proto-google-common-protos - - com.google.api - gax - com.google.cloud google-cloud-spanner @@ -176,6 +172,11 @@ + + com.google.api + gax + test + org.hamcrest hamcrest From 47cba8cb7f5de6ac8ab77734b235282e9ae1340b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 10 Aug 2022 10:23:02 +0530 Subject: [PATCH 0745/1979] chore(main): release 2.7.5 (#914) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index eee7cceefd49..df511b442ef3 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [2.7.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.4...v2.7.5) (2022-08-05) + + +### Bug Fixes + +* enable longpaths support for windows test ([#1485](https://github.com/googleapis/java-spanner-jdbc/issues/1485)) ([#908](https://github.com/googleapis/java-spanner-jdbc/issues/908)) ([2e53ade](https://github.com/googleapis/java-spanner-jdbc/commit/2e53adef54a6336bbdafcdb2dd5ee2011c07dc6f)) +* pr to troubleshoot native image tests ([#912](https://github.com/googleapis/java-spanner-jdbc/issues/912)) ([4e78071](https://github.com/googleapis/java-spanner-jdbc/commit/4e78071c7451b194439b7b0b300488ec50c9cd1e)) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-spanner-bom to v6.27.0 ([#898](https://github.com/googleapis/java-spanner-jdbc/issues/898)) ([c536dd6](https://github.com/googleapis/java-spanner-jdbc/commit/c536dd64f61f7a1f74d3c876156ffb2d99172ef1)) +* update dependency org.graalvm.buildtools:junit-platform-native to v0.9.13 ([#922](https://github.com/googleapis/java-spanner-jdbc/issues/922)) ([125a972](https://github.com/googleapis/java-spanner-jdbc/commit/125a972f902dab45833baeee1538bc773a69d4b6)) +* update dependency org.junit.vintage:junit-vintage-engine to v5.9.0 ([#924](https://github.com/googleapis/java-spanner-jdbc/issues/924)) ([9d6d313](https://github.com/googleapis/java-spanner-jdbc/commit/9d6d3135a3e2fbc3e377f5459924ed8869498c36)) + ## [2.7.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.3...v2.7.4) (2022-06-30) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 21b024887257..7c0ee70c9adc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.5-SNAPSHOT + 2.7.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3d5e03c0957d..20ab104b8d6d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.5-SNAPSHOT + 2.7.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 155cb99b192c..8d692407aac1 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.4:2.7.5-SNAPSHOT +google-cloud-spanner-jdbc:2.7.5:2.7.5 From fe0ea58a7d25b467f30342b9d42b72141cecba0b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 10 Aug 2022 06:16:38 +0000 Subject: [PATCH 0746/1979] chore(main): release 2.7.6-SNAPSHOT (#927) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7c0ee70c9adc..14a269b1f1dc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.5 + 2.7.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 20ab104b8d6d..82355d095820 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.5 + 2.7.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8d692407aac1..7a374a0041b5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.5:2.7.5 +google-cloud-spanner-jdbc:2.7.5:2.7.6-SNAPSHOT From 3857be0f39e0cf3fdbd9bd24a89d0dcb6aa9750c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 12 Aug 2022 00:34:16 +0200 Subject: [PATCH 0747/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3 (#921) 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/java-shared-dependencies) | `2.13.0` -> `3.0.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.1/compatibility-slim/2.13.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.1/confidence-slim/2.13.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v3.0.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​301-httpsgithubcomgoogleapisjava-shared-dependenciescomparev300v301-2022-08-02) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v3.0.0...v3.0.1) ##### Dependencies - update dependency com.google.code.gson:gson to v2.9.1 ([#​766](https://togithub.com/googleapis/java-shared-dependencies/issues/766)) ([f7b2b06](https://togithub.com/googleapis/java-shared-dependencies/commit/f7b2b06b80e3e95ff8ab9b1d6a2638ef3069298a)) - update gax.version to v2.18.7 ([#​767](https://togithub.com/googleapis/java-shared-dependencies/issues/767)) ([9650368](https://togithub.com/googleapis/java-shared-dependencies/commit/96503682e98cdf348ea2c1365a03a60f4322c712)) - update google.core.version to v2.8.6 ([#​770](https://togithub.com/googleapis/java-shared-dependencies/issues/770)) ([cfd4377](https://togithub.com/googleapis/java-shared-dependencies/commit/cfd4377dc178cebb4724065d55d185ce03988d55)) ### [`v3.0.0`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​300-httpsgithubcomgoogleapisjava-shared-dependenciescomparev2130v300-2022-07-29) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v2.13.0...v3.0.0) ##### Bug Fixes - enable longpaths support for windows test ([#​1485](https://togithub.com/googleapis/java-shared-dependencies/issues/1485)) ([#​738](https://togithub.com/googleapis/java-shared-dependencies/issues/738)) ([11bc8f8](https://togithub.com/googleapis/java-shared-dependencies/commit/11bc8f81f28be88a97fdeafca21724e33638770c)) ##### Dependencies - update dependency com.google.api-client:google-api-client-bom to v1.35.2 ([#​729](https://togithub.com/googleapis/java-shared-dependencies/issues/729)) ([1fa59af](https://togithub.com/googleapis/java-shared-dependencies/commit/1fa59af80abb9f278f57658c10158567e825fec6)) - update dependency com.google.api-client:google-api-client-bom to v2 ([#​746](https://togithub.com/googleapis/java-shared-dependencies/issues/746)) ([2dcb2e0](https://togithub.com/googleapis/java-shared-dependencies/commit/2dcb2e071e0ba0eea21bb575bd13cd559d4a1ca6)) - update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.2 ([#​741](https://togithub.com/googleapis/java-shared-dependencies/issues/741)) ([3352d6c](https://togithub.com/googleapis/java-shared-dependencies/commit/3352d6c36111c04e3f6f3e6360470fa3efb10d8f)) - update dependency com.google.auth:google-auth-library-bom to v1.8.0 ([#​726](https://togithub.com/googleapis/java-shared-dependencies/issues/726)) ([2c5d64c](https://togithub.com/googleapis/java-shared-dependencies/commit/2c5d64c127db8384e49113acfeac6928716a2d7f)) - update dependency com.google.auth:google-auth-library-bom to v1.8.1 ([#​742](https://togithub.com/googleapis/java-shared-dependencies/issues/742)) ([4f53527](https://togithub.com/googleapis/java-shared-dependencies/commit/4f53527bda7f40896711b7c1d1c02453321ffbc8)) - update dependency com.google.cloud:first-party-dependencies to v2 ([#​747](https://togithub.com/googleapis/java-shared-dependencies/issues/747)) ([e970ac0](https://togithub.com/googleapis/java-shared-dependencies/commit/e970ac0599941c825dc2516146a7c6673e68a9b9)) - update dependency com.google.cloud:grpc-gcp to v1.2.1 ([#​751](https://togithub.com/googleapis/java-shared-dependencies/issues/751)) ([b3284b6](https://togithub.com/googleapis/java-shared-dependencies/commit/b3284b6ee52a96a6ea8696a05a94443df9ee5b9f)) - update dependency com.google.cloud:third-party-dependencies to v2 ([#​748](https://togithub.com/googleapis/java-shared-dependencies/issues/748)) ([573b41a](https://togithub.com/googleapis/java-shared-dependencies/commit/573b41a69504372741cbeb01dd200e7c71967186)) - update dependency com.google.http-client:google-http-client-bom to v1.42.1 ([#​730](https://togithub.com/googleapis/java-shared-dependencies/issues/730)) ([6b47126](https://togithub.com/googleapis/java-shared-dependencies/commit/6b47126686b603a5d112e097ce6aa3a1880daf6f)) - update dependency com.google.http-client:google-http-client-bom to v1.42.2 ([#​749](https://togithub.com/googleapis/java-shared-dependencies/issues/749)) ([299d7b0](https://togithub.com/googleapis/java-shared-dependencies/commit/299d7b0d4920644e2c3070d12dd1d97da17a5e88)) - update dependency com.google.protobuf:protobuf-bom to v3.21.2 ([#​722](https://togithub.com/googleapis/java-shared-dependencies/issues/722)) ([7a96b12](https://togithub.com/googleapis/java-shared-dependencies/commit/7a96b1259a526b63e9376fd6cc18b27cddeb5f0f)) - update dependency com.google.protobuf:protobuf-bom to v3.21.3 ([#​756](https://togithub.com/googleapis/java-shared-dependencies/issues/756)) ([3d0bac2](https://togithub.com/googleapis/java-shared-dependencies/commit/3d0bac23487aebb94267c0708f41ff6c02a028a4)) - update dependency com.google.protobuf:protobuf-bom to v3.21.4 ([#​759](https://togithub.com/googleapis/java-shared-dependencies/issues/759)) ([5a54ef1](https://togithub.com/googleapis/java-shared-dependencies/commit/5a54ef1a2d56244166d4fcc46041d62c0dc4b411)) - update dependency io.grpc:grpc-bom to v1.48.0 ([#​752](https://togithub.com/googleapis/java-shared-dependencies/issues/752)) ([20ac908](https://togithub.com/googleapis/java-shared-dependencies/commit/20ac908932a5e7c8e581bdfcd68579d7e1cedd5f)) - update dependency org.checkerframework:checker-qual to v3.23.0 ([#​736](https://togithub.com/googleapis/java-shared-dependencies/issues/736)) ([fc01d8f](https://togithub.com/googleapis/java-shared-dependencies/commit/fc01d8f93f391f12fdb800d5006f0b4505832eeb)) - update gax.version to v2.18.3 ([#​731](https://togithub.com/googleapis/java-shared-dependencies/issues/731)) ([e8ee554](https://togithub.com/googleapis/java-shared-dependencies/commit/e8ee554707acb2f71c739d08e2ff02fbe43ffa52)) - update gax.version to v2.18.4 ([#​735](https://togithub.com/googleapis/java-shared-dependencies/issues/735)) ([11c7415](https://togithub.com/googleapis/java-shared-dependencies/commit/11c74152a84697924de3a0e838b05f606c3098f7)) - update gax.version to v2.18.5 ([#​758](https://togithub.com/googleapis/java-shared-dependencies/issues/758)) ([7469fc1](https://togithub.com/googleapis/java-shared-dependencies/commit/7469fc1cc5095b39a5738e60156711a268f6e052)) - update gax.version to v2.18.6 ([#​763](https://togithub.com/googleapis/java-shared-dependencies/issues/763)) ([b5ca2f7](https://togithub.com/googleapis/java-shared-dependencies/commit/b5ca2f7b4d81c705823253f4f03363a32d2be48b)) - update google.common-protos.version to v2.9.1 ([#​724](https://togithub.com/googleapis/java-shared-dependencies/issues/724)) ([5213dbb](https://togithub.com/googleapis/java-shared-dependencies/commit/5213dbbfa9c9b73d2420ec2be7782f16c9c4955f)) - update google.core.version to v2.8.1 ([#​725](https://togithub.com/googleapis/java-shared-dependencies/issues/725)) ([575858a](https://togithub.com/googleapis/java-shared-dependencies/commit/575858a60f76e46bbc2a2435c2b6c01c8f4ab681)) - update google.core.version to v2.8.3 ([#​760](https://togithub.com/googleapis/java-shared-dependencies/issues/760)) ([cb10ae4](https://togithub.com/googleapis/java-shared-dependencies/commit/cb10ae4b76939215ea465af74163b3d4ad65a548)) - update google.core.version to v2.8.4 ([#​762](https://togithub.com/googleapis/java-shared-dependencies/issues/762)) ([821daaf](https://togithub.com/googleapis/java-shared-dependencies/commit/821daafefdbcfdfe6e363e580747538096a562ef)) - update google.core.version to v2.8.5 ([#​764](https://togithub.com/googleapis/java-shared-dependencies/issues/764)) ([a1f8f50](https://togithub.com/googleapis/java-shared-dependencies/commit/a1f8f501b54143a2cec8e72efd4ceb3ce47f13ae)) - update iam.version to v1.5.0 ([#​732](https://togithub.com/googleapis/java-shared-dependencies/issues/732)) ([9dce0e5](https://togithub.com/googleapis/java-shared-dependencies/commit/9dce0e5199c1e425119adc804304958f58003a27)) - update iam.version to v1.5.1 ([#​737](https://togithub.com/googleapis/java-shared-dependencies/issues/737)) ([df39168](https://togithub.com/googleapis/java-shared-dependencies/commit/df391685d42fcb1b04f03ab1380a594893bdce37)) - update iam.version to v1.5.2 ([#​743](https://togithub.com/googleapis/java-shared-dependencies/issues/743)) ([cdde697](https://togithub.com/googleapis/java-shared-dependencies/commit/cdde697f25a89fc8c2ec7eae6b7c54f69977bb1c))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14a269b1f1dc..5cd6f52f3d69 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,14 +62,14 @@ com.google.cloud google-cloud-spanner-bom - 6.27.0 + 6.28.0 pom import com.google.cloud google-cloud-shared-dependencies - 2.13.0 + 3.0.1 pom import From 0332de30e6d8b28fd6c6ff96e1f129b44346bc5e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 12 Aug 2022 02:00:17 +0000 Subject: [PATCH 0748/1979] chore(main): release 2.7.6 (#930) :robot: I have created a release *beep* *boop* --- ## [2.7.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.5...v2.7.6) (2022-08-11) ### Dependencies * update dependency com.google.cloud:google-cloud-shared-dependencies to v3 ([#921](https://github.com/googleapis/java-spanner-jdbc/issues/921)) ([3857be0](https://github.com/googleapis/java-spanner-jdbc/commit/3857be0f39e0cf3fdbd9bd24a89d0dcb6aa9750c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index df511b442ef3..2446d6f9e17c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.5...v2.7.6) (2022-08-11) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-shared-dependencies to v3 ([#921](https://github.com/googleapis/java-spanner-jdbc/issues/921)) ([2aa0a40](https://github.com/googleapis/java-spanner-jdbc/commit/2aa0a40619e9f743877cff410db17968c374dc52)) + ## [2.7.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.4...v2.7.5) (2022-08-05) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5cd6f52f3d69..e266feb7b12b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.6-SNAPSHOT + 2.7.6 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 82355d095820..1298cb98de64 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.6-SNAPSHOT + 2.7.6 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7a374a0041b5..e5504bbe7038 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.5:2.7.6-SNAPSHOT +google-cloud-spanner-jdbc:2.7.6:2.7.6 From 8a5856df08c797ffa8bc5f0bda78dd4c305586b9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 12 Aug 2022 03:24:12 +0000 Subject: [PATCH 0749/1979] chore(main): release 2.7.7-SNAPSHOT (#931) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e266feb7b12b..8ca07e0f26f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.6 + 2.7.7-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1298cb98de64..89c34bd33bb9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.6 + 2.7.7-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e5504bbe7038..6187ae1ea58d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.6:2.7.6 +google-cloud-spanner-jdbc:2.7.6:2.7.7-SNAPSHOT From a0bd3b77b4077dde88eda65cd47338dd6a2e9abb Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Aug 2022 19:46:16 +0200 Subject: [PATCH 0750/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.6 (#928) 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.7.4` -> `2.7.6` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.6/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.6/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.6/compatibility-slim/2.7.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.6/confidence-slim/2.7.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.6`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​276-httpsgithubcomgoogleapisjava-spanner-jdbccomparev275v276-2022-08-11) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.5...v2.7.6) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v3 ([#​921](https://togithub.com/googleapis/java-spanner-jdbc/issues/921)) ([3857be0](https://togithub.com/googleapis/java-spanner-jdbc/commit/3857be0f39e0cf3fdbd9bd24a89d0dcb6aa9750c)) ### [`v2.7.5`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​275-httpsgithubcomgoogleapisjava-spanner-jdbccomparev274v275-2022-08-05) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.4...v2.7.5) ##### Bug Fixes - enable longpaths support for windows test ([#​1485](https://togithub.com/googleapis/java-spanner-jdbc/issues/1485)) ([#​908](https://togithub.com/googleapis/java-spanner-jdbc/issues/908)) ([51712cf](https://togithub.com/googleapis/java-spanner-jdbc/commit/51712cf85d50f41c3ece18057a050362b1eb0f8a)) - pr to troubleshoot native image tests ([#​912](https://togithub.com/googleapis/java-spanner-jdbc/issues/912)) ([f3e6be4](https://togithub.com/googleapis/java-spanner-jdbc/commit/f3e6be4409f7ec12c0a9284e352de0532999a3c1)) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-bom to v6.27.0 ([#​898](https://togithub.com/googleapis/java-spanner-jdbc/issues/898)) ([d6f2fd9](https://togithub.com/googleapis/java-spanner-jdbc/commit/d6f2fd979eaeef500a24f70adee531d2ae0621de)) - update dependency org.graalvm.buildtools:junit-platform-native to v0.9.13 ([#​922](https://togithub.com/googleapis/java-spanner-jdbc/issues/922)) ([7fdf57e](https://togithub.com/googleapis/java-spanner-jdbc/commit/7fdf57e7337421fe1fd0bf6cf0f2cb6404b0d7ce)) - update dependency org.junit.vintage:junit-vintage-engine to v5.9.0 ([#​924](https://togithub.com/googleapis/java-spanner-jdbc/issues/924)) ([6ea2332](https://togithub.com/googleapis/java-spanner-jdbc/commit/6ea233272f86db8f01bf407e8040959438358061))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d84e1a193665..9e6cc5627d4e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.4 + 2.7.6 From fd2baac1e52b710c6e3b86c7817ef9d034897be9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Aug 2022 22:58:12 +0200 Subject: [PATCH 0751/1979] test(deps): update dependency org.mockito:mockito-core to v4.7.0 (#933) 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.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.6.1` -> `4.7.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.7.0/compatibility-slim/4.6.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.7.0/confidence-slim/4.6.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.7.0`](https://togithub.com/mockito/mockito/releases/tag/v4.7.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.6.1...v4.7.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.7.0 - 2022-08-13 - [33 commit(s)](https://togithub.com/mockito/mockito/compare/v4.6.1...v4.7.0) by [`1988123`](https://togithub.com/mockito/mockito/commit/198812345678), Andy Coates, Chen Ni, Marius Lichtblau, Nikita Koselev. Developer Advocate, Open Source Ally, Rafael Winterhalter, dependabot\[bot], dstango, fishautumn, heqiang - Bump com.diffplug.spotless from 6.9.0 to 6.9.1 [(#​2725)](https://togithub.com/mockito/mockito/pull/2725) - Bump versions.bytebuddy from 1.12.12 to 1.12.13 [(#​2719)](https://togithub.com/mockito/mockito/pull/2719) - Fix Javadoc for Mockito. [(#​2718)](https://togithub.com/mockito/mockito/pull/2718) - Bump com.diffplug.spotless from 6.8.0 to 6.9.0 [(#​2717)](https://togithub.com/mockito/mockito/pull/2717) - Fix a typo in comment of InternalRunner.java [(#​2715)](https://togithub.com/mockito/mockito/pull/2715) - Bump junit-platform-launcher from 1.8.2 to 1.9.0 [(#​2713)](https://togithub.com/mockito/mockito/pull/2713) - Bump versions.junitJupiter from 5.8.2 to 5.9.0 [(#​2712)](https://togithub.com/mockito/mockito/pull/2712) - Bump groovy from 3.0.11 to 3.0.12 [(#​2711)](https://togithub.com/mockito/mockito/pull/2711) - Bump shipkit-auto-version from 1.2.0 to 1.2.1 [(#​2709)](https://togithub.com/mockito/mockito/pull/2709) - Bump kotlinVersion from 1.7.0 to 1.7.10 [(#​2705)](https://togithub.com/mockito/mockito/pull/2705) - Bump com.diffplug.spotless from 6.7.2 to 6.8.0 [(#​2699)](https://togithub.com/mockito/mockito/pull/2699) - Bump versions.bytebuddy from 1.12.11 to 1.12.12 [(#​2695)](https://togithub.com/mockito/mockito/pull/2695) - Makes error message less misleading and points to github for help. Issue [#​2692](https://togithub.com/mockito/mockito/issues/2692) [(#​2693)](https://togithub.com/mockito/mockito/pull/2693) - Misleading error message when mocking and a class (of a parameter) is not found [(#​2692)](https://togithub.com/mockito/mockito/issues/2692) - Bump kotlinx-coroutines-core from 1.6.1-native-mt to 1.6.3-native-mt [(#​2691)](https://togithub.com/mockito/mockito/pull/2691) - Bump versions.bytebuddy from 1.12.10 to 1.12.11 [(#​2690)](https://togithub.com/mockito/mockito/pull/2690) - Fixes [#​2679](https://togithub.com/mockito/mockito/issues/2679) : Update Javadoc [(#​2689)](https://togithub.com/mockito/mockito/pull/2689) - Bump org.eclipse.osgi from 3.17.200 to 3.18.0 [(#​2688)](https://togithub.com/mockito/mockito/pull/2688) - RETURNS_SELF: Avoids returning mock when mock type is assignable to method return type, but method return type is Object. [(#​2687)](https://togithub.com/mockito/mockito/pull/2687) - RETURNS_SELF breaks methods with generic return type [(#​2686)](https://togithub.com/mockito/mockito/issues/2686) - Fix [#​2616](https://togithub.com/mockito/mockito/issues/2616) wrong stub for nested static [(#​2685)](https://togithub.com/mockito/mockito/pull/2685) - Bump com.diffplug.spotless from 6.7.0 to 6.7.2 [(#​2684)](https://togithub.com/mockito/mockito/pull/2684) - Avoids starting mocks "half-way" if a superclass constructor is mocked but an unmocked subclass is initiated. [(#​2682)](https://togithub.com/mockito/mockito/pull/2682) - Fix typo [(#​2681)](https://togithub.com/mockito/mockito/pull/2681) - Update javadoc of `Strictness.STRICT_STUBS` [(#​2679)](https://togithub.com/mockito/mockito/issues/2679) - Bump kotlinVersion from 1.6.21 to 1.7.0 [(#​2677)](https://togithub.com/mockito/mockito/pull/2677) - Bump biz.aQute.bnd.builder from 6.3.0 to 6.3.1 [(#​2675)](https://togithub.com/mockito/mockito/pull/2675) - Bump biz.aQute.bnd.gradle from 6.3.0 to 6.3.1 [(#​2674)](https://togithub.com/mockito/mockito/pull/2674) - Bump com.diffplug.spotless from 6.6.1 to 6.7.0 [(#​2672)](https://togithub.com/mockito/mockito/pull/2672) - update CONTRIBUTING.md - stackoverflow [(#​2671)](https://togithub.com/mockito/mockito/pull/2671) - stackoverflow.com is a non-actionable text, to be replaced with a hyperlink [(#​2670)](https://togithub.com/mockito/mockito/issues/2670) - Fix typos [(#​2669)](https://togithub.com/mockito/mockito/pull/2669) - Bump biz.aQute.bnd.gradle from 6.2.0 to 6.3.0 [(#​2666)](https://togithub.com/mockito/mockito/pull/2666) - Bump biz.aQute.bnd.builder from 6.2.0 to 6.3.0 [(#​2665)](https://togithub.com/mockito/mockito/pull/2665) - Improve Varargs handling in AdditionalAnswers [(#​2664)](https://togithub.com/mockito/mockito/pull/2664) - Bump appcompat from 1.4.1 to 1.4.2 [(#​2663)](https://togithub.com/mockito/mockito/pull/2663) - Varargs methods cause `ClassCastException` in `AnswerFunctionalInterfaces` [(#​2644)](https://togithub.com/mockito/mockito/issues/2644) - Mock static class seems records wrong invocations if called nested method throws exception [(#​2616)](https://togithub.com/mockito/mockito/issues/2616)
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8ca07e0f26f0..619eb265525f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.6.1 + 4.7.0 2.2 0.31.1 From 4729d0c00e615ebee8c632861bbc198e020d45dd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Aug 2022 15:30:21 +0200 Subject: [PATCH 0752/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.1 (#935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.4.0` -> `3.4.1` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.1/compatibility-slim/3.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.1/confidence-slim/3.4.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 619eb265525f..3f9891e74bdc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -459,7 +459,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.0 + 3.4.1 From 1fd054a1dec6a520e3c4dab7a7db634c54620fc3 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Aug 2022 15:50:22 +0200 Subject: [PATCH 0753/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.4.1 (#934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-javadoc-plugin](https://maven.apache.org/plugins/) | `3.4.0` -> `3.4.1` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.1/compatibility-slim/3.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.4.1/confidence-slim/3.4.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3f9891e74bdc..63f9d0e4b6ad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -486,7 +486,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.0 + 3.4.1 html From 7fbce2b0d0de7a16c3969c02f26c92a29cabf8b5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 18 Aug 2022 16:00:16 +0200 Subject: [PATCH 0754/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.0 (#932) 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.0.0` -> `26.1.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.0/compatibility-slim/26.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.0/confidence-slim/26.0.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a7dacec26deb..c9583be0d396 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.0.0 + 26.1.0 pom import From 7a495047cebdfad4d835128997b9a72520483e5d Mon Sep 17 00:00:00 2001 From: Clamatius Date: Fri, 26 Aug 2022 08:41:53 -0700 Subject: [PATCH 0755/1979] fix: Types.BOOLEAN and Types.BIT should have identical behaviour for nullability (#920) * Types.BOOLEAN and Types.BIT should have identical behaviour for nullability. In master, BOOLEAN is nullable but BIT will throw IllegalArgumentException if an attempt is made to set a null value. * fix: Types.BOOLEAN and Types.BIT should have identical behaviour for nullability. In master, BOOLEAN is nullable but BIT will throw IllegalArgumentException if an attempt is made to set a null value. --- .../com/google/cloud/spanner/jdbc/JdbcParameterStore.java | 1 + .../com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 9ba490faa459..8be9e6fc3310 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -858,6 +858,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { return binder.to((ByteArray) null); case Types.BLOB: return binder.to((ByteArray) null); + case Types.BIT: case Types.BOOLEAN: return binder.to((Boolean) null); case Types.CHAR: diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index d886598ec46a..7d966b4f6a7b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; @@ -379,6 +380,9 @@ public void testSetParameterWithType() throws SQLException, IOException { params.setParameter(1, BigDecimal.ZERO, type); assertEquals(BigDecimal.ZERO, params.getParameter(1)); verifyParameter(params, Value.bool(false)); + params.setParameter(1, null, type); + assertNull(params.getParameter(1)); + verifyParameter(params, Value.bool(null)); } // types that should lead to numeric From 8e225d05c9bd68d6fc2174f207f1950a8292aead Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 30 Aug 2022 16:51:09 +0200 Subject: [PATCH 0756/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.0 (#943) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 63f9d0e4b6ad..7ec066bfda1b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.28.0 + 6.29.0 pom import From 5becd165af4ebf3a8a9cb47ab40156a123cfc4a4 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 31 Aug 2022 22:44:30 +0200 Subject: [PATCH 0757/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.1 (#944) 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.1.0` -> `26.1.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.1/compatibility-slim/26.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.1/confidence-slim/26.1.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c9583be0d396..a347b149335f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.0 + 26.1.1 pom import From 8cace9134c6721381a920339a55e59f7b0f871d7 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 5 Sep 2022 07:02:45 +0200 Subject: [PATCH 0758/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.1 (#961) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ec066bfda1b..51a378c4bcd9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.29.0 + 6.29.1 pom import From 7e81e6c3fcfba8b433e40fced73274e8612bd66d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 8 Sep 2022 03:32:32 +0200 Subject: [PATCH 0759/1979] test(deps): update dependency org.mockito:mockito-core to v4.8.0 (#962) 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.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.7.0` -> `4.8.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.8.0/compatibility-slim/4.7.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.8.0/confidence-slim/4.7.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.8.0`](https://togithub.com/mockito/mockito/releases/tag/v4.8.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.7.0...v4.8.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.8.0 - 2022-09-07 - [10 commit(s)](https://togithub.com/mockito/mockito/compare/v4.7.0...v4.8.0) by Alex, James Baker, Johannes Spangenberg, Kurt Alfred Kluever, Rafael Winterhalter, Thibault Helsmoortel, dependabot\[bot] - GitHub Workflows security hardening [(#​2744)](https://togithub.com/mockito/mockito/pull/2744) - Assign GlobalConfiguration initializer to unused variable [(#​2742)](https://togithub.com/mockito/mockito/pull/2742) - Bump com.diffplug.spotless from 6.9.1 to 6.10.0 [(#​2738)](https://togithub.com/mockito/mockito/pull/2738) - Drop varargs collector before invoking a user method. [(#​2736)](https://togithub.com/mockito/mockito/pull/2736) - Bump versions.bytebuddy from 1.12.13 to 1.12.14 [(#​2734)](https://togithub.com/mockito/mockito/pull/2734) - Remove useless thrown exception from constructor [(#​2732)](https://togithub.com/mockito/mockito/pull/2732) - TypeSafeMatching no longer iterates over class methods inefficiently [(#​2729)](https://togithub.com/mockito/mockito/pull/2729) - Fixes [#​2720](https://togithub.com/mockito/mockito/issues/2720): Use StackWalker on Java 9+ to create Locations [(#​2723)](https://togithub.com/mockito/mockito/pull/2723) - LocationImpl adds performance overheads due to instantiating a stack trace [(#​2720)](https://togithub.com/mockito/mockito/issues/2720) - Fixes [#​2626](https://togithub.com/mockito/mockito/issues/2626) : Introduce MockSettings.mockMaker [(#​2701)](https://togithub.com/mockito/mockito/pull/2701) - Introduce option to disable inline-mock-maker for a specific instance [(#​2626)](https://togithub.com/mockito/mockito/issues/2626)
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 51a378c4bcd9..e4ff315b7f33 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.7.0 + 4.8.0 2.2 0.31.1 From cd7ea51ac500249f901c03af0868aff02836fe08 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 9 Sep 2022 05:52:28 +0200 Subject: [PATCH 0760/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.2 (#963) 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/java-shared-dependencies) | `3.0.1` -> `3.0.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.2/compatibility-slim/3.0.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.2/confidence-slim/3.0.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v3.0.2`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​302-httpsgithubcomgoogleapisjava-shared-dependenciescomparev301v302-2022-09-08) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v3.0.1...v3.0.2) ##### Dependencies - Update dependency com.fasterxml.jackson:jackson-bom to v2.13.4 ([#​789](https://togithub.com/googleapis/java-shared-dependencies/issues/789)) ([6cf91a9](https://togithub.com/googleapis/java-shared-dependencies/commit/6cf91a96b9ea6af0fb845b50582dac7aa2892cab)) - Update dependency com.google.auth:google-auth-library-bom to v1.10.0 ([#​781](https://togithub.com/googleapis/java-shared-dependencies/issues/781)) ([8859e61](https://togithub.com/googleapis/java-shared-dependencies/commit/8859e61808bfc5cd9546e27e945fc855b36d2554)) - Update dependency com.google.auth:google-auth-library-bom to v1.11.0 ([#​790](https://togithub.com/googleapis/java-shared-dependencies/issues/790)) ([3431a47](https://togithub.com/googleapis/java-shared-dependencies/commit/3431a471cbf874a67a4f1a42e31f0ed891dedc92)) - Update dependency com.google.auth:google-auth-library-bom to v1.9.0 ([#​773](https://togithub.com/googleapis/java-shared-dependencies/issues/773)) ([27fc79f](https://togithub.com/googleapis/java-shared-dependencies/commit/27fc79f00ee70011df6a368bb8fcfad7f0ce41f0)) - Update dependency com.google.errorprone:error_prone_annotations to v2.15.0 ([#​776](https://togithub.com/googleapis/java-shared-dependencies/issues/776)) ([bf333b8](https://togithub.com/googleapis/java-shared-dependencies/commit/bf333b8c88072d21cb959db4d3328bbb55d9ef5c)) - Update dependency com.google.protobuf:protobuf-bom to v3.21.5 ([#​780](https://togithub.com/googleapis/java-shared-dependencies/issues/780)) ([da7f44d](https://togithub.com/googleapis/java-shared-dependencies/commit/da7f44d71d6d7f372b5313dab68ce220308614d4)) - Update dependency io.grpc:grpc-bom to v1.48.1 ([#​768](https://togithub.com/googleapis/java-shared-dependencies/issues/768)) ([5c7768d](https://togithub.com/googleapis/java-shared-dependencies/commit/5c7768d3c9665dd356de6c39c0a6a5fa6e992f2e)) - Update dependency io.grpc:grpc-bom to v1.49.0 ([#​786](https://togithub.com/googleapis/java-shared-dependencies/issues/786)) ([8734812](https://togithub.com/googleapis/java-shared-dependencies/commit/8734812f1b4e2faaa48caf41eff59a85892ae344)) - Update dependency org.checkerframework:checker-qual to v3.24.0 ([#​775](https://togithub.com/googleapis/java-shared-dependencies/issues/775)) ([df74b7b](https://togithub.com/googleapis/java-shared-dependencies/commit/df74b7b0dd5dd592523f302d9fb36adb5991cb0b)) - Update dependency org.checkerframework:checker-qual to v3.25.0 ([#​788](https://togithub.com/googleapis/java-shared-dependencies/issues/788)) ([207035b](https://togithub.com/googleapis/java-shared-dependencies/commit/207035bd04c9305899eea540acbefaf06a7b1ec9)) - Update dependency org.threeten:threetenbp to v1.6.1 ([#​782](https://togithub.com/googleapis/java-shared-dependencies/issues/782)) ([0f218ae](https://togithub.com/googleapis/java-shared-dependencies/commit/0f218aeb6aa33cf1da4a8b1d6c82bbf87946dab9)) - Update gax.version to v2.19.0 ([#​785](https://togithub.com/googleapis/java-shared-dependencies/issues/785)) ([4448331](https://togithub.com/googleapis/java-shared-dependencies/commit/4448331c4c6d88ea8076260776d1d47d24aa19fa)) - Update google.core.version to v2.8.10 ([#​787](https://togithub.com/googleapis/java-shared-dependencies/issues/787)) ([3c344d5](https://togithub.com/googleapis/java-shared-dependencies/commit/3c344d515e3b9215db5a1f8ef550d800d974e558)) - Update google.core.version to v2.8.7 ([#​774](https://togithub.com/googleapis/java-shared-dependencies/issues/774)) ([d0cd5e8](https://togithub.com/googleapis/java-shared-dependencies/commit/d0cd5e8f6ca88787fe0dbf7f30c849cb4c4fae5e)) - Update google.core.version to v2.8.8 ([#​777](https://togithub.com/googleapis/java-shared-dependencies/issues/777)) ([f00571c](https://togithub.com/googleapis/java-shared-dependencies/commit/f00571cd1e9f1c4e011fba4a1e1674c1d8d60200)) - Update google.core.version to v2.8.9 ([#​784](https://togithub.com/googleapis/java-shared-dependencies/issues/784)) ([aa8e505](https://togithub.com/googleapis/java-shared-dependencies/commit/aa8e505dbb1214b2239e55d5ac83b00c167d77e4))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e4ff315b7f33..15a6322904ce 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.0.1 + 3.0.2 pom import From 67c3b272e73fc357af9b5fa5c5480efc3a2feaf2 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 10 Sep 2022 02:08:31 +0000 Subject: [PATCH 0761/1979] chore: Generated snippets should not be owned by samples reviewers (#1575) (#964) Source-Link: https://github.com/googleapis/synthtool/commit/2e9ac19d5b8181af77cdc5337cf922517813cc49 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:8175681a918181d306d9c370d3262f16b4c724cc73d74111b7d42fc985ca7f93 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 +-- java-spanner-jdbc/.github/CODEOWNERS | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index d99cbbc27f08..6259292301cb 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,5 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:04f254abfe5f47fe73ae6f91d68d55c3b76e722a4943066c3bb0ce03573b4ad9 -# created: 2022-07-18T21:44:23.94208526Z \ No newline at end of file + digest: sha256:8175681a918181d306d9c370d3262f16b4c724cc73d74111b7d42fc985ca7f93 diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index 8ec690b49dcc..c5107b508607 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -13,3 +13,6 @@ # The java-samples-reviewers team is the default owner for samples changes samples/**/*.java @googleapis/java-samples-reviewers + +# Generated snippets should not be owned by samples reviewers +samples/snippets/generated/ @googleapis/yoshi-java From 021523bd28fb387a128fbb8cf9892c33b78abef8 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 15 Sep 2022 06:50:20 +0200 Subject: [PATCH 0762/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.3 (#966) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 15a6322904ce..3fd483f0fb48 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.0.2 + 3.0.3 pom import From 62b9cc4b6a7797c00d90320193d2befd8e60c9c5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 15 Sep 2022 06:50:46 +0200 Subject: [PATCH 0763/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.4.0 (#965) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3fd483f0fb48..007147d63985 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -261,7 +261,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.3.0 + 3.4.0 From f066bed8b486428073b1af469c71ff44a20f56d8 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Fri, 16 Sep 2022 15:14:13 -0400 Subject: [PATCH 0764/1979] deps: google-cloud-spanner-bom 6.30.0 (#967) RenovateBot didn't create a pull request. So I'm creating one by myself. --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 007147d63985..9925201ad738 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.29.1 + 6.30.0 pom import From e4baf39abaec8a35f86948ae4e62ec25a93c2fe9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 21:02:13 +0000 Subject: [PATCH 0765/1979] chore(main): release 2.7.7 (#940) :robot: I have created a release *beep* *boop* --- ## [2.7.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.6...v2.7.7) (2022-09-16) ### Bug Fixes * Types.BOOLEAN and Types.BIT should have identical behaviour for nullability ([#920](https://github.com/googleapis/java-spanner-jdbc/issues/920)) ([7a49504](https://github.com/googleapis/java-spanner-jdbc/commit/7a495047cebdfad4d835128997b9a72520483e5d)) ### Dependencies * Google-cloud-spanner-bom 6.30.0 ([#967](https://github.com/googleapis/java-spanner-jdbc/issues/967)) ([f066bed](https://github.com/googleapis/java-spanner-jdbc/commit/f066bed8b486428073b1af469c71ff44a20f56d8)) * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.2 ([#963](https://github.com/googleapis/java-spanner-jdbc/issues/963)) ([cd7ea51](https://github.com/googleapis/java-spanner-jdbc/commit/cd7ea51ac500249f901c03af0868aff02836fe08)) * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.3 ([#966](https://github.com/googleapis/java-spanner-jdbc/issues/966)) ([021523b](https://github.com/googleapis/java-spanner-jdbc/commit/021523bd28fb387a128fbb8cf9892c33b78abef8)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.0 ([#943](https://github.com/googleapis/java-spanner-jdbc/issues/943)) ([8e225d0](https://github.com/googleapis/java-spanner-jdbc/commit/8e225d05c9bd68d6fc2174f207f1950a8292aead)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.1 ([#961](https://github.com/googleapis/java-spanner-jdbc/issues/961)) ([8cace91](https://github.com/googleapis/java-spanner-jdbc/commit/8cace9134c6721381a920339a55e59f7b0f871d7)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 2446d6f9e17c..47170afac7d6 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.7.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.6...v2.7.7) (2022-09-16) + + +### Bug Fixes + +* Types.BOOLEAN and Types.BIT should have identical behaviour for nullability ([#920](https://github.com/googleapis/java-spanner-jdbc/issues/920)) ([42e5903](https://github.com/googleapis/java-spanner-jdbc/commit/42e590343ccbe294301a7b9933bd5db1830c8877)) + + +### Dependencies + +* Google-cloud-spanner-bom 6.30.0 ([#967](https://github.com/googleapis/java-spanner-jdbc/issues/967)) ([9385a5d](https://github.com/googleapis/java-spanner-jdbc/commit/9385a5dc52704de6fb1fe1c31f2c4ba2ad84d547)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.2 ([#963](https://github.com/googleapis/java-spanner-jdbc/issues/963)) ([811d96b](https://github.com/googleapis/java-spanner-jdbc/commit/811d96b0a7f90df7ec4d680aad085eec9d331a5e)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.3 ([#966](https://github.com/googleapis/java-spanner-jdbc/issues/966)) ([f8b88cd](https://github.com/googleapis/java-spanner-jdbc/commit/f8b88cd95c2bf02ce178a387ad82b149a9f4dbca)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.0 ([#943](https://github.com/googleapis/java-spanner-jdbc/issues/943)) ([9754023](https://github.com/googleapis/java-spanner-jdbc/commit/9754023b4d16aa78361d5be465d24b0481b84293)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.29.1 ([#961](https://github.com/googleapis/java-spanner-jdbc/issues/961)) ([a3e1fc6](https://github.com/googleapis/java-spanner-jdbc/commit/a3e1fc6b627e8f4da0191787e432d52b8174067a)) + ## [2.7.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.5...v2.7.6) (2022-08-11) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9925201ad738..2f060f40b762 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.7-SNAPSHOT + 2.7.7 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 89c34bd33bb9..1dff733de6d4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.7-SNAPSHOT + 2.7.7 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6187ae1ea58d..76f194b2af57 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.6:2.7.7-SNAPSHOT +google-cloud-spanner-jdbc:2.7.7:2.7.7 From 9616565f988a178c84a15e707c257cae2e6218c9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 22:26:43 +0000 Subject: [PATCH 0766/1979] chore(main): release 2.7.8-SNAPSHOT (#969) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2f060f40b762..d72c3ff67742 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.7 + 2.7.8-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1dff733de6d4..4c331c8156af 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.7 + 2.7.8-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 76f194b2af57..f6ff42e7e91c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.7:2.7.7 +google-cloud-spanner-jdbc:2.7.7:2.7.8-SNAPSHOT From cd9bf676d9ab967d4f152cd2d37f57e2b1517790 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sun, 18 Sep 2022 10:55:46 +0200 Subject: [PATCH 0767/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.7 (#970) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9e6cc5627d4e..47520ab9c016 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.6 + 2.7.7 From d72a2d2be6e6e38d614aee1ce9e2c31cc73158ee Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 19 Sep 2022 19:58:51 +0200 Subject: [PATCH 0768/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.2 (#972) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a347b149335f..c6725e93085d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.1 + 26.1.2 pom import From 8c961f4a1f8b6fc6b1613ad0b2c42e17f60ed7fb Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 20 Sep 2022 22:14:16 +0200 Subject: [PATCH 0769/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.1 (#973) 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.30.0` -> `6.30.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.1/compatibility-slim/6.30.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.1/confidence-slim/6.30.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.30.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6301-httpsgithubcomgoogleapisjava-spannercomparev6300v6301-2022-09-20) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.30.0...v6.30.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.4.4 ([#​2014](https://togithub.com/googleapis/java-spanner/issues/2014)) ([9cebad4](https://togithub.com/googleapis/java-spanner/commit/9cebad485afc8b8d94bd4bc1673542a330451fbd)) - Update dependency com.google.cloud:google-cloud-trace to v2.3.3 ([#​2004](https://togithub.com/googleapis/java-spanner/issues/2004)) ([54f9095](https://togithub.com/googleapis/java-spanner/commit/54f90957544f0798d9872956dbe40ce822d5167d))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d72c3ff67742..29c936ca01d3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.30.0 + 6.30.1 pom import From 15a14ff7992ab8c05c0dc7dcdef918f21dde5133 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 21 Sep 2022 06:44:19 +0200 Subject: [PATCH 0770/1979] deps: update dependency org.junit.vintage:junit-vintage-engine to v5.9.1 (#974) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 29c936ca01d3..5308b55202c5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -358,7 +358,7 @@ org.junit.vintage junit-vintage-engine - 5.9.0 + 5.9.1 test From 721820d286a5626ff8d379f94acaae1c580e454f Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 21 Sep 2022 19:18:19 +0200 Subject: [PATCH 0771/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.2 (#976) 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.30.1` -> `6.30.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.2/compatibility-slim/6.30.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.30.2/confidence-slim/6.30.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.30.2`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6302-httpsgithubcomgoogleapisjava-spannercomparev6301v6302-2022-09-21) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.30.1...v6.30.2) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.4.5 ([#​2022](https://togithub.com/googleapis/java-spanner/issues/2022)) ([0536962](https://togithub.com/googleapis/java-spanner/commit/0536962df9af3feed237f758a560c24fafd81d60)) - Update dependency org.junit.vintage:junit-vintage-engine to v5.9.1 ([#​2023](https://togithub.com/googleapis/java-spanner/issues/2023)) ([3fb4235](https://togithub.com/googleapis/java-spanner/commit/3fb423571c1128b7cafdc6596d5366268d74f0e4))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5308b55202c5..d8b573ebfb61 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.30.1 + 6.30.2 pom import From 2bc323dcf3337e8c0fe0e0ed18feab610555939b Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 26 Sep 2022 22:10:13 +0000 Subject: [PATCH 0772/1979] chore: pin versions of dependencies for compatibility with Python 3.6 (#1588) (#978) * chore: pin versions of dependencies for compatibility with Python 3.6 * fix path of requirements file in synthtool Source-Link: https://github.com/googleapis/synthtool/commit/69cdb47824170d0b02bf694649ce66613c889040 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:6566dc8226f20993af18e5a4e7a2b1ba85a292b02dedb6a1634cf10e1b418fa5 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- .../.kokoro/release/publish_javadoc.sh | 2 +- .../.kokoro/release/publish_javadoc11.sh | 2 +- java-spanner-jdbc/.kokoro/release/stage.sh | 3 +- java-spanner-jdbc/.kokoro/requirements.in | 31 ++ java-spanner-jdbc/.kokoro/requirements.txt | 452 ++++++++++++++++++ 6 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/requirements.in create mode 100644 java-spanner-jdbc/.kokoro/requirements.txt diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 6259292301cb..791e842d2f88 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:8175681a918181d306d9c370d3262f16b4c724cc73d74111b7d42fc985ca7f93 + digest: sha256:6566dc8226f20993af18e5a4e7a2b1ba85a292b02dedb6a1634cf10e1b418fa5 diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh index 2f1cac7d1139..54c727bad2e1 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh @@ -28,7 +28,7 @@ fi pushd $(dirname "$0")/../../ # install docuploader package -python3 -m pip install gcp-docuploader +python3 -m pip install --require-hashes -r .kokoro/requirements.txt # compile all packages mvn clean install -B -q -DskipTests=true diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh index 49678864cc3d..03eff888c7dd 100755 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh @@ -28,7 +28,7 @@ fi pushd $(dirname "$0")/../../ # install docuploader package -python3 -m pip install gcp-docuploader +python3 -m pip install --require-hashes -r .kokoro/requirements.txt # compile all packages mvn clean install -B -q -DskipTests=true diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh index 1dba8de10857..61e714d6ba56 100755 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ b/java-spanner-jdbc/.kokoro/release/stage.sh @@ -16,7 +16,8 @@ set -eo pipefail # Start the releasetool reporter -python3 -m pip install gcp-releasetool +requirementsFile=$(realpath $(dirname "${BASH_SOURCE[0]}")/../requirements.txt) +python3 -m pip install --require-hashes -r $requirementsFile python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script source $(dirname "$0")/common.sh diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in new file mode 100644 index 000000000000..cfdc2e7ed955 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -0,0 +1,31 @@ +gcp-docuploader==0.6.3 +google-crc32c==1.3.0 +googleapis-common-protos==1.56.3 +gcp-releasetool==1.8.7 +cachetools==4.2.4 +cffi==1.15.1 +jeepney==0.7.1 +jinja2==3.0.3 +markupsafe==2.0.1 +keyring==23.4.1 +packaging==21.3 +protobuf==3.19.5 +pyjwt==2.4.0 +pyparsing==3.0.9 +pycparser==2.21 +pyperclip==1.8.2 +python-dateutil==2.8.2 +requests==2.27.1 +importlib-metadata==4.8.3 +zipp==3.6.0 +google_api_core==2.8.2 +google-cloud-storage==2.0.0 +google-cloud-core==2.3.1 +typing-extensions==4.1.1 +urllib3==1.26.12 +zipp==3.6.0 +rsa==4.9 +six==1.16.0 +attrs==22.1.0 +google-auth==2.11.0 +idna==3.4 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt new file mode 100644 index 000000000000..170f1c63abb7 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -0,0 +1,452 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --allow-unsafe --generate-hashes requirements.in +# +attrs==22.1.0 \ + --hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \ + --hash=sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c + # via + # -r requirements.in + # gcp-releasetool +cachetools==4.2.4 \ + --hash=sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693 \ + --hash=sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1 + # via + # -r requirements.in + # google-auth +certifi==2022.9.14 \ + --hash=sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5 \ + --hash=sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516 + # via requests +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 + # via + # -r requirements.in + # cryptography +charset-normalizer==2.0.12 \ + --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \ + --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df + # via requests +click==8.0.4 \ + --hash=sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1 \ + --hash=sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb + # via + # gcp-docuploader + # gcp-releasetool +colorlog==6.7.0 \ + --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ + --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 + # via gcp-docuploader +cryptography==38.0.1 \ + --hash=sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a \ + --hash=sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f \ + --hash=sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0 \ + --hash=sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407 \ + --hash=sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7 \ + --hash=sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6 \ + --hash=sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153 \ + --hash=sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750 \ + --hash=sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad \ + --hash=sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6 \ + --hash=sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b \ + --hash=sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5 \ + --hash=sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a \ + --hash=sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d \ + --hash=sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d \ + --hash=sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294 \ + --hash=sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0 \ + --hash=sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a \ + --hash=sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac \ + --hash=sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61 \ + --hash=sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013 \ + --hash=sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e \ + --hash=sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb \ + --hash=sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9 \ + --hash=sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd \ + --hash=sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818 + # via + # gcp-releasetool + # secretstorage +gcp-docuploader==0.6.3 \ + --hash=sha256:ba8c9d76b3bbac54b0311c503a373b00edc2dc02d6d54ea9507045adb8e870f7 \ + --hash=sha256:c0f5aaa82ce1854a386197e4e359b120ad6d4e57ae2c812fce42219a3288026b + # via -r requirements.in +gcp-releasetool==1.8.7 \ + --hash=sha256:3d2a67c9db39322194afb3b427e9cb0476ce8f2a04033695f0aeb63979fc2b37 \ + --hash=sha256:5e4d28f66e90780d77f3ecf1e9155852b0c3b13cbccb08ab07e66b2357c8da8d + # via -r requirements.in +google-api-core==2.8.2 \ + --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \ + --hash=sha256:93c6a91ccac79079ac6bbf8b74ee75db970cc899278b97d53bc012f35908cf50 + # via + # -r requirements.in + # google-cloud-core + # google-cloud-storage +google-auth==2.11.0 \ + --hash=sha256:be62acaae38d0049c21ca90f27a23847245c9f161ff54ede13af2cb6afecbac9 \ + --hash=sha256:ed65ecf9f681832298e29328e1ef0a3676e3732b2e56f41532d45f70a22de0fb + # via + # -r requirements.in + # gcp-releasetool + # google-api-core + # google-cloud-core + # google-cloud-storage +google-cloud-core==2.3.1 \ + --hash=sha256:113ba4f492467d5bd442c8d724c1a25ad7384045c3178369038840ecdd19346c \ + --hash=sha256:34334359cb04187bdc80ddcf613e462dfd7a3aabbc3fe4d118517ab4b9303d53 + # via + # -r requirements.in + # google-cloud-storage +google-cloud-storage==2.0.0 \ + --hash=sha256:a57a15aead0f9dfbd4381f1bfdbe8bf89818a4bd75bab846cafcefb2db846c47 \ + --hash=sha256:ec4be60bb223a3a960f0d01697d849b86d91cad815a84915a32ed3635e93a5e7 + # via + # -r requirements.in + # 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 + # via + # -r requirements.in + # google-resumable-media +google-resumable-media==2.3.3 \ + --hash=sha256:27c52620bd364d1c8116eaac4ea2afcbfb81ae9139fb3199652fcac1724bfb6c \ + --hash=sha256:5b52774ea7a829a8cdaa8bd2d4c3d4bc660c91b30857ab2668d0eb830f4ea8c5 + # via google-cloud-storage +googleapis-common-protos==1.56.3 \ + --hash=sha256:6f1369b58ed6cf3a4b7054a44ebe8d03b29c309257583a2bbdc064cd1e4a1442 \ + --hash=sha256:87955d7b3a73e6e803f2572a33179de23989ebba725e05ea42f24838b792e461 + # via + # -r requirements.in + # google-api-core +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via + # -r requirements.in + # requests +importlib-metadata==4.8.3 \ + --hash=sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e \ + --hash=sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668 + # via + # -r requirements.in + # keyring +jeepney==0.7.1 \ + --hash=sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac \ + --hash=sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f + # via + # -r requirements.in + # keyring + # secretstorage +jinja2==3.0.3 \ + --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \ + --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7 + # via + # -r requirements.in + # gcp-releasetool +keyring==23.4.1 \ + --hash=sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca \ + --hash=sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55 + # via + # -r requirements.in + # 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 + # via + # -r requirements.in + # jinja2 +packaging==21.3 \ + --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ + --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 + # via + # -r requirements.in + # gcp-releasetool +protobuf==3.19.5 \ + --hash=sha256:1867f93b06a183f87696871bb8d1e99ee71dbb69d468ce1f0cc8bf3d30f982f3 \ + --hash=sha256:3c4160b601220627f7e91154e572baf5e161a9c3f445a8242d536ee3d0b7b17c \ + --hash=sha256:4ee2af7051d3b10c8a4fe6fd1a2c69f201fea36aeee7086cf202a692e1b99ee1 \ + --hash=sha256:5266c36cc0af3bb3dbf44f199d225b33da66a9a5c3bdc2b14865ad10eddf0e37 \ + --hash=sha256:5470f892961af464ae6eaf0f3099e2c1190ae8c7f36f174b89491281341f79ca \ + --hash=sha256:66d14b5b90090353efe75c9fb1bf65ef7267383034688d255b500822e37d5c2f \ + --hash=sha256:67efb5d20618020aa9596e17bfc37ca068c28ec0c1507d9507f73c93d46c9855 \ + --hash=sha256:696e6cfab94cc15a14946f2bf72719dced087d437adbd994fff34f38986628bc \ + --hash=sha256:6a02172b9650f819d01fb8e224fc69b0706458fc1ab4f1c669281243c71c1a5e \ + --hash=sha256:6eca9ae238ba615d702387a2ddea635d535d769994a9968c09a4ca920c487ab9 \ + --hash=sha256:950abd6c00e7b51f87ae8b18a0ce4d69fea217f62f171426e77de5061f6d9850 \ + --hash=sha256:9e1d74032f56ff25f417cfe84c8147047732e5059137ca42efad20cbbd25f5e0 \ + --hash=sha256:9e42b1cf2ecd8a1bd161239e693f22035ba99905ae6d7efeac8a0546c7ec1a27 \ + --hash=sha256:9f957ef53e872d58a0afd3bf6d80d48535d28c99b40e75e6634cbc33ea42fd54 \ + --hash=sha256:a89aa0c042e61e11ade320b802d6db4ee5391d8d973e46d3a48172c1597789f8 \ + --hash=sha256:c0f80876a8ff0ae7064084ed094eb86497bd5a3812e6fc96a05318b92301674e \ + --hash=sha256:c44e3282cff74ad18c7e8a0375f407f69ee50c2116364b44492a196293e08b21 \ + --hash=sha256:d249519ba5ecf5dd6b18150c9b6bcde510b273714b696f3923ff8308fc11ae49 \ + --hash=sha256:d3973a2d58aefc7d1230725c2447ce7f86a71cbc094b86a77c6ee1505ac7cdb1 \ + --hash=sha256:dca2284378a5f2a86ffed35c6ac147d14c48b525eefcd1083e5a9ce28dfa8657 \ + --hash=sha256:e63b0b3c42e51c94add62b010366cd4979cb6d5f06158bcae8faac4c294f91e1 \ + --hash=sha256:f2b599a21c9a32e171ec29a2ac54e03297736c578698e11b099d031f79da114b \ + --hash=sha256:f2bde37667b18c2b5280df83bc799204394a5d2d774e4deaf9de0eb741df6833 \ + --hash=sha256:f4f909f4dde413dec435a44b0894956d55bb928ded7d6e3c726556ca4c796e84 \ + --hash=sha256:f976234e20ab2785f54224bcdafa027674e23663b132fa3ca0caa291a6cfbde7 \ + --hash=sha256:f9cebda093c2f6bfed88f1c17cdade09d4d96096421b344026feee236532d4de + # via + # -r requirements.in + # gcp-docuploader + # gcp-releasetool + # google-api-core + # google-cloud-storage + # googleapis-common-protos +pyasn1==0.4.8 \ + --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \ + --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.2.8 \ + --hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \ + --hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 + # via google-auth +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 + # via + # -r requirements.in + # cffi +pyjwt==2.4.0 \ + --hash=sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf \ + --hash=sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba + # via + # -r requirements.in + # gcp-releasetool +pyparsing==3.0.9 \ + --hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \ + --hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc + # via + # -r requirements.in + # packaging +pyperclip==1.8.2 \ + --hash=sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57 + # via + # -r requirements.in + # gcp-releasetool +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via + # -r requirements.in + # gcp-releasetool +requests==2.27.1 \ + --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ + --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d + # via + # -r requirements.in + # gcp-releasetool + # google-api-core + # google-cloud-storage +rsa==4.9 \ + --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ + --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 + # via + # -r requirements.in + # google-auth +secretstorage==3.3.3 \ + --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ + --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 + # via keyring +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via + # -r requirements.in + # gcp-docuploader + # google-auth + # python-dateutil +typing-extensions==4.1.1 \ + --hash=sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42 \ + --hash=sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2 + # via -r requirements.in +urllib3==1.26.12 \ + --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ + --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 + # via + # -r requirements.in + # requests +zipp==3.6.0 \ + --hash=sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832 \ + --hash=sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc + # via + # -r requirements.in + # importlib-metadata From c7479b03d8826dbdeb9a5bbaf1edcf72657a35c8 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 27 Sep 2022 17:52:13 +0200 Subject: [PATCH 0773/1979] deps: update dependency org.graalvm.buildtools:junit-platform-native to v0.9.14 (#977) 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.graalvm.buildtools:junit-platform-native](https://togithub.com/graalvm/native-build-tools) | `0.9.13` -> `0.9.14` | [![age](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.14/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.14/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.14/compatibility-slim/0.9.13)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.14/confidence-slim/0.9.13)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    graalvm/native-build-tools ### [`v0.9.14`](https://togithub.com/graalvm/native-build-tools/releases/tag/0.9.14) [Compare Source](https://togithub.com/graalvm/native-build-tools/compare/0.9.13...0.9.14) #### What's Changed Read what's new in the [documentation](https://graalvm.github.io/native-build-tools/latest/index.html#changelog). - Fix how the GRAALVM_QUICK_BUILD env var is read by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/278](https://togithub.com/graalvm/native-build-tools/pull/278) - Make it possible to pass env vars to the builder process by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/280](https://togithub.com/graalvm/native-build-tools/pull/280) - Maven plugin fixes by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/274](https://togithub.com/graalvm/native-build-tools/pull/274) - Add support for `test-jar` artifacts by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/281](https://togithub.com/graalvm/native-build-tools/pull/281) - Add Gradle CLI options for quick build and debugging by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/286](https://togithub.com/graalvm/native-build-tools/pull/286) - Add a changelog and docs about build -> compile-no-fork changes by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/290](https://togithub.com/graalvm/native-build-tools/pull/290) - Do not filter out entry values starting with `java.` in the metadata post-processing action by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/289](https://togithub.com/graalvm/native-build-tools/pull/289) - Try to fix snapshot publishing by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/244](https://togithub.com/graalvm/native-build-tools/pull/244) - Fix javadoc and warnings by [@​lazar-mitrovic](https://togithub.com/lazar-mitrovic) in [https://github.com/graalvm/native-build-tools/pull/291](https://togithub.com/graalvm/native-build-tools/pull/291) - Bump the default metadata repository version to 0.1.2 by [@​gradinac](https://togithub.com/gradinac) in [https://github.com/graalvm/native-build-tools/pull/294](https://togithub.com/graalvm/native-build-tools/pull/294) - Fix metadata repository crash by [@​dnestoro](https://togithub.com/dnestoro) in [https://github.com/graalvm/native-build-tools/pull/295](https://togithub.com/graalvm/native-build-tools/pull/295) - Add support for override flag by [@​sdeleuze](https://togithub.com/sdeleuze) in [https://github.com/graalvm/native-build-tools/pull/296](https://togithub.com/graalvm/native-build-tools/pull/296) - Fix build time initialization error with JUnit 5.9.0 by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/308](https://togithub.com/graalvm/native-build-tools/pull/308) - Fix compatibility with configuration cache by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/304](https://togithub.com/graalvm/native-build-tools/pull/304) - Bump metadata repository version by [@​melix](https://togithub.com/melix) in [https://github.com/graalvm/native-build-tools/pull/310](https://togithub.com/graalvm/native-build-tools/pull/310) #### New Contributors - [@​dnestoro](https://togithub.com/dnestoro) made their first contribution in [https://github.com/graalvm/native-build-tools/pull/295](https://togithub.com/graalvm/native-build-tools/pull/295) **Full Changelog**: https://github.com/graalvm/native-build-tools/compare/0.9.13...0.9.14
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d8b573ebfb61..97f38fbca60c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -365,7 +365,7 @@ org.graalvm.buildtools junit-platform-native - 0.9.13 + 0.9.14 test From 553b962fc24fac6823d4e3a33d9c7c97505b63c9 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 09:48:00 -0400 Subject: [PATCH 0774/1979] chore: exclude requirements.txt file from renovate-bot (#1594) (#979) Source-Link: https://github.com/googleapis/synthtool/commit/f58d3135a2fab20e225d98741dbc06d57459b816 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:f14e3fefe8e361e85752bd9890c8e56f2fe25f1e89cbb9597e4e3c7a429203a3 Co-authored-by: Owl Bot Co-authored-by: Diego Alonso Marquez Palacios --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 ++- java-spanner-jdbc/renovate.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 791e842d2f88..2c3ef72011b4 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:6566dc8226f20993af18e5a4e7a2b1ba85a292b02dedb6a1634cf10e1b418fa5 + digest: sha256:f14e3fefe8e361e85752bd9890c8e56f2fe25f1e89cbb9597e4e3c7a429203a3 + diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 5371695645d9..6525dc2a570f 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -10,6 +10,7 @@ ":maintainLockFilesDisabled", ":autodetectPinVersions" ], + "ignorePaths": [".kokoro/requirements.txt"], "packageRules": [ { "packagePatterns": [ From 34949567ecd4e12be9a55979397710684795a5c3 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:56:49 -0400 Subject: [PATCH 0775/1979] fix: upgrade native image plugin to 0.9.14 to unblock graalvm 22.2 update (#998) --- java-spanner-jdbc/.kokoro/build.sh | 8 ++++---- java-spanner-jdbc/pom.xml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index f66c99f85e56..079a70384273 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -70,13 +70,13 @@ integration) RETURN_CODE=$? ;; graalvm) - # Run Unit and Integration Tests with Native Image. Use native-maven-plugin until https://github.com/graalvm/native-build-tools/issues/279 is fixed. - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.11 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + # Run Unit and Integration Tests with Native Image. + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.14 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; graalvm17) - # Run Unit and Integration Tests with Native Image. Use native-maven-plugin 0.9.11 until https://github.com/graalvm/native-build-tools/issues/279 is fixed. - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.11 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + # Run Unit and Integration Tests with Native Image. + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.14 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; samples) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97f38fbca60c..2d1ef949541e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -351,7 +351,7 @@ - native-0.9.11 + native-0.9.14 @@ -391,7 +391,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.11 + 0.9.14 true From f8733c9b8bc10d067e83b2eb9ac73e4238c02645 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 30 Sep 2022 23:54:48 +0200 Subject: [PATCH 0776/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.0 (#1000) 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.30.2` -> `6.31.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.0/compatibility-slim/6.30.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.0/confidence-slim/6.30.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.31.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6310-httpsgithubcomgoogleapisjava-spannercomparev6302v6310-2022-09-29) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.30.2...v6.31.0) ##### Features - Support customer managed instance configurations ([#​1742](https://togithub.com/googleapis/java-spanner/issues/1742)) ([c1c805c](https://togithub.com/googleapis/java-spanner/commit/c1c805cf6e9c00f2d6796627d919338be1a0599a)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-trace to v2.3.4 ([#​2027](https://togithub.com/googleapis/java-spanner/issues/2027)) ([14890ed](https://togithub.com/googleapis/java-spanner/commit/14890ed8e0df99eba7c2521a196132c78054b6ed)) - Update dependency com.google.cloud:google-cloud-trace to v2.3.5 ([#​2083](https://togithub.com/googleapis/java-spanner/issues/2083)) ([cef4e0a](https://togithub.com/googleapis/java-spanner/commit/cef4e0ada98ab65020f32836fc0c8ab1ee0c7eed)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.14 ([#​2030](https://togithub.com/googleapis/java-spanner/issues/2030)) ([04b59ff](https://togithub.com/googleapis/java-spanner/commit/04b59ff8a1efaa32082aa4e9567d90b5956810c6)) - Update dependency org.json:json to v20220924 ([#​2035](https://togithub.com/googleapis/java-spanner/issues/2035)) ([a26a14a](https://togithub.com/googleapis/java-spanner/commit/a26a14a94ac3ca6cd7eabce6826cce3dde27ea66))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2d1ef949541e..94ce483e6ba0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.30.2 + 6.31.0 pom import From d1ceef4e6fb38c5e5e3105647305a512986a3d25 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 3 Oct 2022 15:46:27 +0200 Subject: [PATCH 0777/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.4 (#1001) 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/java-shared-dependencies) | `3.0.3` -> `3.0.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.4/compatibility-slim/3.0.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.0.4/confidence-slim/3.0.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v3.0.4`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​304-httpsgithubcomgoogleapisjava-shared-dependenciescomparev303v304-2022-10-03) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v3.0.3...v3.0.4) ##### Dependencies - Update dependency cachetools to v5 ([#​816](https://togithub.com/googleapis/java-shared-dependencies/issues/816)) ([3f6c408](https://togithub.com/googleapis/java-shared-dependencies/commit/3f6c408210c931c286235f61c7aadea5bf5cfe4d)) - Update dependency certifi to v2022.9.24 ([#​818](https://togithub.com/googleapis/java-shared-dependencies/issues/818)) ([5f04b97](https://togithub.com/googleapis/java-shared-dependencies/commit/5f04b97c2343146600e8c9ee65afdeb58f5743a6)) - Update dependency charset-normalizer to v2.1.1 ([#​822](https://togithub.com/googleapis/java-shared-dependencies/issues/822)) ([6997c5a](https://togithub.com/googleapis/java-shared-dependencies/commit/6997c5acad937ebe3594330de73261a424d42cf3)) - Update dependency click to v8.1.3 ([#​823](https://togithub.com/googleapis/java-shared-dependencies/issues/823)) ([42bf9f8](https://togithub.com/googleapis/java-shared-dependencies/commit/42bf9f834fdafea60f2be7ccbf7d363e058cd7c2)) - Update dependency com.google.protobuf:protobuf-bom to v3.21.7 ([#​837](https://togithub.com/googleapis/java-shared-dependencies/issues/837)) ([d31e507](https://togithub.com/googleapis/java-shared-dependencies/commit/d31e5077c7e036de5e238e9a611df7ced527574a)) - Update dependency gcp-releasetool to v1.8.8 ([#​819](https://togithub.com/googleapis/java-shared-dependencies/issues/819)) ([8245d97](https://togithub.com/googleapis/java-shared-dependencies/commit/8245d975fb12e81454ec7664f9a7c9809bbac697)) - Update dependency gcp-releasetool to v1.8.9 ([#​846](https://togithub.com/googleapis/java-shared-dependencies/issues/846)) ([04e3283](https://togithub.com/googleapis/java-shared-dependencies/commit/04e32831c6e87c372444901013a747d2d02ce38d)) - Update dependency google-api-core to v2.10.1 ([#​824](https://togithub.com/googleapis/java-shared-dependencies/issues/824)) ([818b9aa](https://togithub.com/googleapis/java-shared-dependencies/commit/818b9aa2ac99d8b1f9b39a74b626122aed5f1d94)) - Update dependency google-auth to v2.12.0 ([#​825](https://togithub.com/googleapis/java-shared-dependencies/issues/825)) ([07c544b](https://togithub.com/googleapis/java-shared-dependencies/commit/07c544b5e0fa9f7110bbc957570f7a405962072e)) - Update dependency google-cloud-core to v2.3.2 ([#​820](https://togithub.com/googleapis/java-shared-dependencies/issues/820)) ([2a219e8](https://togithub.com/googleapis/java-shared-dependencies/commit/2a219e86f187ba5ad72f2570bd58ca6100128c43)) - Update dependency google-cloud-storage to v2.5.0 ([#​826](https://togithub.com/googleapis/java-shared-dependencies/issues/826)) ([bb10d18](https://togithub.com/googleapis/java-shared-dependencies/commit/bb10d1858a515f09d365362ffa0110a5b362c96b)) - Update dependency google-crc32c to v1.5.0 ([#​827](https://togithub.com/googleapis/java-shared-dependencies/issues/827)) ([7e5dae6](https://togithub.com/googleapis/java-shared-dependencies/commit/7e5dae60d667cb84b9ee4f6c977bdc35e79e4cf6)) - Update dependency google-resumable-media to v2.4.0 ([#​838](https://togithub.com/googleapis/java-shared-dependencies/issues/838)) ([ad82d63](https://togithub.com/googleapis/java-shared-dependencies/commit/ad82d6378f64039da383509638fb4782908eb4bc)) - Update dependency googleapis-common-protos to v1.56.4 ([#​821](https://togithub.com/googleapis/java-shared-dependencies/issues/821)) ([93d7745](https://togithub.com/googleapis/java-shared-dependencies/commit/93d77458c9bbf84ec367cdb4caaa41e6f71675c6)) - Update dependency importlib-metadata to v4.12.0 ([#​832](https://togithub.com/googleapis/java-shared-dependencies/issues/832)) ([ee19fb1](https://togithub.com/googleapis/java-shared-dependencies/commit/ee19fb1ca5a2a2e1985297e3b72d44de68bc72e3)) - Update dependency importlib-metadata to v4.13.0 ([#​843](https://togithub.com/googleapis/java-shared-dependencies/issues/843)) ([d2ede60](https://togithub.com/googleapis/java-shared-dependencies/commit/d2ede601eee8c875780c7eb5924623537480c509)) - Update dependency importlib-metadata to v5 ([#​845](https://togithub.com/googleapis/java-shared-dependencies/issues/845)) ([03ac7e8](https://togithub.com/googleapis/java-shared-dependencies/commit/03ac7e800274c5f58d2bc4ddd0561bfcdea1bb27)) - Update dependency io.grpc:grpc-bom to v1.49.1 ([#​802](https://togithub.com/googleapis/java-shared-dependencies/issues/802)) ([b8c54bf](https://togithub.com/googleapis/java-shared-dependencies/commit/b8c54bf8f1ddecc788cee151f8afe42de45bdc9d)) - Update dependency io.grpc:grpc-bom to v1.49.2 ([#​842](https://togithub.com/googleapis/java-shared-dependencies/issues/842)) ([1b1cfa2](https://togithub.com/googleapis/java-shared-dependencies/commit/1b1cfa27d05f7732da12721305cf41dcbebda232)) - Update dependency jeepney to v0.8.0 ([#​833](https://togithub.com/googleapis/java-shared-dependencies/issues/833)) ([15d2f9f](https://togithub.com/googleapis/java-shared-dependencies/commit/15d2f9f52b5a3259db0813df3d2424e256ccb372)) - Update dependency jinja2 to v3.1.2 ([#​834](https://togithub.com/googleapis/java-shared-dependencies/issues/834)) ([c188f95](https://togithub.com/googleapis/java-shared-dependencies/commit/c188f95acdb3349f1c4b3ed56e5fffb75e8fbc8d)) - Update dependency keyring to v23.9.3 ([#​828](https://togithub.com/googleapis/java-shared-dependencies/issues/828)) ([b185aaa](https://togithub.com/googleapis/java-shared-dependencies/commit/b185aaae716d4d97cb64f0426cac0e778f11223d)) - Update dependency markupsafe to v2.1.1 ([#​829](https://togithub.com/googleapis/java-shared-dependencies/issues/829)) ([add2825](https://togithub.com/googleapis/java-shared-dependencies/commit/add2825bd34cd80f529dbe0dadb3c84219177916)) - Update dependency org.threeten:threetenbp to v1.6.2 ([#​808](https://togithub.com/googleapis/java-shared-dependencies/issues/808)) ([2d2eabd](https://togithub.com/googleapis/java-shared-dependencies/commit/2d2eabd14d8150207885ea47280c0f7ff3d2962f)) - Update dependency protobuf to v3.20.2 ([#​830](https://togithub.com/googleapis/java-shared-dependencies/issues/830)) ([5afa76f](https://togithub.com/googleapis/java-shared-dependencies/commit/5afa76f9ef4705aecba49abc7bb93982fb1ecf3e)) - Update dependency protobuf to v3.20.3 ([#​839](https://togithub.com/googleapis/java-shared-dependencies/issues/839)) ([d9fc7dd](https://togithub.com/googleapis/java-shared-dependencies/commit/d9fc7ddd3e663458e6ea3f78a3c6241377df0319)) - Update dependency protobuf to v4 ([#​817](https://togithub.com/googleapis/java-shared-dependencies/issues/817)) ([ee8d154](https://togithub.com/googleapis/java-shared-dependencies/commit/ee8d154287ccd256b4dcfa48f28f5ec61a91fe3e)) - Update dependency pyjwt to v2.5.0 ([#​812](https://togithub.com/googleapis/java-shared-dependencies/issues/812)) ([4d4528e](https://togithub.com/googleapis/java-shared-dependencies/commit/4d4528e8ce269d49b99d2dbc4fcda2dc37a058cb)) - Update dependency requests to v2.28.1 ([#​813](https://togithub.com/googleapis/java-shared-dependencies/issues/813)) ([a3a8d89](https://togithub.com/googleapis/java-shared-dependencies/commit/a3a8d89b0117007a7108553c70aa82dd289e1691)) - Update dependency typing-extensions to v4.3.0 ([#​814](https://togithub.com/googleapis/java-shared-dependencies/issues/814)) ([da875e5](https://togithub.com/googleapis/java-shared-dependencies/commit/da875e5e91fa9d8c177e6c3afc9e34242eb914b7)) - Update dependency zipp to v3.8.1 ([#​815](https://togithub.com/googleapis/java-shared-dependencies/issues/815)) ([15585fd](https://togithub.com/googleapis/java-shared-dependencies/commit/15585fd0216013fe93be011f93f391f6269aa777)) - Update gax.version to v2.19.2 ([#​847](https://togithub.com/googleapis/java-shared-dependencies/issues/847)) ([c4afe1f](https://togithub.com/googleapis/java-shared-dependencies/commit/c4afe1fdc88af29ab039cea618d52c15c90e43e9)) - Update google.common-protos.version to v2.9.3 ([#​803](https://togithub.com/googleapis/java-shared-dependencies/issues/803)) ([a3e8e5e](https://togithub.com/googleapis/java-shared-dependencies/commit/a3e8e5eb53a8da14abf3b8d81a4f34fbb2f3b8f9)) - Update google.common-protos.version to v2.9.5 ([#​831](https://togithub.com/googleapis/java-shared-dependencies/issues/831)) ([1c901db](https://togithub.com/googleapis/java-shared-dependencies/commit/1c901db8a7740afaec3e809e51d4d369fbf469c4)) - Update google.common-protos.version to v2.9.6 ([#​844](https://togithub.com/googleapis/java-shared-dependencies/issues/844)) ([9e156be](https://togithub.com/googleapis/java-shared-dependencies/commit/9e156be59bd89959f04252c3045b8cd7a8be8070)) - Update google.core.version to v2.8.13 ([#​804](https://togithub.com/googleapis/java-shared-dependencies/issues/804)) ([45ae571](https://togithub.com/googleapis/java-shared-dependencies/commit/45ae57142bd6d5334eedd46243736b200a459795)) - Update google.core.version to v2.8.14 ([#​805](https://togithub.com/googleapis/java-shared-dependencies/issues/805)) ([02c9397](https://togithub.com/googleapis/java-shared-dependencies/commit/02c9397a84bf3fcca8d04e4c9867cc47689abde2)) - Update google.core.version to v2.8.15 ([#​807](https://togithub.com/googleapis/java-shared-dependencies/issues/807)) ([980856c](https://togithub.com/googleapis/java-shared-dependencies/commit/980856c43981992a3d08f69eac83aeada752d244)) - Update google.core.version to v2.8.16 ([#​810](https://togithub.com/googleapis/java-shared-dependencies/issues/810)) ([c2b2c9a](https://togithub.com/googleapis/java-shared-dependencies/commit/c2b2c9a327fd588f69524bb93a17e5d4ae8f5a42)) - Update google.core.version to v2.8.17 ([#​835](https://togithub.com/googleapis/java-shared-dependencies/issues/835)) ([3def21d](https://togithub.com/googleapis/java-shared-dependencies/commit/3def21df2e4253e3df0da064b6c4e472df079d2b)) - Update google.core.version to v2.8.18 ([#​840](https://togithub.com/googleapis/java-shared-dependencies/issues/840)) ([46566dc](https://togithub.com/googleapis/java-shared-dependencies/commit/46566dc18c4b1ed41c482b4ce21b92651e2f9dc5)) - Update google.core.version to v2.8.19 ([#​841](https://togithub.com/googleapis/java-shared-dependencies/issues/841)) ([99afde9](https://togithub.com/googleapis/java-shared-dependencies/commit/99afde97ea498f549eb75cc58c4ed88edf81b20d)) - Update google.core.version to v2.8.20 ([#​848](https://togithub.com/googleapis/java-shared-dependencies/issues/848)) ([c980c4f](https://togithub.com/googleapis/java-shared-dependencies/commit/c980c4fdfc8890d812b4881ba5b87bfd21269a5f)) - Update iam.version to v1.6.1 ([#​806](https://togithub.com/googleapis/java-shared-dependencies/issues/806)) ([a50158d](https://togithub.com/googleapis/java-shared-dependencies/commit/a50158d3b83cf8e02d8ee08c94e512b5669a927b)) - Update iam.version to v1.6.2 ([#​849](https://togithub.com/googleapis/java-shared-dependencies/issues/849)) ([e43ac96](https://togithub.com/googleapis/java-shared-dependencies/commit/e43ac96bc189a096a9311c9b03e85c86bea07e99))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 94ce483e6ba0..ced8b38cc8f2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.0.3 + 3.0.4 pom import From fe90014df96dbdd5678dcbc2d48427a923e960d1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 16:08:14 +0000 Subject: [PATCH 0778/1979] chore(main): release 2.7.8 (#975) :robot: I have created a release *beep* *boop* --- ## [2.7.8](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.7...v2.7.8) (2022-10-03) ### Bug Fixes * Upgrade native image plugin to 0.9.14 to unblock graalvm 22.2 update ([#998](https://togithub.com/googleapis/java-spanner-jdbc/issues/998)) ([3494956](https://togithub.com/googleapis/java-spanner-jdbc/commit/34949567ecd4e12be9a55979397710684795a5c3)) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.4 ([#1001](https://togithub.com/googleapis/java-spanner-jdbc/issues/1001)) ([d1ceef4](https://togithub.com/googleapis/java-spanner-jdbc/commit/d1ceef4e6fb38c5e5e3105647305a512986a3d25)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.1 ([#973](https://togithub.com/googleapis/java-spanner-jdbc/issues/973)) ([8c961f4](https://togithub.com/googleapis/java-spanner-jdbc/commit/8c961f4a1f8b6fc6b1613ad0b2c42e17f60ed7fb)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.2 ([#976](https://togithub.com/googleapis/java-spanner-jdbc/issues/976)) ([721820d](https://togithub.com/googleapis/java-spanner-jdbc/commit/721820d286a5626ff8d379f94acaae1c580e454f)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.0 ([#1000](https://togithub.com/googleapis/java-spanner-jdbc/issues/1000)) ([f8733c9](https://togithub.com/googleapis/java-spanner-jdbc/commit/f8733c9b8bc10d067e83b2eb9ac73e4238c02645)) * Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.14 ([#977](https://togithub.com/googleapis/java-spanner-jdbc/issues/977)) ([c7479b0](https://togithub.com/googleapis/java-spanner-jdbc/commit/c7479b03d8826dbdeb9a5bbaf1edcf72657a35c8)) * Update dependency org.junit.vintage:junit-vintage-engine to v5.9.1 ([#974](https://togithub.com/googleapis/java-spanner-jdbc/issues/974)) ([15a14ff](https://togithub.com/googleapis/java-spanner-jdbc/commit/15a14ff7992ab8c05c0dc7dcdef918f21dde5133)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 17 +++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 47170afac7d6..de9cc318360d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [2.7.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.7...v2.7.8) (2022-10-03) + + +### Bug Fixes + +* Upgrade native image plugin to 0.9.14 to unblock graalvm 22.2 update ([#998](https://github.com/googleapis/java-spanner-jdbc/issues/998)) ([e5ed330](https://github.com/googleapis/java-spanner-jdbc/commit/e5ed3300780eec0a32c0f135415063f65fb5ca82)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.4 ([#1001](https://github.com/googleapis/java-spanner-jdbc/issues/1001)) ([feafe10](https://github.com/googleapis/java-spanner-jdbc/commit/feafe1076c7e272bfe69fe055f742072b5aac763)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.1 ([#973](https://github.com/googleapis/java-spanner-jdbc/issues/973)) ([205f312](https://github.com/googleapis/java-spanner-jdbc/commit/205f312ab3466e9efb3fc3c79ddc9644adcca527)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.2 ([#976](https://github.com/googleapis/java-spanner-jdbc/issues/976)) ([037a33a](https://github.com/googleapis/java-spanner-jdbc/commit/037a33a932d2a50412bc53cc05cf512a9d2a4548)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.0 ([#1000](https://github.com/googleapis/java-spanner-jdbc/issues/1000)) ([59d69fb](https://github.com/googleapis/java-spanner-jdbc/commit/59d69fb6548d7e1d23fc8285faa975befd00323a)) +* Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.14 ([#977](https://github.com/googleapis/java-spanner-jdbc/issues/977)) ([32c881e](https://github.com/googleapis/java-spanner-jdbc/commit/32c881ea6530d23385f0c001e99d767146544210)) +* Update dependency org.junit.vintage:junit-vintage-engine to v5.9.1 ([#974](https://github.com/googleapis/java-spanner-jdbc/issues/974)) ([fab57d9](https://github.com/googleapis/java-spanner-jdbc/commit/fab57d9adea37ca4c3aa9aeb8d11e086ba86e538)) + ## [2.7.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.6...v2.7.7) (2022-09-16) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ced8b38cc8f2..ff0625c9bd76 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.8-SNAPSHOT + 2.7.8 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4c331c8156af..b8d8f28b334b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.8-SNAPSHOT + 2.7.8 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f6ff42e7e91c..6d1fec2c2aaa 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.7:2.7.8-SNAPSHOT +google-cloud-spanner-jdbc:2.7.8:2.7.8 From 43c2d9d0ba7a3d34f892599d0052b91936624101 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 18:02:14 +0000 Subject: [PATCH 0779/1979] chore(main): release 2.7.9-SNAPSHOT (#1003) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ff0625c9bd76..97f22d01ca07 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.8 + 2.7.9-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b8d8f28b334b..d91947056f4b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.8 + 2.7.9-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6d1fec2c2aaa..3d9a2678f025 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.8:2.7.8 +google-cloud-spanner-jdbc:2.7.8:2.7.9-SNAPSHOT From 0a5754794fd2d51eba235ebd9989e9049508645c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 6 Oct 2022 20:16:14 +0200 Subject: [PATCH 0780/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.2 (#1002) 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.31.0` -> `6.31.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.2/compatibility-slim/6.31.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.31.2/confidence-slim/6.31.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.31.2`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6312-httpsgithubcomgoogleapisjava-spannercomparev6311v6312-2022-10-05) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.31.1...v6.31.2) ##### Bug Fixes - update protobuf to v3.21.7 ([ac71008](https://togithub.com/googleapis/java-spanner/commit/ac71008bf8b1244cb3c5cf4317a0d25d4ffc5bbd)) ### [`v6.31.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6311-httpsgithubcomgoogleapisjava-spannercomparev6310v6311-2022-10-03) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.31.0...v6.31.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.4 ([#​2090](https://togithub.com/googleapis/java-spanner/issues/2090)) ([8f46938](https://togithub.com/googleapis/java-spanner/commit/8f46938b67e44a7b739dc156dc8a0a89bcb33ef0)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.14 ([#​2031](https://togithub.com/googleapis/java-spanner/issues/2031)) ([c5e9ba1](https://togithub.com/googleapis/java-spanner/commit/c5e9ba1c1a47faf89c47a9146a97cb6711dce242))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97f22d01ca07..4e3d81d86d4a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.31.0 + 6.31.2 pom import From 8d1a86c8b9455d1b6fd8c2286fc6270be90934bd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 6 Oct 2022 22:00:27 +0200 Subject: [PATCH 0781/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.8 (#1004) 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.7.7` -> `2.7.8` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.8/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.8/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.8/compatibility-slim/2.7.7)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.8/confidence-slim/2.7.7)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.8`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​278-httpsgithubcomgoogleapisjava-spanner-jdbccomparev277v278-2022-10-03) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.7...v2.7.8) ##### Bug Fixes - Upgrade native image plugin to 0.9.14 to unblock graalvm 22.2 update ([#​998](https://togithub.com/googleapis/java-spanner-jdbc/issues/998)) ([3494956](https://togithub.com/googleapis/java-spanner-jdbc/commit/34949567ecd4e12be9a55979397710684795a5c3)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.4 ([#​1001](https://togithub.com/googleapis/java-spanner-jdbc/issues/1001)) ([d1ceef4](https://togithub.com/googleapis/java-spanner-jdbc/commit/d1ceef4e6fb38c5e5e3105647305a512986a3d25)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.1 ([#​973](https://togithub.com/googleapis/java-spanner-jdbc/issues/973)) ([8c961f4](https://togithub.com/googleapis/java-spanner-jdbc/commit/8c961f4a1f8b6fc6b1613ad0b2c42e17f60ed7fb)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.30.2 ([#​976](https://togithub.com/googleapis/java-spanner-jdbc/issues/976)) ([721820d](https://togithub.com/googleapis/java-spanner-jdbc/commit/721820d286a5626ff8d379f94acaae1c580e454f)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.0 ([#​1000](https://togithub.com/googleapis/java-spanner-jdbc/issues/1000)) ([f8733c9](https://togithub.com/googleapis/java-spanner-jdbc/commit/f8733c9b8bc10d067e83b2eb9ac73e4238c02645)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.14 ([#​977](https://togithub.com/googleapis/java-spanner-jdbc/issues/977)) ([c7479b0](https://togithub.com/googleapis/java-spanner-jdbc/commit/c7479b03d8826dbdeb9a5bbaf1edcf72657a35c8)) - Update dependency org.junit.vintage:junit-vintage-engine to v5.9.1 ([#​974](https://togithub.com/googleapis/java-spanner-jdbc/issues/974)) ([15a14ff](https://togithub.com/googleapis/java-spanner-jdbc/commit/15a14ff7992ab8c05c0dc7dcdef918f21dde5133))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 47520ab9c016..3fa30836812d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.7 + 2.7.8 From b29f0da5a17783884fe97523840cc7e72ea2453f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 20:02:14 +0000 Subject: [PATCH 0782/1979] chore(main): release 2.7.9 (#1005) :robot: I have created a release *beep* *boop* --- ## [2.7.9](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.8...v2.7.9) (2022-10-06) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.2 ([#1002](https://togithub.com/googleapis/java-spanner-jdbc/issues/1002)) ([0a57547](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a5754794fd2d51eba235ebd9989e9049508645c)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index de9cc318360d..2a779dbbe1eb 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.8...v2.7.9) (2022-10-06) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.2 ([#1002](https://github.com/googleapis/java-spanner-jdbc/issues/1002)) ([f2ac8e3](https://github.com/googleapis/java-spanner-jdbc/commit/f2ac8e392e972d326bc5702855385471febea87c)) + ## [2.7.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.7...v2.7.8) (2022-10-03) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4e3d81d86d4a..f7612180bdaa 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.9-SNAPSHOT + 2.7.9 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d91947056f4b..e960a293f2e7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.9-SNAPSHOT + 2.7.9 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3d9a2678f025..620c6cc15ace 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.8:2.7.9-SNAPSHOT +google-cloud-spanner-jdbc:2.7.9:2.7.9 From a0a9511eb5a62b95449fb2dd2e9a13ab10834095 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 22:00:25 +0000 Subject: [PATCH 0783/1979] chore(main): release 2.7.10-SNAPSHOT (#1006) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f7612180bdaa..dd1d87b3e4b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.9 + 2.7.10-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e960a293f2e7..4cbc9f9e1627 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.9 + 2.7.10-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 620c6cc15ace..04b790df14c0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.9:2.7.9 +google-cloud-spanner-jdbc:2.7.9:2.7.10-SNAPSHOT From 0aeb98684a7c3bf8b65d4d4adb2d6363a98ff807 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 7 Oct 2022 04:38:14 +0200 Subject: [PATCH 0784/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.3 (#1008) 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.1.2` -> `26.1.3` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.3/compatibility-slim/26.1.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.3/confidence-slim/26.1.2)](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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c6725e93085d..fc7c803ad9ee 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.2 + 26.1.3 pom import From ee7dac0a4e349a1020377da6645414063658a3a5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 10 Oct 2022 16:14:21 +0200 Subject: [PATCH 0785/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.9 (#1007) 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.7.8` -> `2.7.9` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.9/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.9/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.9/compatibility-slim/2.7.8)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.9/confidence-slim/2.7.8)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.9`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​279-httpsgithubcomgoogleapisjava-spanner-jdbccomparev278v279-2022-10-06) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.8...v2.7.9) ##### Dependencies - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.31.2 ([#​1002](https://togithub.com/googleapis/java-spanner-jdbc/issues/1002)) ([0a57547](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a5754794fd2d51eba235ebd9989e9049508645c))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3fa30836812d..d6ace51c4cc4 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.8 + 2.7.9 From 565d013cac1fbff537d8e1a00b9c04073bfb4ae0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 Oct 2022 16:42:16 +0200 Subject: [PATCH 0786/1979] deps: update dependency org.graalvm.buildtools:junit-platform-native to v0.9.15 (#1009) 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.graalvm.buildtools:junit-platform-native](https://togithub.com/graalvm/native-build-tools) | `0.9.14` -> `0.9.15` | [![age](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.15/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.15/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.15/compatibility-slim/0.9.14)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:junit-platform-native/0.9.15/confidence-slim/0.9.14)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    graalvm/native-build-tools ### [`v0.9.15`](https://togithub.com/graalvm/native-build-tools/releases/tag/0.9.15) [Compare Source](https://togithub.com/graalvm/native-build-tools/compare/0.9.14...0.9.15) #### What's Changed Read what's new in the [documentation](https://graalvm.github.io/native-build-tools/latest/index.html#changelog). - Move block from onTestClassRegistered to onLoad function by [@​dnestoro](https://togithub.com/dnestoro) in [https://togithub.com/graalvm/native-build-tools/pull/312](https://togithub.com/graalvm/native-build-tools/pull/312) - Add .sdkmanrc by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/320](https://togithub.com/graalvm/native-build-tools/pull/320) - Bump the default metadata repository version to 0.2.1 by [@​dnestoro](https://togithub.com/dnestoro) in [https://togithub.com/graalvm/native-build-tools/pull/323](https://togithub.com/graalvm/native-build-tools/pull/323) - Fix functional tests for MacOS users by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/321](https://togithub.com/graalvm/native-build-tools/pull/321) - Include buildtool support for bundling reachability metadata into jar files by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/322](https://togithub.com/graalvm/native-build-tools/pull/322) - Ship the GraalVM metadata repository as an artifact alongside NBT by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/331](https://togithub.com/graalvm/native-build-tools/pull/331) - Improve toolchain selection diagnostics by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/332](https://togithub.com/graalvm/native-build-tools/pull/332) - Bump metadata repository version by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/335](https://togithub.com/graalvm/native-build-tools/pull/335) - Fix ` NoSuchFileExceptionv in `collectReachabilityMetadata\` Gradle task by [@​sdeleuze](https://togithub.com/sdeleuze) in [https://togithub.com/graalvm/native-build-tools/pull/336](https://togithub.com/graalvm/native-build-tools/pull/336) - Remove use of DependencyFilter by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/337](https://togithub.com/graalvm/native-build-tools/pull/337) #### New Contributors - [@​philwebb](https://togithub.com/philwebb) made their first contribution in [https://togithub.com/graalvm/native-build-tools/pull/320](https://togithub.com/graalvm/native-build-tools/pull/320) **Full Changelog**: https://togithub.com/graalvm/native-build-tools/compare/0.9.14...0.9.15
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dd1d87b3e4b0..54fabc1e24f7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -365,7 +365,7 @@ org.graalvm.buildtools junit-platform-native - 0.9.14 + 0.9.15 test
    From e73bfb4dba0391c70a4ffbde7e898da60d831f46 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 18 Oct 2022 16:54:20 +0200 Subject: [PATCH 0787/1979] deps: update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.15 (#1010) 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.graalvm.buildtools:native-maven-plugin](https://togithub.com/graalvm/native-build-tools) | `0.9.14` -> `0.9.15` | [![age](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:native-maven-plugin/0.9.15/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:native-maven-plugin/0.9.15/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:native-maven-plugin/0.9.15/compatibility-slim/0.9.14)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.graalvm.buildtools:native-maven-plugin/0.9.15/confidence-slim/0.9.14)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    graalvm/native-build-tools ### [`v0.9.15`](https://togithub.com/graalvm/native-build-tools/releases/tag/0.9.15) [Compare Source](https://togithub.com/graalvm/native-build-tools/compare/0.9.14...0.9.15) #### What's Changed Read what's new in the [documentation](https://graalvm.github.io/native-build-tools/latest/index.html#changelog). - Move block from onTestClassRegistered to onLoad function by [@​dnestoro](https://togithub.com/dnestoro) in [https://togithub.com/graalvm/native-build-tools/pull/312](https://togithub.com/graalvm/native-build-tools/pull/312) - Add .sdkmanrc by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/320](https://togithub.com/graalvm/native-build-tools/pull/320) - Bump the default metadata repository version to 0.2.1 by [@​dnestoro](https://togithub.com/dnestoro) in [https://togithub.com/graalvm/native-build-tools/pull/323](https://togithub.com/graalvm/native-build-tools/pull/323) - Fix functional tests for MacOS users by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/321](https://togithub.com/graalvm/native-build-tools/pull/321) - Include buildtool support for bundling reachability metadata into jar files by [@​philwebb](https://togithub.com/philwebb) in [https://togithub.com/graalvm/native-build-tools/pull/322](https://togithub.com/graalvm/native-build-tools/pull/322) - Ship the GraalVM metadata repository as an artifact alongside NBT by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/331](https://togithub.com/graalvm/native-build-tools/pull/331) - Improve toolchain selection diagnostics by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/332](https://togithub.com/graalvm/native-build-tools/pull/332) - Bump metadata repository version by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/335](https://togithub.com/graalvm/native-build-tools/pull/335) - Fix ` NoSuchFileExceptionv in `collectReachabilityMetadata\` Gradle task by [@​sdeleuze](https://togithub.com/sdeleuze) in [https://togithub.com/graalvm/native-build-tools/pull/336](https://togithub.com/graalvm/native-build-tools/pull/336) - Remove use of DependencyFilter by [@​melix](https://togithub.com/melix) in [https://togithub.com/graalvm/native-build-tools/pull/337](https://togithub.com/graalvm/native-build-tools/pull/337) #### New Contributors - [@​philwebb](https://togithub.com/philwebb) made their first contribution in [https://togithub.com/graalvm/native-build-tools/pull/320](https://togithub.com/graalvm/native-build-tools/pull/320) **Full Changelog**: https://togithub.com/graalvm/native-build-tools/compare/0.9.14...0.9.15
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 54fabc1e24f7..52eb931c480d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -391,7 +391,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.14 + 0.9.15 true From 3d12c0c8c920996322f9f89f9b579fe247c074d8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 16:28:14 +0000 Subject: [PATCH 0788/1979] chore(main): release 2.7.10 (#1011) :robot: I have created a release *beep* *boop* --- ## [2.7.10](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.9...v2.7.10) (2022-10-18) ### Dependencies * Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.15 ([#1009](https://togithub.com/googleapis/java-spanner-jdbc/issues/1009)) ([565d013](https://togithub.com/googleapis/java-spanner-jdbc/commit/565d013cac1fbff537d8e1a00b9c04073bfb4ae0)) * Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.15 ([#1010](https://togithub.com/googleapis/java-spanner-jdbc/issues/1010)) ([e73bfb4](https://togithub.com/googleapis/java-spanner-jdbc/commit/e73bfb4dba0391c70a4ffbde7e898da60d831f46)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 2a779dbbe1eb..083bfbfc324e 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.7.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.9...v2.7.10) (2022-10-18) + + +### Dependencies + +* Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.15 ([#1009](https://github.com/googleapis/java-spanner-jdbc/issues/1009)) ([8a6da6c](https://github.com/googleapis/java-spanner-jdbc/commit/8a6da6cbd95a23f6601775fb7147567ca1017119)) +* Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.15 ([#1010](https://github.com/googleapis/java-spanner-jdbc/issues/1010)) ([b686d20](https://github.com/googleapis/java-spanner-jdbc/commit/b686d20f86f2408d714e8e0335332635f10971cb)) + ## [2.7.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.8...v2.7.9) (2022-10-06) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 52eb931c480d..08d94530f72c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.10-SNAPSHOT + 2.7.10 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4cbc9f9e1627..a2d454810d1a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.10-SNAPSHOT + 2.7.10 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 04b790df14c0..f1ed31ff67d6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.9:2.7.10-SNAPSHOT +google-cloud-spanner-jdbc:2.7.10:2.7.10 From 235667bd8521bc7386f70153aca3da19bc4562e9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 17:54:17 +0000 Subject: [PATCH 0789/1979] chore(main): release 2.7.11-SNAPSHOT (#1012) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 08d94530f72c..5fc1d7ad812c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.10 + 2.7.11-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a2d454810d1a..935d5c2da06a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.10 + 2.7.11-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f1ed31ff67d6..601f596f3c51 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.10:2.7.10 +google-cloud-spanner-jdbc:2.7.10:2.7.11-SNAPSHOT From 424df9b3051f62200e9a0fd3c47c963da475a5ba Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 20 Oct 2022 04:13:08 +0200 Subject: [PATCH 0790/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.4 (#1019) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5fc1d7ad812c..fb09258dba27 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.3 + 1.5.4 From 08784492e4802a736f383c8f0de55bdc6ea0a99a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 20 Oct 2022 04:13:27 +0200 Subject: [PATCH 0791/1979] deps: update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.16 (#1018) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fb09258dba27..5062873e1794 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -391,7 +391,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.15 + 0.9.16 true From d5e17a5c5ddf564d62f7adfc95fd7751079efccf Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 20 Oct 2022 04:13:47 +0200 Subject: [PATCH 0792/1979] deps: update dependency org.graalvm.buildtools:junit-platform-native to v0.9.16 (#1017) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5062873e1794..d6a75818ed29 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -365,7 +365,7 @@ org.graalvm.buildtools junit-platform-native - 0.9.15 + 0.9.16 test From 659115886b968b53ca45af30713c198c1ad34cc7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 20 Oct 2022 03:34:13 +0000 Subject: [PATCH 0793/1979] chore(main): release 2.7.11 (#1020) :robot: I have created a release *beep* *boop* --- ## [2.7.11](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.10...v2.7.11) (2022-10-20) ### Dependencies * Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.16 ([#1017](https://togithub.com/googleapis/java-spanner-jdbc/issues/1017)) ([d5e17a5](https://togithub.com/googleapis/java-spanner-jdbc/commit/d5e17a5c5ddf564d62f7adfc95fd7751079efccf)) * Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.16 ([#1018](https://togithub.com/googleapis/java-spanner-jdbc/issues/1018)) ([0878449](https://togithub.com/googleapis/java-spanner-jdbc/commit/08784492e4802a736f383c8f0de55bdc6ea0a99a)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 083bfbfc324e..e57e6af48058 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.7.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.10...v2.7.11) (2022-10-20) + + +### Dependencies + +* Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.16 ([#1017](https://github.com/googleapis/java-spanner-jdbc/issues/1017)) ([ee7888c](https://github.com/googleapis/java-spanner-jdbc/commit/ee7888c1720aa84ca2d4278a9e52f111c298ea9d)) +* Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.16 ([#1018](https://github.com/googleapis/java-spanner-jdbc/issues/1018)) ([3d5b100](https://github.com/googleapis/java-spanner-jdbc/commit/3d5b1004eb3d4e61f954b523ef2c45d59f0fbfe0)) + ## [2.7.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.9...v2.7.10) (2022-10-18) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d6a75818ed29..81c7f294353d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.11-SNAPSHOT + 2.7.11 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 935d5c2da06a..ec4ca4b286c2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.11-SNAPSHOT + 2.7.11 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 601f596f3c51..e4eecf44ea05 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.10:2.7.11-SNAPSHOT +google-cloud-spanner-jdbc:2.7.11:2.7.11 From f7ad255b62fa692bb749ed73bdbfc2ea1158303e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 20 Oct 2022 04:56:14 +0000 Subject: [PATCH 0794/1979] chore(main): release 2.7.12-SNAPSHOT (#1021) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 81c7f294353d..e3a817df6f5f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.11 + 2.7.12-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ec4ca4b286c2..1eec16a12d9c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.11 + 2.7.12-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e4eecf44ea05..970030d0de06 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.11:2.7.11 +google-cloud-spanner-jdbc:2.7.11:2.7.12-SNAPSHOT From 8c8c07f796d60e9df836dbf362725e76bd086d06 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 24 Oct 2022 23:10:43 +0200 Subject: [PATCH 0795/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.11 (#1013) 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.7.9` -> `2.7.11` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.11/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.11/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.11/compatibility-slim/2.7.9)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.11/confidence-slim/2.7.9)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.11`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2711-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2710v2711-2022-10-20) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.10...v2.7.11) ##### Dependencies - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.16 ([#​1017](https://togithub.com/googleapis/java-spanner-jdbc/issues/1017)) ([d5e17a5](https://togithub.com/googleapis/java-spanner-jdbc/commit/d5e17a5c5ddf564d62f7adfc95fd7751079efccf)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.16 ([#​1018](https://togithub.com/googleapis/java-spanner-jdbc/issues/1018)) ([0878449](https://togithub.com/googleapis/java-spanner-jdbc/commit/08784492e4802a736f383c8f0de55bdc6ea0a99a)) ### [`v2.7.10`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2710-httpsgithubcomgoogleapisjava-spanner-jdbccomparev279v2710-2022-10-18) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.9...v2.7.10) ##### Dependencies - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.15 ([#​1009](https://togithub.com/googleapis/java-spanner-jdbc/issues/1009)) ([565d013](https://togithub.com/googleapis/java-spanner-jdbc/commit/565d013cac1fbff537d8e1a00b9c04073bfb4ae0)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.15 ([#​1010](https://togithub.com/googleapis/java-spanner-jdbc/issues/1010)) ([e73bfb4](https://togithub.com/googleapis/java-spanner-jdbc/commit/e73bfb4dba0391c70a4ffbde7e898da60d831f46))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d6ace51c4cc4..30bc6b7cdd61 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.9 + 2.7.11 From 8b1899ecb467edd97e2bda5ddb86a8bdddd06808 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 21:14:28 +0000 Subject: [PATCH 0796/1979] chore: pin versions of certifi and google-resumable-media (#1660) (#1016) chore: pin versions of certifi and google-resumable-media Source-Link: https://togithub.com/googleapis/synthtool/commit/09c4fcd0c6a0a880cf73662e118a8e8019da947c Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:264c6d5da60ff1684fbdd2b268d6a3ffca2038246e0948a06f15ca0c3cf28ce8 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 +-- java-spanner-jdbc/.kokoro/requirements.in | 2 ++ java-spanner-jdbc/.kokoro/requirements.txt | 14 +++++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 2c3ef72011b4..7649651ccd4b 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,5 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:f14e3fefe8e361e85752bd9890c8e56f2fe25f1e89cbb9597e4e3c7a429203a3 - + digest: sha256:264c6d5da60ff1684fbdd2b268d6a3ffca2038246e0948a06f15ca0c3cf28ce8 diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index cfdc2e7ed955..6aa7cf2b55ee 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -16,10 +16,12 @@ pycparser==2.21 pyperclip==1.8.2 python-dateutil==2.8.2 requests==2.27.1 +certifi==2022.9.24 importlib-metadata==4.8.3 zipp==3.6.0 google_api_core==2.8.2 google-cloud-storage==2.0.0 +google-resumable-media==2.3.3 google-cloud-core==2.3.1 typing-extensions==4.1.1 urllib3==1.26.12 diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 170f1c63abb7..02ae42bb4039 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -16,10 +16,12 @@ cachetools==4.2.4 \ # via # -r requirements.in # google-auth -certifi==2022.9.14 \ - --hash=sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5 \ - --hash=sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516 - # via requests +certifi==2022.9.24 \ + --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \ + --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382 + # via + # -r requirements.in + # requests cffi==1.15.1 \ --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ @@ -218,7 +220,9 @@ google-crc32c==1.3.0 \ google-resumable-media==2.3.3 \ --hash=sha256:27c52620bd364d1c8116eaac4ea2afcbfb81ae9139fb3199652fcac1724bfb6c \ --hash=sha256:5b52774ea7a829a8cdaa8bd2d4c3d4bc660c91b30857ab2668d0eb830f4ea8c5 - # via google-cloud-storage + # via + # -r requirements.in + # google-cloud-storage googleapis-common-protos==1.56.3 \ --hash=sha256:6f1369b58ed6cf3a4b7054a44ebe8d03b29c309257583a2bbdc064cd1e4a1442 \ --hash=sha256:87955d7b3a73e6e803f2572a33179de23989ebba725e05ea42f24838b792e461 From d5e4cb6c2feea59cbc568e67193eb31b17e98873 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Wed, 26 Oct 2022 17:25:50 -0400 Subject: [PATCH 0797/1979] fix(java): initialize classes at build-time to address native image 22.2.0 issues (#1026) * deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.5 * fix(java): initialize class at build-time to address 22.2.0 native-image issues * add junit class for built-time initialization Co-authored-by: Renovate Bot --- java-spanner-jdbc/pom.xml | 2 +- .../google-cloud-spanner-jdbc/native-image.properties | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e3a817df6f5f..bcdc41daad47 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.0.4 + 3.0.5 pom import diff --git a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties index f211d3a26461..b5754aca41dc 100644 --- a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties +++ b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties @@ -1,3 +1,6 @@ Args = --initialize-at-build-time==com.google.cloud.spanner.IntegrationTestEnv,\ com.google.cloud.spanner.jdbc.it.JdbcIntegrationTestEnv,\ - com.google.common.collect.RegularImmutableMap \ No newline at end of file + com.google.common.collect.RegularImmutableMap,\ + com.google.cloud.spanner.Dialect,\ + com.google.spanner.admin.database.v1.DatabaseDialect,\ + org.junit.runners.MethodSorters \ No newline at end of file From d72471c4669e3e0a72877c167a93a6e23201da19 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 27 Oct 2022 04:54:21 +0200 Subject: [PATCH 0798/1979] test(deps): update dependency org.mockito:mockito-core to v4.8.1 (#1023) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bcdc41daad47..348be71c9914 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.8.0 + 4.8.1 2.2 0.31.1 From a985d0959dd3fea9716b42e9582c7ad440614978 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Oct 2022 04:16:44 +0000 Subject: [PATCH 0799/1979] chore(main): release 2.7.12 (#1027) :robot: I have created a release *beep* *boop* --- ## [2.7.12](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.11...v2.7.12) (2022-10-27) ### Bug Fixes * **java:** Initialize classes at build-time to address native image 22.2.0 issues ([#1026](https://togithub.com/googleapis/java-spanner-jdbc/issues/1026)) ([d5e4cb6](https://togithub.com/googleapis/java-spanner-jdbc/commit/d5e4cb6c2feea59cbc568e67193eb31b17e98873)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e57e6af48058..ac9d2dbf6180 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.12](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.11...v2.7.12) (2022-10-27) + + +### Bug Fixes + +* **java:** Initialize classes at build-time to address native image 22.2.0 issues ([#1026](https://github.com/googleapis/java-spanner-jdbc/issues/1026)) ([8010da5](https://github.com/googleapis/java-spanner-jdbc/commit/8010da5ef539d509eb7f96d9b89edf35b2e809ad)) + ## [2.7.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.10...v2.7.11) (2022-10-20) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 348be71c9914..a6bc7dc05084 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.12-SNAPSHOT + 2.7.12 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1eec16a12d9c..77e0b8febc23 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.12-SNAPSHOT + 2.7.12 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 970030d0de06..6f1fe580c2d8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.11:2.7.12-SNAPSHOT +google-cloud-spanner-jdbc:2.7.12:2.7.12 From e9b8b3879e5baed5546d15321539dc567f0979fd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Oct 2022 05:38:16 +0000 Subject: [PATCH 0800/1979] chore(main): release 2.7.13-SNAPSHOT (#1028) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a6bc7dc05084..b2b8665beffb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.12 + 2.7.13-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 77e0b8febc23..c44b3f878117 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.12 + 2.7.13-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6f1fe580c2d8..976c54c0bf39 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.12:2.7.12 +google-cloud-spanner-jdbc:2.7.12:2.7.13-SNAPSHOT From 558e82074cdc48967499310e2124c77d89b038bf Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 28 Oct 2022 22:08:32 +0000 Subject: [PATCH 0801/1979] chore: [java] synthtool not to create an initial gitignore. (#1672) (#1031) * chore: [java] synthtool not to create an initial gitignore. Given that new generated libraries will come to the Java monorepo going forward and that any new hand-written libraries can get a new .gitignore from humans, there's no need to automatically prepare .gitignore file. * deleting gitignore * deleting .gitignore from golden Source-Link: https://togithub.com/googleapis/synthtool/commit/0baf7e4b652fcc7bf77ec341965c62c0b67e722d Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:25a679b48797fcdd98fe339c885d9595a8be5c16a275d1b466ba98e6951a3217 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/dependencies.sh | 51 --------------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 7649651ccd4b..b468b64dd72d 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:264c6d5da60ff1684fbdd2b268d6a3ffca2038246e0948a06f15ca0c3cf28ce8 + digest: sha256:25a679b48797fcdd98fe339c885d9595a8be5c16a275d1b466ba98e6951a3217 diff --git a/java-spanner-jdbc/.kokoro/dependencies.sh b/java-spanner-jdbc/.kokoro/dependencies.sh index d7476cfe9727..bd8960246f66 100755 --- a/java-spanner-jdbc/.kokoro/dependencies.sh +++ b/java-spanner-jdbc/.kokoro/dependencies.sh @@ -57,54 +57,3 @@ retry_with_backoff 3 10 \ -Dclirr.skip=true mvn -B dependency:analyze -DfailOnWarning=true - -echo "****************** DEPENDENCY LIST COMPLETENESS CHECK *******************" -## Run dependency list completeness check -function completenessCheck() { - # Output dep list with compile scope generated using the original pom - # Running mvn dependency:list on Java versions that support modules will also include the module of the dependency. - # This is stripped from the output as it is not present in the flattened pom. - # Only dependencies with 'compile' or 'runtime' scope are included from original dependency list. - msg "Generating dependency list using original pom..." - mvn dependency:list -f pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' | sed -e 's/ --.*//' >.org-list.txt - - # Output dep list generated using the flattened pom (only 'compile' and 'runtime' scopes) - msg "Generating dependency list using flattened pom..." - mvn dependency:list -f .flattened-pom.xml -DincludeScope=runtime -Dsort=true | grep '\[INFO] .*:.*:.*:.*:.*' >.new-list.txt - - # Compare two dependency lists - msg "Comparing dependency lists..." - diff .org-list.txt .new-list.txt >.diff.txt - if [[ $? == 0 ]] - then - msg "Success. No diff!" - else - msg "Diff found. See below: " - msg "You can also check .diff.txt file located in $1." - cat .diff.txt - return 1 - fi -} - -# Allow failures to continue running the script -set +e - -error_count=0 -for path in **/.flattened-pom.xml -do - # Check flattened pom in each dir that contains it for completeness - dir=$(dirname "$path") - pushd "$dir" - completenessCheck "$dir" - error_count=$(($error_count + $?)) - popd -done - -if [[ $error_count == 0 ]] -then - msg "All checks passed." - exit 0 -else - msg "Errors found. See log statements above." - exit 1 -fi From cf9f785be962d018bc2116b1fe2b2e5fa30b9482 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 29 Oct 2022 00:14:18 +0200 Subject: [PATCH 0802/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.7.12 (#1029) 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.7.11` -> `2.7.12` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.12/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.12/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.12/compatibility-slim/2.7.11)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.7.12/confidence-slim/2.7.11)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.7.12`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2712-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2711v2712-2022-10-27) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.11...v2.7.12) ##### Bug Fixes - **java:** Initialize classes at build-time to address native image 22.2.0 issues ([#​1026](https://togithub.com/googleapis/java-spanner-jdbc/issues/1026)) ([d5e4cb6](https://togithub.com/googleapis/java-spanner-jdbc/commit/d5e4cb6c2feea59cbc568e67193eb31b17e98873))
    --- ### 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, click this checkbox. --- 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 30bc6b7cdd61..cccec2749a02 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.11 + 2.7.12 From 68016ddf785257db35c3bb8df10876f7610cf5e2 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 29 Oct 2022 00:14:33 +0200 Subject: [PATCH 0803/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.4.1 (#1030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-shade-plugin](https://maven.apache.org/plugins/) | `3.4.0` -> `3.4.1` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.4.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.4.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.4.1/compatibility-slim/3.4.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-shade-plugin/3.4.1/confidence-slim/3.4.0)](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, click this checkbox. --- 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b2b8665beffb..fac5f9d49fe3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -261,7 +261,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.4.0 + 3.4.1 From 9c05d63fde99f6dcae8e8753bbeb7c280d59eacf Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 29 Oct 2022 00:56:16 +0000 Subject: [PATCH 0804/1979] chore(deps): update dependency protobuf to v3.20.2 (#1659) (#1032) Co-authored-by: Jeffrey Rennie Co-authored-by: Tomo Suzuki Source-Link: https://togithub.com/googleapis/synthtool/commit/b59cf7b5a91ecab29e21fdfbb7e3b81066229be4 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:894d56f45fc3f4f0d5f3bcf790846419ee2d8e44715eae8917d6a1bba2b7283d --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/requirements.txt | 50 ++++++++++----------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index b468b64dd72d..82b5a1a2e2e1 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:25a679b48797fcdd98fe339c885d9595a8be5c16a275d1b466ba98e6951a3217 + digest: sha256:894d56f45fc3f4f0d5f3bcf790846419ee2d8e44715eae8917d6a1bba2b7283d diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 02ae42bb4039..4a16dfadf82a 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -339,33 +339,29 @@ packaging==21.3 \ # via # -r requirements.in # gcp-releasetool -protobuf==3.19.5 \ - --hash=sha256:1867f93b06a183f87696871bb8d1e99ee71dbb69d468ce1f0cc8bf3d30f982f3 \ - --hash=sha256:3c4160b601220627f7e91154e572baf5e161a9c3f445a8242d536ee3d0b7b17c \ - --hash=sha256:4ee2af7051d3b10c8a4fe6fd1a2c69f201fea36aeee7086cf202a692e1b99ee1 \ - --hash=sha256:5266c36cc0af3bb3dbf44f199d225b33da66a9a5c3bdc2b14865ad10eddf0e37 \ - --hash=sha256:5470f892961af464ae6eaf0f3099e2c1190ae8c7f36f174b89491281341f79ca \ - --hash=sha256:66d14b5b90090353efe75c9fb1bf65ef7267383034688d255b500822e37d5c2f \ - --hash=sha256:67efb5d20618020aa9596e17bfc37ca068c28ec0c1507d9507f73c93d46c9855 \ - --hash=sha256:696e6cfab94cc15a14946f2bf72719dced087d437adbd994fff34f38986628bc \ - --hash=sha256:6a02172b9650f819d01fb8e224fc69b0706458fc1ab4f1c669281243c71c1a5e \ - --hash=sha256:6eca9ae238ba615d702387a2ddea635d535d769994a9968c09a4ca920c487ab9 \ - --hash=sha256:950abd6c00e7b51f87ae8b18a0ce4d69fea217f62f171426e77de5061f6d9850 \ - --hash=sha256:9e1d74032f56ff25f417cfe84c8147047732e5059137ca42efad20cbbd25f5e0 \ - --hash=sha256:9e42b1cf2ecd8a1bd161239e693f22035ba99905ae6d7efeac8a0546c7ec1a27 \ - --hash=sha256:9f957ef53e872d58a0afd3bf6d80d48535d28c99b40e75e6634cbc33ea42fd54 \ - --hash=sha256:a89aa0c042e61e11ade320b802d6db4ee5391d8d973e46d3a48172c1597789f8 \ - --hash=sha256:c0f80876a8ff0ae7064084ed094eb86497bd5a3812e6fc96a05318b92301674e \ - --hash=sha256:c44e3282cff74ad18c7e8a0375f407f69ee50c2116364b44492a196293e08b21 \ - --hash=sha256:d249519ba5ecf5dd6b18150c9b6bcde510b273714b696f3923ff8308fc11ae49 \ - --hash=sha256:d3973a2d58aefc7d1230725c2447ce7f86a71cbc094b86a77c6ee1505ac7cdb1 \ - --hash=sha256:dca2284378a5f2a86ffed35c6ac147d14c48b525eefcd1083e5a9ce28dfa8657 \ - --hash=sha256:e63b0b3c42e51c94add62b010366cd4979cb6d5f06158bcae8faac4c294f91e1 \ - --hash=sha256:f2b599a21c9a32e171ec29a2ac54e03297736c578698e11b099d031f79da114b \ - --hash=sha256:f2bde37667b18c2b5280df83bc799204394a5d2d774e4deaf9de0eb741df6833 \ - --hash=sha256:f4f909f4dde413dec435a44b0894956d55bb928ded7d6e3c726556ca4c796e84 \ - --hash=sha256:f976234e20ab2785f54224bcdafa027674e23663b132fa3ca0caa291a6cfbde7 \ - --hash=sha256:f9cebda093c2f6bfed88f1c17cdade09d4d96096421b344026feee236532d4de +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 # via # -r requirements.in # gcp-docuploader From 6e76867fe2d4e7fb587924ecc3e7414a42f5d9ab Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 31 Oct 2022 16:08:29 +0100 Subject: [PATCH 0805/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.32.0 (#1033) 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.31.2` -> `6.32.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.32.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.32.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.32.0/compatibility-slim/6.31.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.32.0/confidence-slim/6.31.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.32.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6320-httpsgithubcomgoogleapisjava-spannercomparev6312v6320-2022-10-27) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.31.2...v6.32.0) ##### Features - Enable client to server compression ([#​2117](https://togithub.com/googleapis/java-spanner/issues/2117)) ([50f8425](https://togithub.com/googleapis/java-spanner/commit/50f8425fe9e1db16ed060337d26feccc9a9813e2)) - Increase default number of channels when gRPC-GCP channel pool is enabled ([#​1997](https://togithub.com/googleapis/java-spanner/issues/1997)) ([44f27fc](https://togithub.com/googleapis/java-spanner/commit/44f27fc90fa3f9f4914574fb0476e971da4c02ff)) - Update result_set.proto to return undeclared parameters in ExecuteSql API ([#​2101](https://togithub.com/googleapis/java-spanner/issues/2101)) ([826eb93](https://togithub.com/googleapis/java-spanner/commit/826eb9305095db064f52a15dc502bc0e0df9a984)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.4.6 ([#​2093](https://togithub.com/googleapis/java-spanner/issues/2093)) ([b08db44](https://togithub.com/googleapis/java-spanner/commit/b08db443229afdc1d49ef9f5e459cade5e2abe90)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.5.0 ([#​2113](https://togithub.com/googleapis/java-spanner/issues/2113)) ([99d825b](https://togithub.com/googleapis/java-spanner/commit/99d825b18397ff9e8633b89effa05e61159d956f)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.6.0 ([#​2125](https://togithub.com/googleapis/java-spanner/issues/2125)) ([7d86fe4](https://togithub.com/googleapis/java-spanner/commit/7d86fe40de29311ad65bd382e55f75326d16c4e3)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.5 ([#​2122](https://togithub.com/googleapis/java-spanner/issues/2122)) ([308a65c](https://togithub.com/googleapis/java-spanner/commit/308a65c3e07e33f82b7ce474e0e95099192bb593)) - Update dependency com.google.cloud:google-cloud-trace to v2.3.7 ([#​2094](https://togithub.com/googleapis/java-spanner/issues/2094)) ([6ec3f3f](https://togithub.com/googleapis/java-spanner/commit/6ec3f3f585ed5eaecdb09d5fd1eb6c9af3b22555)) - Update dependency com.google.cloud:google-cloud-trace to v2.4.0 ([#​2114](https://togithub.com/googleapis/java-spanner/issues/2114)) ([84347f1](https://togithub.com/googleapis/java-spanner/commit/84347f1c6a52f3dfe569649f061cb16e2e466f6a)) - Update dependency com.google.cloud:google-cloud-trace to v2.5.0 ([#​2126](https://togithub.com/googleapis/java-spanner/issues/2126)) ([5167928](https://togithub.com/googleapis/java-spanner/commit/516792809cf976aeab10709ca62503b7f03bb333)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.15 ([#​2109](https://togithub.com/googleapis/java-spanner/issues/2109)) ([bf092ad](https://togithub.com/googleapis/java-spanner/commit/bf092ad7ac86c500e8a445397e192cb8fb0594ae)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.16 ([#​2119](https://togithub.com/googleapis/java-spanner/issues/2119)) ([b2d27e8](https://togithub.com/googleapis/java-spanner/commit/b2d27e8f841cab096d5ccad64a250c7f0b35f670)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.15 ([#​2110](https://togithub.com/googleapis/java-spanner/issues/2110)) ([d28b202](https://togithub.com/googleapis/java-spanner/commit/d28b202cfc29e8fbbfdf3612b94bab5c2f319419)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.16 ([#​2120](https://togithub.com/googleapis/java-spanner/issues/2120)) ([151cf77](https://togithub.com/googleapis/java-spanner/commit/151cf778ff76edaee9e849181f72119ffa6cb897)) - Update dependency org.graalvm.sdk:graal-sdk to v22.2.0.1 ([#​2102](https://togithub.com/googleapis/java-spanner/issues/2102)) ([68c2089](https://togithub.com/googleapis/java-spanner/commit/68c2089101124b9887af57b2697c35a64eb1a51f)) - Update dependency org.graalvm.sdk:graal-sdk to v22.3.0 ([#​2116](https://togithub.com/googleapis/java-spanner/issues/2116)) ([9d6930b](https://togithub.com/googleapis/java-spanner/commit/9d6930b77ec479e5f517236852244476c23dc5c8))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fac5f9d49fe3..d43f6f02cbdc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.31.2 + 6.32.0 pom import From b9eeccea0a0ad278d68b347015de5a06c2113149 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 16:28:16 +0000 Subject: [PATCH 0806/1979] chore(main): release 2.7.13 (#1036) :robot: I have created a release *beep* *boop* --- ## [2.7.13](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.12...v2.7.13) (2022-10-31) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.32.0 ([#1033](https://togithub.com/googleapis/java-spanner-jdbc/issues/1033)) ([6e76867](https://togithub.com/googleapis/java-spanner-jdbc/commit/6e76867fe2d4e7fb587924ecc3e7414a42f5d9ab)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ac9d2dbf6180..be31d7fde5bb 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.7.13](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.12...v2.7.13) (2022-10-31) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.32.0 ([#1033](https://github.com/googleapis/java-spanner-jdbc/issues/1033)) ([bbbd2c6](https://github.com/googleapis/java-spanner-jdbc/commit/bbbd2c65d75a5805965fa7f9b9dc820e62f34ad3)) + ## [2.7.12](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.11...v2.7.12) (2022-10-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d43f6f02cbdc..6bfbf522b49f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.13-SNAPSHOT + 2.7.13 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c44b3f878117..506a57ea2b4c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.13-SNAPSHOT + 2.7.13 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 976c54c0bf39..e0206c1751ab 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.12:2.7.13-SNAPSHOT +google-cloud-spanner-jdbc:2.7.13:2.7.13 From 7ec807bbbdb5a0c68b3b595605cf7c6b8995330c Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 16:52:17 +0000 Subject: [PATCH 0807/1979] Revert "chore(deps): update dependency protobuf to v3.20.2" (#1674) (#1035) Revert "chore(deps): update dependency protobuf to v3.20.2 (#1659)" This reverts commit b59cf7b5a91ecab29e21fdfbb7e3b81066229be4. Source-Link: https://togithub.com/googleapis/synthtool/commit/a66e34625d760ad299627f6613a1bd438c1b62a9 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:bd316b9a591c45264775ecaba72e37d65905925c323b68e51a08c4126e4b6d0a --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 +- java-spanner-jdbc/.kokoro/requirements.txt | 50 +++++++++++---------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 82b5a1a2e2e1..7c29609707c8 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:894d56f45fc3f4f0d5f3bcf790846419ee2d8e44715eae8917d6a1bba2b7283d + digest: sha256:bd316b9a591c45264775ecaba72e37d65905925c323b68e51a08c4126e4b6d0a + diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 4a16dfadf82a..02ae42bb4039 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -339,29 +339,33 @@ packaging==21.3 \ # via # -r requirements.in # 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.19.5 \ + --hash=sha256:1867f93b06a183f87696871bb8d1e99ee71dbb69d468ce1f0cc8bf3d30f982f3 \ + --hash=sha256:3c4160b601220627f7e91154e572baf5e161a9c3f445a8242d536ee3d0b7b17c \ + --hash=sha256:4ee2af7051d3b10c8a4fe6fd1a2c69f201fea36aeee7086cf202a692e1b99ee1 \ + --hash=sha256:5266c36cc0af3bb3dbf44f199d225b33da66a9a5c3bdc2b14865ad10eddf0e37 \ + --hash=sha256:5470f892961af464ae6eaf0f3099e2c1190ae8c7f36f174b89491281341f79ca \ + --hash=sha256:66d14b5b90090353efe75c9fb1bf65ef7267383034688d255b500822e37d5c2f \ + --hash=sha256:67efb5d20618020aa9596e17bfc37ca068c28ec0c1507d9507f73c93d46c9855 \ + --hash=sha256:696e6cfab94cc15a14946f2bf72719dced087d437adbd994fff34f38986628bc \ + --hash=sha256:6a02172b9650f819d01fb8e224fc69b0706458fc1ab4f1c669281243c71c1a5e \ + --hash=sha256:6eca9ae238ba615d702387a2ddea635d535d769994a9968c09a4ca920c487ab9 \ + --hash=sha256:950abd6c00e7b51f87ae8b18a0ce4d69fea217f62f171426e77de5061f6d9850 \ + --hash=sha256:9e1d74032f56ff25f417cfe84c8147047732e5059137ca42efad20cbbd25f5e0 \ + --hash=sha256:9e42b1cf2ecd8a1bd161239e693f22035ba99905ae6d7efeac8a0546c7ec1a27 \ + --hash=sha256:9f957ef53e872d58a0afd3bf6d80d48535d28c99b40e75e6634cbc33ea42fd54 \ + --hash=sha256:a89aa0c042e61e11ade320b802d6db4ee5391d8d973e46d3a48172c1597789f8 \ + --hash=sha256:c0f80876a8ff0ae7064084ed094eb86497bd5a3812e6fc96a05318b92301674e \ + --hash=sha256:c44e3282cff74ad18c7e8a0375f407f69ee50c2116364b44492a196293e08b21 \ + --hash=sha256:d249519ba5ecf5dd6b18150c9b6bcde510b273714b696f3923ff8308fc11ae49 \ + --hash=sha256:d3973a2d58aefc7d1230725c2447ce7f86a71cbc094b86a77c6ee1505ac7cdb1 \ + --hash=sha256:dca2284378a5f2a86ffed35c6ac147d14c48b525eefcd1083e5a9ce28dfa8657 \ + --hash=sha256:e63b0b3c42e51c94add62b010366cd4979cb6d5f06158bcae8faac4c294f91e1 \ + --hash=sha256:f2b599a21c9a32e171ec29a2ac54e03297736c578698e11b099d031f79da114b \ + --hash=sha256:f2bde37667b18c2b5280df83bc799204394a5d2d774e4deaf9de0eb741df6833 \ + --hash=sha256:f4f909f4dde413dec435a44b0894956d55bb928ded7d6e3c726556ca4c796e84 \ + --hash=sha256:f976234e20ab2785f54224bcdafa027674e23663b132fa3ca0caa291a6cfbde7 \ + --hash=sha256:f9cebda093c2f6bfed88f1c17cdade09d4d96096421b344026feee236532d4de # via # -r requirements.in # gcp-docuploader From 00576ba9018a8426449b082488d3ab110a46c3c5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 18:14:17 +0000 Subject: [PATCH 0808/1979] chore(main): release 2.7.14-SNAPSHOT (#1037) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6bfbf522b49f..271eb91e15e8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.13 + 2.7.14-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 506a57ea2b4c..be6c44eddf9e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.13 + 2.7.14-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e0206c1751ab..c4db87bc5319 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.13:2.7.13 +google-cloud-spanner-jdbc:2.7.13:2.7.14-SNAPSHOT From 24f21ce69cb2897686bc080202cfcc9b255fa326 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 4 Nov 2022 05:57:50 +0100 Subject: [PATCH 0809/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.4 (#1039) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fc7c803ad9ee..e735290da7bc 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.3 + 26.1.4 pom import From 939e25268183f8615fb161f6d74f7f66083b914c Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Fri, 4 Nov 2022 09:37:54 -0400 Subject: [PATCH 0810/1979] chore: remove native-maven-plugin 0.9.14 workaround (#1025) * chore: remove native-maven-plugin workaround --- java-spanner-jdbc/.kokoro/build.sh | 4 +- java-spanner-jdbc/pom.xml | 61 ------------------------------ 2 files changed, 2 insertions(+), 63 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 079a70384273..53a65e6fcf7f 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -71,12 +71,12 @@ integration) ;; graalvm) # Run Unit and Integration Tests with Native Image. - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.14 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; graalvm17) # Run Unit and Integration Tests with Native Image. - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative-0.9.14 -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" + mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; samples) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 271eb91e15e8..95a9b6595eff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -350,67 +350,6 @@
    - - native-0.9.14 - - - - - org.junit.vintage - junit-vintage-engine - 5.9.1 - test - - - - org.graalvm.buildtools - junit-platform-native - 0.9.16 - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - 2.22.2 - - - - - **/IT*.java - - **/*ClientTest.java - - - - - - org.graalvm.buildtools - native-maven-plugin - 0.9.16 - true - - - test-native - - test - - test - - - - - --no-fallback - - - - - - shade From 8062ba9a32b24433bcb94f41b69b88f356339c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 7 Nov 2022 14:44:14 +0100 Subject: [PATCH 0811/1979] feat: jsonb data type support (#926) Add support for the jsonb data type for PostgreSQL dialect databases. --- .../spanner/jdbc/AbstractJdbcWrapper.java | 105 ++++-- .../google/cloud/spanner/jdbc/JdbcArray.java | 3 + .../cloud/spanner/jdbc/JdbcDataType.java | 31 ++ .../spanner/jdbc/JdbcDatabaseMetaData.java | 48 ++- .../spanner/jdbc/JdbcParameterStore.java | 15 + .../cloud/spanner/jdbc/JdbcResultSet.java | 16 + .../spanner/jdbc/JdbcResultSetMetaData.java | 4 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 10 +- .../cloud/spanner/jdbc/PgJsonbType.java | 51 +++ .../DatabaseMetaData_GetColumns.sql | 2 +- .../cloud/spanner/jdbc/JdbcArrayTest.java | 19 + .../jdbc/JdbcDatabaseMetaDataTest.java | 51 +-- .../spanner/jdbc/JdbcParameterStoreTest.java | 37 +- .../jdbc/JdbcPreparedStatementTest.java | 10 +- .../jdbc/JdbcResultSetMetaDataTest.java | 356 +++++++++++++----- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 6 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 46 +++ .../spanner/jdbc/it/CreateMusicTables_PG.sql | 4 +- 18 files changed, 644 insertions(+), 170 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index ce1f84760c28..f577ac3c6586 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -41,18 +41,32 @@ abstract class AbstractJdbcWrapper implements Wrapper { */ static int extractColumnType(Type type) { Preconditions.checkNotNull(type); - if (type.equals(Type.bool())) return Types.BOOLEAN; - if (type.equals(Type.bytes())) return Types.BINARY; - if (type.equals(Type.date())) return Types.DATE; - if (type.equals(Type.float64())) return Types.DOUBLE; - if (type.equals(Type.int64())) return Types.BIGINT; - if (type.equals(Type.numeric())) return Types.NUMERIC; - if (type.equals(Type.pgNumeric())) return Types.NUMERIC; - if (type.equals(Type.string())) return Types.NVARCHAR; - if (type.equals(Type.json())) return Types.NVARCHAR; - if (type.equals(Type.timestamp())) return Types.TIMESTAMP; - if (type.getCode() == Code.ARRAY) return Types.ARRAY; - return Types.OTHER; + switch (type.getCode()) { + case BOOL: + return Types.BOOLEAN; + case BYTES: + return Types.BINARY; + case DATE: + return Types.DATE; + case FLOAT64: + return Types.DOUBLE; + case INT64: + return Types.BIGINT; + case NUMERIC: + case PG_NUMERIC: + return Types.NUMERIC; + case STRING: + case JSON: + case PG_JSONB: + return Types.NVARCHAR; + case TIMESTAMP: + return Types.TIMESTAMP; + case ARRAY: + return Types.ARRAY; + case STRUCT: + default: + return Types.OTHER; + } } /** Extract Spanner type name from {@link java.sql.Types} code. */ @@ -101,29 +115,52 @@ static String getClassName(int sqlType) { */ static String getClassName(Type type) { Preconditions.checkNotNull(type); - if (type == Type.bool()) return Boolean.class.getName(); - if (type == Type.bytes()) return byte[].class.getName(); - if (type == Type.date()) return Date.class.getName(); - if (type == Type.float64()) return Double.class.getName(); - if (type == Type.int64()) return Long.class.getName(); - if (type == Type.numeric()) return BigDecimal.class.getName(); - if (type == Type.pgNumeric()) return BigDecimal.class.getName(); - if (type == Type.string()) return String.class.getName(); - if (type == Type.json()) return String.class.getName(); - if (type == Type.timestamp()) return Timestamp.class.getName(); - if (type.getCode() == Code.ARRAY) { - if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); - if (type.getArrayElementType() == Type.bytes()) return byte[][].class.getName(); - if (type.getArrayElementType() == Type.date()) return Date[].class.getName(); - if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); - if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); - if (type.getArrayElementType() == Type.numeric()) return BigDecimal[].class.getName(); - if (type.getArrayElementType() == Type.pgNumeric()) return BigDecimal[].class.getName(); - if (type.getArrayElementType() == Type.string()) return String[].class.getName(); - if (type.getArrayElementType() == Type.json()) return String[].class.getName(); - if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); + switch (type.getCode()) { + case BOOL: + return Boolean.class.getName(); + case BYTES: + return byte[].class.getName(); + case DATE: + return Date.class.getName(); + case FLOAT64: + return Double.class.getName(); + case INT64: + return Long.class.getName(); + case NUMERIC: + case PG_NUMERIC: + return BigDecimal.class.getName(); + case STRING: + case JSON: + case PG_JSONB: + return String.class.getName(); + case TIMESTAMP: + return Timestamp.class.getName(); + case ARRAY: + switch (type.getArrayElementType().getCode()) { + case BOOL: + return Boolean[].class.getName(); + case BYTES: + return byte[][].class.getName(); + case DATE: + return Date[].class.getName(); + case FLOAT64: + return Double[].class.getName(); + case INT64: + return Long[].class.getName(); + case NUMERIC: + case PG_NUMERIC: + return BigDecimal[].class.getName(); + case STRING: + case JSON: + case PG_JSONB: + return String[].class.getName(); + case TIMESTAMP: + return Timestamp[].class.getName(); + } + case STRUCT: + default: + return null; } - return null; } /** Standard error message for out-of-range values. */ diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index f712b56ca722..650c1eb78f0e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -203,6 +203,9 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { case JSON: builder = binder.to(Value.json((String) value)); break; + case PG_JSONB: + builder = binder.to(Value.pgJsonb((String) value)); + break; case TIMESTAMP: builder = binder.to(JdbcTypeConverter.toGoogleTimestamp((Timestamp) value)); break; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 7eecb2a678d6..c495bbe1660f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -281,6 +281,37 @@ public Type getSpannerType() { return Type.json(); } }, + PG_JSONB { + @Override + public int getSqlType() { + return PgJsonbType.VENDOR_TYPE_NUMBER; + } + + @Override + public Class getJavaClass() { + return String.class; + } + + @Override + public Code getCode() { + return Code.PG_JSONB; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getPgJsonbList(columnIndex); + } + + @Override + public String getTypeName() { + return "JSONB"; + } + + @Override + public Type getSpannerType() { + return Type.pgJsonb(); + } + }, TIMESTAMP { @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 66c76b53207e..b9c7cb8639dc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -940,6 +940,7 @@ public ResultSet getTypeInfo() { StructField.of("SQL_DATETIME_SUB", Type.int64()), StructField.of("NUM_PREC_RADIX", Type.int64())), Arrays.asList( + // TODO(#925): Make these dialect-dependent (i.e. 'timestamptz' for PostgreSQL. Struct.newBuilder() .set("TYPE_NAME") .to("STRING") @@ -1243,7 +1244,52 @@ public ResultSet getTypeInfo() { .to((Long) null) .set("NUM_PREC_RADIX") .to(10) - .build()))); + .build(), + getJsonType(connection.getDialect())))); + } + + private Struct getJsonType(Dialect dialect) { + return Struct.newBuilder() + .set("TYPE_NAME") + .to(dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON") + .set("DATA_TYPE") + .to( + dialect == Dialect.POSTGRESQL + ? PgJsonbType.VENDOR_TYPE_NUMBER + : JsonType.VENDOR_TYPE_NUMBER) + .set("PRECISION") + .to(2621440L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(true) + .set("SEARCHABLE") + .to(DatabaseMetaData.typeSearchable) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to(dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 8be9e6fc3310..3ce105aa747e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -273,6 +273,7 @@ private boolean isTypeSupported(int sqlType) { case Types.NUMERIC: case Types.DECIMAL: case JsonType.VENDOR_TYPE_NUMBER: + case PgJsonbType.VENDOR_TYPE_NUMBER: return true; } return false; @@ -336,6 +337,12 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { || value instanceof InputStream || value instanceof Reader || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.JSON); + case PgJsonbType.VENDOR_TYPE_NUMBER: + return value instanceof String + || value instanceof InputStream + || value instanceof Reader + || (value instanceof Value + && ((Value) value).getType().getCode() == Type.Code.PG_JSONB); } return false; } @@ -490,6 +497,7 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } return binder.to(stringValue); case JsonType.VENDOR_TYPE_NUMBER: + case PgJsonbType.VENDOR_TYPE_NUMBER: String jsonValue; if (value instanceof String) { jsonValue = (String) value; @@ -501,6 +509,9 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, throw JdbcSqlExceptionFactory.of( value + " is not a valid JSON value", Code.INVALID_ARGUMENT); } + if (sqlType == PgJsonbType.VENDOR_TYPE_NUMBER) { + return binder.to(Value.pgJsonb(jsonValue)); + } return binder.to(Value.json(jsonValue)); case Types.DATE: if (value instanceof Date) { @@ -750,6 +761,8 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu return binder.toStringArray(null); case JsonType.VENDOR_TYPE_NUMBER: return binder.toJsonArray(null); + case PgJsonbType.VENDOR_TYPE_NUMBER: + return binder.toPgJsonbArray(null); case Types.DATE: return binder.toDateArray(null); case Types.TIME: @@ -818,6 +831,8 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (String[].class.isAssignableFrom(value.getClass())) { if (type == JsonType.VENDOR_TYPE_NUMBER) { return binder.toJsonArray(Arrays.asList((String[]) value)); + } else if (type == PgJsonbType.VENDOR_TYPE_NUMBER) { + return binder.toPgJsonbArray(Arrays.asList((String[]) value)); } else { return binder.toStringArray(Arrays.asList((String[]) value)); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 089ef7b21610..f8ab452640d5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -155,6 +155,8 @@ public String getString(int columnIndex) throws SQLException { return isNull ? null : spanner.getString(spannerIndex); case JSON: return isNull ? null : spanner.getJson(spannerIndex); + case PG_JSONB: + return isNull ? null : spanner.getPgJsonb(spannerIndex); case TIMESTAMP: return isNull ? null : spanner.getTimestamp(spannerIndex).toString(); case STRUCT: @@ -185,6 +187,7 @@ public boolean getBoolean(int columnIndex) throws SQLException { return !isNull && Boolean.parseBoolean(spanner.getString(spannerIndex)); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -219,6 +222,7 @@ public byte getByte(int columnIndex) throws SQLException { return isNull ? (byte) 0 : checkedCastToByte(parseLong(spanner.getString(spannerIndex))); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -253,6 +257,7 @@ public short getShort(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToShort(parseLong(spanner.getString(spannerIndex))); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -287,6 +292,7 @@ public int getInt(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToInt(parseLong(spanner.getString(spannerIndex))); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -319,6 +325,7 @@ public long getLong(int columnIndex) throws SQLException { return isNull ? 0L : parseLong(spanner.getString(spannerIndex)); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -349,6 +356,7 @@ public float getFloat(int columnIndex) throws SQLException { return isNull ? 0 : checkedCastToFloat(parseDouble(spanner.getString(spannerIndex))); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -379,6 +387,7 @@ public double getDouble(int columnIndex) throws SQLException { return isNull ? 0 : parseDouble(spanner.getString(spannerIndex)); case BYTES: case JSON: + case PG_JSONB: case DATE: case STRUCT: case TIMESTAMP: @@ -418,6 +427,7 @@ public Date getDate(int columnIndex) throws SQLException { case PG_NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: @@ -444,6 +454,7 @@ public Time getTime(int columnIndex) throws SQLException { case PG_NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: @@ -471,6 +482,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case PG_NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: @@ -726,6 +738,7 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) } case BYTES: case JSON: + case PG_JSONB: case DATE: case TIMESTAMP: case STRUCT: @@ -818,6 +831,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { case NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: @@ -848,6 +862,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { case NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: @@ -881,6 +896,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException case NUMERIC: case BYTES: case JSON: + case PG_JSONB: case STRUCT: case ARRAY: default: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index ae312e909715..26226bc66314 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -155,7 +155,9 @@ public int getPrecision(int column) { @Override public int getScale(int column) { int colType = getColumnType(column); - if (colType == Types.DOUBLE || colType == Types.NUMERIC) return 15; + if (colType == Types.DOUBLE || colType == Types.NUMERIC) { + return 15; + } return 0; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index f6cba1dcd20b..a506998ea6c3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -84,8 +84,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx } if (targetType.equals(byte[].class)) { if (type.getCode() == Code.BYTES) return value; - if (type.getCode() == Code.STRING || type.getCode() == Code.JSON) - return ((String) value).getBytes(UTF8); + if (type.getCode() == Code.STRING + || type.getCode() == Code.JSON + || type.getCode() == Code.PG_JSONB) return ((String) value).getBytes(UTF8); } if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; @@ -207,6 +208,9 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx toGoogleTimestamps((java.sql.Timestamp[]) ((java.sql.Array) value).getArray())); case JSON: return Value.jsonArray(Arrays.asList((String[]) ((java.sql.Array) value).getArray())); + case PG_JSONB: + return Value.pgJsonbArray( + Arrays.asList((String[]) ((java.sql.Array) value).getArray())); case STRUCT: default: throw JdbcSqlExceptionFactory.of( @@ -232,6 +236,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.timestamp(toGoogleTimestamp((java.sql.Timestamp) value)); case JSON: return Value.json((String) value); + case PG_JSONB: + return Value.pgJsonb((String) value); case STRUCT: default: throw JdbcSqlExceptionFactory.of( diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java new file mode 100644 index 000000000000..8627d341391d --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java @@ -0,0 +1,51 @@ +/* + * Copyright 2022 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.spanner.v1.TypeCode; +import java.sql.SQLType; + +public class PgJsonbType implements SQLType { + public static final PgJsonbType INSTANCE = new PgJsonbType(); + /** + * Spanner/Spangres does not have any type numbers, but the code values are unique. Add 200,000 to + * avoid conflicts with the type numbers in java.sql.Types. Native Cloud Spanner types already use + * the range starting at 100,000 (see {@link JsonType}). + */ + public static final int VENDOR_TYPE_NUMBER = 200_000 + TypeCode.JSON_VALUE; + + private PgJsonbType() {} + + @Override + public String getName() { + return "JSONB"; + } + + @Override + public String getVendor() { + return PgJsonbType.class.getPackage().getName(); + } + + @Override + public Integer getVendorTypeNumber() { + return VENDOR_TYPE_NUMBER; + } + + public String toString() { + return getName(); + } +} diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index 2c3c2e4762bf..5b37e32ecad4 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -37,7 +37,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE = 'bigint' THEN 19 WHEN DATA_TYPE = 'numeric' THEN 15 WHEN DATA_TYPE LIKE 'character varying' THEN CHARACTER_MAXIMUM_LENGTH - WHEN DATA_TYPE = 'jsonb' THEN 2621440 + WHEN DATA_TYPE = 'jsonb' THEN CHARACTER_MAXIMUM_LENGTH WHEN DATA_TYPE = 'timestamp with time zone' THEN 35 END AS "COLUMN_SIZE", 0 AS "BUFFER_LENGTH", diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 5888b3b40081..16e16ad06c35 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -169,6 +169,25 @@ public void testCreateArrayTypeName() throws SQLException { assertFalse(rs.next()); } + array = + JdbcArray.createArray( + "JSONB", + new String[] {"{}", "[]", null, "{\"name\":\"John\", \"age\":30, \"car\":null}"}); + assertThat(array.getBaseType()).isEqualTo(PgJsonbType.VENDOR_TYPE_NUMBER); + assertThat(((String[]) array.getArray(1, 1))[0]).isEqualTo("{}"); + try (ResultSet rs = array.getResultSet()) { + assertTrue(rs.next()); + assertEquals("{}", rs.getString(2)); + assertTrue(rs.next()); + assertEquals("[]", rs.getString(2)); + assertTrue(rs.next()); + assertNull(rs.getString(2)); + assertTrue(rs.wasNull()); + assertTrue(rs.next()); + assertEquals("{\"name\":\"John\", \"age\":30, \"car\":null}", rs.getString(2)); + assertFalse(rs.next()); + } + array = JdbcArray.createArray( "TIMESTAMP", diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 0d977c9959bf..6a2b0cac0605 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -22,10 +22,12 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptionsTest; import java.io.IOException; @@ -462,28 +464,33 @@ public void testGetTableTypes() throws SQLException { @Test public void testGetTypeInfo() throws SQLException { - JdbcConnection connection = mock(JdbcConnection.class); - DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); - try (ResultSet rs = meta.getTypeInfo()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("STRING"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("INT64"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("BYTES"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("FLOAT64"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("BOOL"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("DATE"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("TIMESTAMP"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TYPE_NAME"), is(equalTo("NUMERIC"))); - assertThat(rs.next(), is(false)); - ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(18))); + for (Dialect dialect : Dialect.values()) { + JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); + DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); + try (ResultSet rs = meta.getTypeInfo()) { + assertTrue(rs.next()); + assertEquals("STRING", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("INT64", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("BYTES", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("FLOAT64", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("BOOL", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("DATE", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("TIMESTAMP", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals("NUMERIC", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); + assertEquals(dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON", rs.getString("TYPE_NAME")); + assertThat(rs.next(), is(false)); + ResultSetMetaData rsmd = rs.getMetaData(); + assertThat(rsmd.getColumnCount(), is(equalTo(18))); + } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 7d966b4f6a7b..869655bb39c6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -226,6 +226,14 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(jsonString, params.getParameter(1)); verifyParameter(params, Value.json(jsonString)); + params.setParameter(1, jsonString, PgJsonbType.VENDOR_TYPE_NUMBER); + assertEquals(jsonString, params.getParameter(1)); + verifyParameter(params, Value.pgJsonb(jsonString)); + + params.setParameter(1, jsonString, PgJsonbType.INSTANCE); + assertEquals(jsonString, params.getParameter(1)); + verifyParameter(params, Value.pgJsonb(jsonString)); + params.setParameter(1, BigDecimal.ONE, Types.DECIMAL); if (dialect == Dialect.POSTGRESQL) { verifyParameter(params, Value.pgNumeric(BigDecimal.ONE.toString())); @@ -476,7 +484,8 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { Types.NCHAR, Types.NVARCHAR, Types.LONGNVARCHAR, - JsonType.VENDOR_TYPE_NUMBER + JsonType.VENDOR_TYPE_NUMBER, + PgJsonbType.VENDOR_TYPE_NUMBER }) { assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); @@ -502,7 +511,8 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { Types.NCHAR, Types.NVARCHAR, Types.LONGNVARCHAR, - JsonType.VENDOR_TYPE_NUMBER + JsonType.VENDOR_TYPE_NUMBER, + PgJsonbType.VENDOR_TYPE_NUMBER }) { Reader reader = new StringReader("test"); reader.close(); @@ -595,6 +605,10 @@ public void testSetParameterWithoutType() throws SQLException { params.setParameter(1, Value.json(jsonString), (Integer) null); assertEquals(Value.json(jsonString), params.getParameter(1)); verifyParameter(params, Value.json(jsonString)); + + params.setParameter(1, Value.pgJsonb(jsonString), (Integer) null); + assertEquals(Value.pgJsonb(jsonString), params.getParameter(1)); + verifyParameter(params, Value.pgJsonb(jsonString)); } private boolean stringReadersEqual(StringReader r1, StringReader r2) throws IOException { @@ -772,6 +786,25 @@ public void testSetArrayParameter() throws SQLException { assertEquals( Value.jsonArray(Arrays.asList(jsonString1, jsonString2, null)), params.getParameter(1)); verifyParameter(params, Value.jsonArray(Arrays.asList(jsonString1, jsonString2, null))); + + // JSONB + params.setParameter( + 1, + JdbcArray.createArray("JSONB", new String[] {jsonString1, jsonString2, null}), + Types.ARRAY); + assertEquals( + JdbcArray.createArray("JSONB", new String[] {jsonString1, jsonString2, null}), + params.getParameter(1)); + verifyParameter(params, Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null))); + + params.setParameter(1, JdbcArray.createArray("JSONB", null), Types.ARRAY); + assertEquals(JdbcArray.createArray("JSONB", null), params.getParameter(1)); + verifyParameter(params, Value.pgJsonbArray(null)); + + params.setParameter(1, Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null))); + assertEquals( + Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null)), params.getParameter(1)); + verifyParameter(params, Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null))); } private void verifyParameter(JdbcParameterStore params, Value value) throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 99f8974159cc..b4c33a802f92 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -128,6 +128,8 @@ public void testValueAsParameter() throws SQLException { Value.int64(13L), Value.numeric(new BigDecimal("3.14")), Value.string("bar"), + Value.json("{}"), + Value.pgJsonb("{}"), Value.timestamp(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(999L, 99)), Value.boolArray(Collections.singleton(true)), Value.bytesArray(Collections.singleton(ByteArray.copyFrom("foo"))), @@ -137,6 +139,8 @@ public void testValueAsParameter() throws SQLException { Value.int64Array(Collections.singleton(13L)), Value.numericArray(Collections.singleton(new BigDecimal("3.14"))), Value.stringArray(Collections.singleton("bar")), + Value.jsonArray(Collections.singleton("{}")), + Value.pgJsonbArray(Collections.singleton("{}")), Value.timestampArray( Collections.singleton(com.google.cloud.Timestamp.ofTimeSecondsAndNanos(999L, 99))), }) { @@ -152,7 +156,7 @@ public void testValueAsParameter() throws SQLException { @SuppressWarnings("deprecation") @Test public void testParameters() throws SQLException, MalformedURLException { - final int numberOfParams = 51; + final int numberOfParams = 53; String sql = generateSqlWithParameters(numberOfParams); JdbcConnection connection = createMockConnection(); @@ -204,6 +208,8 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setObject(49, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e")); ps.setObject(50, "TEST", JDBCType.NVARCHAR); ps.setObject(51, "TEST", JDBCType.NVARCHAR, 20); + ps.setObject(52, "{}", JsonType.VENDOR_TYPE_NUMBER); + ps.setObject(53, "{}", PgJsonbType.VENDOR_TYPE_NUMBER); testSetUnsupportedTypes(ps); @@ -259,6 +265,8 @@ public void testParameters() throws SQLException, MalformedURLException { assertEquals(UUID.class.getName(), pmd.getParameterClassName(49)); assertEquals(String.class.getName(), pmd.getParameterClassName(50)); assertEquals(String.class.getName(), pmd.getParameterClassName(51)); + assertEquals(String.class.getName(), pmd.getParameterClassName(51)); + assertEquals(String.class.getName(), pmd.getParameterClassName(51)); ps.clearParameters(); pmd = ps.getParameterMetaData(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java index 559ad2935888..a46a1c324030 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -27,10 +27,10 @@ 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.Type.StructField; import com.google.cloud.spanner.Value; import com.google.common.base.Preconditions; +import java.math.BigDecimal; import java.sql.Date; import java.sql.ResultSetMetaData; import java.sql.SQLException; @@ -67,15 +67,31 @@ private TestColumn(Type type, String name, Integer nulls, boolean calculated) { } private static int getDefaultSize(Type type) { - if (type == Type.bool()) return 1; - if (type == Type.date()) return 10; - if (type == Type.float64()) return 14; - if (type == Type.int64()) return 10; - if (type == Type.timestamp()) return 24; - if (type == Type.string()) return 50; - if (type == Type.json()) return 50; - if (type == Type.bytes()) return 50; - return 50; + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return 1; + case DATE: + return 10; + case FLOAT64: + return 14; + case INT64: + return 10; + case TIMESTAMP: + return 24; + case STRING: + case BYTES: + case JSON: + case PG_JSONB: + return 50; + case NUMERIC: + case PG_NUMERIC: + return 50; + case ARRAY: + case STRUCT: + default: + return 50; + } } private boolean isTableColumn() { @@ -177,7 +193,10 @@ private static List getAllTypes() { types.add(Type.int64()); types.add(Type.string()); types.add(Type.json()); + types.add(Type.pgJsonb()); types.add(Type.timestamp()); + types.add(Type.numeric()); + types.add(Type.pgNumeric()); List arrayTypes = new ArrayList<>(); for (Type type : types) { arrayTypes.add(Type.array(type)); @@ -208,42 +227,70 @@ private JdbcResultSet getFooTestResultSet(Statement statement) { } private Value getDefaultValue(Type type, int row) { - if (type == Type.bool()) return Value.bool(Boolean.TRUE); - if (type == Type.bytes()) return Value.bytes(ByteArray.copyFrom("test byte array " + row)); - if (type == Type.date()) return Value.date(com.google.cloud.Date.fromYearMonthDay(2018, 4, 1)); - if (type == Type.float64()) return Value.float64(123.45D); - if (type == Type.int64()) return Value.int64(12345L); - if (type == Type.string()) return Value.string("test value " + row); - if (type == Type.json()) return Value.json("{\"test_value\": " + row + "}"); - if (type == Type.timestamp()) return Value.timestamp(com.google.cloud.Timestamp.now()); - - if (type.getCode() == Code.ARRAY) { - if (type.getArrayElementType() == Type.bool()) - return Value.boolArray(Arrays.asList(Boolean.TRUE, Boolean.FALSE)); - if (type.getArrayElementType() == Type.bytes()) - return Value.bytesArray( - Arrays.asList( - ByteArray.copyFrom("test byte array " + row), - ByteArray.copyFrom("test byte array " + row))); - if (type.getArrayElementType() == Type.date()) - return Value.dateArray( - Arrays.asList( - com.google.cloud.Date.fromYearMonthDay(2018, 4, 1), - com.google.cloud.Date.fromYearMonthDay(2018, 4, 2))); - if (type.getArrayElementType() == Type.float64()) - return Value.float64Array(Arrays.asList(123.45D, 543.21D)); - if (type.getArrayElementType() == Type.int64()) - return Value.int64Array(Arrays.asList(12345L, 54321L)); - if (type.getArrayElementType() == Type.string()) - return Value.stringArray(Arrays.asList("test value " + row, "test value " + row)); - if (type.getArrayElementType() == Type.json()) - return Value.jsonArray( - Arrays.asList("{\"test_value\": " + row + "}", "{\"test_value\": " + row + "}")); - if (type.getArrayElementType() == Type.timestamp()) - return Value.timestampArray( - Arrays.asList(com.google.cloud.Timestamp.now(), com.google.cloud.Timestamp.now())); - } - return null; + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return Value.bool(Boolean.TRUE); + case INT64: + return Value.int64(12345L); + case NUMERIC: + return Value.numeric(new BigDecimal("3.14")); + case PG_NUMERIC: + return Value.pgNumeric("3.14"); + case FLOAT64: + return Value.float64(123.45D); + case STRING: + return Value.string("test value " + row); + case JSON: + return Value.json("{\"test_value\": " + row + "}"); + case PG_JSONB: + return Value.pgJsonb("{\"test_value\": " + row + "}"); + case BYTES: + return Value.bytes(ByteArray.copyFrom("test byte array " + row)); + case TIMESTAMP: + return Value.timestamp(com.google.cloud.Timestamp.now()); + case DATE: + return Value.date(com.google.cloud.Date.fromYearMonthDay(2018, 4, 1)); + case ARRAY: + switch (type.getArrayElementType().getCode()) { + case BOOL: + return Value.boolArray(Arrays.asList(Boolean.TRUE, Boolean.FALSE)); + case INT64: + return Value.int64Array(Arrays.asList(12345L, 54321L)); + case NUMERIC: + return Value.numericArray(Arrays.asList(BigDecimal.ONE, BigDecimal.TEN)); + case PG_NUMERIC: + return Value.pgNumericArray(Arrays.asList("3.14", null, "NaN", "6.626")); + case FLOAT64: + return Value.float64Array(Arrays.asList(123.45D, 543.21D)); + case STRING: + return Value.stringArray(Arrays.asList("test value " + row, "test value " + row)); + case JSON: + return Value.jsonArray( + Arrays.asList("{\"test_value\": " + row + "}", "{\"test_value\": " + row + "}")); + case PG_JSONB: + return Value.pgJsonbArray( + Arrays.asList("{\"test_value\": " + row + "}", "{\"test_value\": " + row + "}")); + case BYTES: + return Value.bytesArray( + Arrays.asList( + ByteArray.copyFrom("test byte array " + row), + ByteArray.copyFrom("test byte array " + row))); + case TIMESTAMP: + return Value.timestampArray( + Arrays.asList(com.google.cloud.Timestamp.now(), com.google.cloud.Timestamp.now())); + case DATE: + return Value.dateArray( + Arrays.asList( + com.google.cloud.Date.fromYearMonthDay(2018, 4, 1), + com.google.cloud.Date.fromYearMonthDay(2018, 4, 2))); + case ARRAY: + case STRUCT: + } + case STRUCT: + default: + return null; + } } @Test @@ -263,7 +310,10 @@ public void testIsCaseSensitive() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { Type type = TEST_COLUMNS.get(i - 1).type; assertEquals( - type == Type.string() || type == Type.bytes() || type == Type.json(), + type == Type.string() + || type == Type.bytes() + || type == Type.json() + || type == Type.pgJsonb(), subject.isCaseSensitive(i)); } } @@ -293,7 +343,10 @@ public void testIsNullable() { public void testIsSigned() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { Type type = TEST_COLUMNS.get(i - 1).type; - if (type == Type.int64() || type == Type.float64()) { + if (type == Type.int64() + || type == Type.float64() + || type == Type.numeric() + || type == Type.pgNumeric()) { assertTrue(subject.isSigned(i)); } else { assertFalse(subject.isSigned(i)); @@ -305,24 +358,42 @@ public void testIsSigned() { public void testGetColumnDisplaySize() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals( - getDefaultDisplaySize(TEST_COLUMNS.get(i - 1).type, i), subject.getColumnDisplaySize(i)); + "Wrong column display size for " + TEST_COLUMNS.get(i - 1).type, + getDefaultDisplaySize(TEST_COLUMNS.get(i - 1).type, i), + subject.getColumnDisplaySize(i)); } } private int getDefaultDisplaySize(Type type, int column) { - if (type.getCode() == Code.ARRAY) return 50; - if (type == Type.bool()) return 5; - if (type == Type.bytes()) return 50; - if (type == Type.date()) return 10; - if (type == Type.float64()) return 14; - if (type == Type.int64()) return 10; - if (type == Type.string()) { - int length = subject.getPrecision(column); - return length == 0 ? 50 : length; + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return 5; + case INT64: + return 10; + case NUMERIC: + case PG_NUMERIC: + return 14; + case FLOAT64: + return 14; + case STRING: + int length = subject.getPrecision(column); + return length == 0 ? 50 : length; + case JSON: + case PG_JSONB: + return 50; + case BYTES: + return 50; + case TIMESTAMP: + return 16; + case DATE: + return 10; + case ARRAY: + return 50; + case STRUCT: + default: + return 10; } - if (type == Type.json()) return 50; - if (type == Type.timestamp()) return 16; - return 10; } @Test @@ -347,18 +418,38 @@ public void testGetSchemaName() throws SQLException { @Test public void testGetPrecision() { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { - assertEquals(getPrecision(TEST_COLUMNS.get(i - 1)), subject.getPrecision(i)); + assertEquals( + "Wrong precision for type " + TEST_COLUMNS.get(i - 1).type, + getPrecision(TEST_COLUMNS.get(i - 1)), + subject.getPrecision(i)); } } private int getPrecision(TestColumn col) { - if (col.type == Type.bool()) return 1; - if (col.type == Type.date()) return 10; - if (col.type == Type.float64()) return 14; - if (col.type == Type.int64()) return 10; - if (col.type == Type.timestamp()) return 24; - if (col.isTableColumn()) return col.defaultSize; - return 50; + Preconditions.checkNotNull(col); + switch (col.type.getCode()) { + case BOOL: + return 1; + case DATE: + return 10; + case FLOAT64: + return 14; + case INT64: + return 10; + case TIMESTAMP: + return 24; + case NUMERIC: + case PG_NUMERIC: + return 14; + case STRING: + case JSON: + case PG_JSONB: + case BYTES: + case ARRAY: + case STRUCT: + default: + return col.isTableColumn() ? col.defaultSize : 50; + } } @Test @@ -369,7 +460,9 @@ public void testGetScale() { } private int getScale(TestColumn col) { - if (col.type == Type.float64()) return 15; + if (col.type == Type.float64() || col.type == Type.numeric() || col.type == Type.pgNumeric()) { + return 15; + } return 0; } @@ -393,16 +486,33 @@ public void testGetColumnType() { } private int getSqlType(Type type) { - if (type == Type.bool()) return Types.BOOLEAN; - if (type == Type.bytes()) return Types.BINARY; - if (type == Type.date()) return Types.DATE; - if (type == Type.float64()) return Types.DOUBLE; - if (type == Type.int64()) return Types.BIGINT; - if (type == Type.string()) return Types.NVARCHAR; - if (type == Type.json()) return Types.NVARCHAR; - if (type == Type.timestamp()) return Types.TIMESTAMP; - if (type.getCode() == Code.ARRAY) return Types.ARRAY; - return Types.OTHER; + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return Types.BOOLEAN; + case INT64: + return Types.BIGINT; + case NUMERIC: + case PG_NUMERIC: + return Types.NUMERIC; + case FLOAT64: + return Types.DOUBLE; + case STRING: + case JSON: + case PG_JSONB: + return Types.NVARCHAR; + case BYTES: + return Types.BINARY; + case TIMESTAMP: + return Types.TIMESTAMP; + case DATE: + return Types.DATE; + case ARRAY: + return Types.ARRAY; + case STRUCT: + default: + return Types.OTHER; + } } @Test @@ -443,25 +553,57 @@ public void testGetColumnClassName() { } private String getTypeClassName(Type type) { - if (type == Type.bool()) return Boolean.class.getName(); - if (type == Type.bytes()) return byte[].class.getName(); - if (type == Type.date()) return Date.class.getName(); - if (type == Type.float64()) return Double.class.getName(); - if (type == Type.int64()) return Long.class.getName(); - if (type == Type.string()) return String.class.getName(); - if (type == Type.json()) return String.class.getName(); - if (type == Type.timestamp()) return Timestamp.class.getName(); - if (type.getCode() == Code.ARRAY) { - if (type.getArrayElementType() == Type.bool()) return Boolean[].class.getName(); - if (type.getArrayElementType() == Type.bytes()) return byte[][].class.getName(); - if (type.getArrayElementType() == Type.date()) return Date[].class.getName(); - if (type.getArrayElementType() == Type.float64()) return Double[].class.getName(); - if (type.getArrayElementType() == Type.int64()) return Long[].class.getName(); - if (type.getArrayElementType() == Type.string()) return String[].class.getName(); - if (type.getArrayElementType() == Type.json()) return String[].class.getName(); - if (type.getArrayElementType() == Type.timestamp()) return Timestamp[].class.getName(); - } - return null; + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return Boolean.class.getName(); + case INT64: + return Long.class.getName(); + case NUMERIC: + case PG_NUMERIC: + return BigDecimal.class.getName(); + case FLOAT64: + return Double.class.getName(); + case STRING: + case JSON: + case PG_JSONB: + return String.class.getName(); + case BYTES: + return byte[].class.getName(); + case TIMESTAMP: + return Timestamp.class.getName(); + case DATE: + return Date.class.getName(); + case ARRAY: + switch (type.getArrayElementType().getCode()) { + case BOOL: + return Boolean[].class.getName(); + case INT64: + return Long[].class.getName(); + case NUMERIC: + case PG_NUMERIC: + return BigDecimal[].class.getName(); + case FLOAT64: + return Double[].class.getName(); + case STRING: + case JSON: + case PG_JSONB: + return String[].class.getName(); + case BYTES: + return byte[][].class.getName(); + case TIMESTAMP: + return Timestamp[].class.getName(); + case DATE: + return Date[].class.getName(); + case ARRAY: + case STRUCT: + default: + // fallthrough + } + case STRUCT: + default: + return null; + } } private static final String EXPECTED_TO_STRING = @@ -472,16 +614,22 @@ private String getTypeClassName(Type type) { + "Col 5: COL5 INT64\n" + "Col 6: COL6 STRING\n" + "Col 7: COL7 JSON\n" - + "Col 8: COL8 TIMESTAMP\n" - + "Col 9: COL9 ARRAY\n" - + "Col 10: COL10 ARRAY\n" - + "Col 11: COL11 ARRAY\n" + + "Col 8: COL8 PG_JSONB\n" + + "Col 9: COL9 TIMESTAMP\n" + + "Col 10: COL10 NUMERIC\n" + + "Col 11: COL11 PG_NUMERIC\n" + "Col 12: COL12 ARRAY\n" + "Col 13: COL13 ARRAY\n" + "Col 14: COL14 ARRAY\n" + "Col 15: COL15 ARRAY\n" + "Col 16: COL16 ARRAY\n" - + "Col 17: CALCULATED INT64\n"; + + "Col 17: COL17 ARRAY\n" + + "Col 18: COL18 ARRAY\n" + + "Col 19: COL19 ARRAY\n" + + "Col 20: COL20 ARRAY\n" + + "Col 21: COL21 ARRAY\n" + + "Col 22: COL22 ARRAY\n" + + "Col 23: CALCULATED INT64\n"; @Test public void testToString() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index ca13ea2c2b14..bbd37122cb60 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -129,6 +129,7 @@ private Column( new Column( "colstringmax", Types.NVARCHAR, "character varying", null, null, null, true, null), new Column("colbytes", Types.BINARY, "bytea", 10485760, null, null, false, null), + new Column("coldate", Types.DATE, "date", 10, null, null, false, null), new Column( "coltimestamp", Types.TIMESTAMP, @@ -138,7 +139,10 @@ private Column( null, true, null), - new Column("colnumeric", Types.NUMERIC, "numeric", 15, 16383, 10, false, null)); + new Column("colnumeric", Types.NUMERIC, "numeric", 15, 16383, 10, false, null), + // TODO: Update this to typeName=jsonb and colSize=2621440 + new Column( + "coljson", Types.NVARCHAR, "character varying", null, null, null, false, null)); @Test public void testGetColumns() throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index c473b6e96c2b..a452fdb0a5a7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; import com.google.cloud.ByteArray; import com.google.cloud.spanner.Database; @@ -910,6 +911,51 @@ public void test08_InsertAllColumnTypes() throws SQLException { } } + @Test + public void test08_PGInsertAllColumnTypes() throws SQLException { + assumeTrue(dialect.dialect == Dialect.POSTGRESQL); + + String sql = + "INSERT INTO TableWithAllColumnTypes (" + + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + try (Connection con = createConnection(env, database)) { + try (PreparedStatement ps = con.prepareStatement(sql)) { + int index = 0; + ps.setLong(++index, 1L); + ps.setDouble(++index, 2D); + ps.setBoolean(++index, true); + ps.setString(++index, "test"); + ps.setObject(++index, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); + ps.setBytes(++index, "test".getBytes()); + ps.setDate(++index, new Date(System.currentTimeMillis())); + ps.setTimestamp(++index, new Timestamp(System.currentTimeMillis())); + ps.setBigDecimal(++index, BigDecimal.TEN); + // TODO: This test currently uses string/varchar. This should be updated to JSONB. + ps.setObject(++index, "{\"test_value\": \"foo\"}", Types.VARCHAR); + + assertEquals(1, ps.executeUpdate()); + } + try (ResultSet rs = + con.createStatement().executeQuery("SELECT * FROM TableWithAllColumnTypes")) { + int index = 0; + assertTrue(rs.next()); + assertEquals(1L, rs.getLong(++index)); + assertEquals(2d, rs.getDouble(++index), 0.0d); + assertTrue(rs.getBoolean(++index)); + assertEquals("test", rs.getString(++index)); + assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(++index)); + assertArrayEquals("test".getBytes(), rs.getBytes(++index)); + assertNotNull(rs.getDate(++index)); + assertNotNull(rs.getTimestamp(++index)); + assertEquals(BigDecimal.TEN, rs.getBigDecimal(++index)); + assertEquals("{\"test_value\": \"foo\"}", rs.getString(++index)); + + assertFalse(rs.next()); + } + } + } + @Test public void test09_MetaData_FromQuery() throws SQLException { assumeFalse( diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index 550542318599..438d2d5df7b0 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -69,8 +69,10 @@ CREATE TABLE TableWithAllColumnTypes ( ColString VARCHAR(100) NOT NULL, ColStringMax TEXT, ColBytes BYTEA NOT NULL, + ColDate DATE NOT NULL, ColTimestamp TIMESTAMP WITH TIME ZONE, - ColNumeric NUMERIC NOT NULL + ColNumeric NUMERIC NOT NULL, + ColJson VARCHAR NOT NULL ); CREATE TABLE TableWithRef ( From bd2b50364ed1b49b36a58b94877ec9576cf12a29 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 14 Nov 2022 21:00:36 +0100 Subject: [PATCH 0812/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.6 (#1044) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 95a9b6595eff..a9626de5d750 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.0.5 + 3.0.6 pom import From 5dfd58fc903d1428b144ea1cdfd0a2527f3ae3fb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 14 Nov 2022 21:00:49 +0100 Subject: [PATCH 0813/1979] deps: update dependency io.perfmark:perfmark-api to v0.26.0 (#1045) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a9626de5d750..857e18952642 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -86,7 +86,7 @@ io.perfmark perfmark-api - 0.25.0 + 0.26.0 From 6018ff3bba079a30a2ca35ae4aa0da265c0da416 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 11:10:13 +0000 Subject: [PATCH 0814/1979] chore(java): update dependencies in java requirements file (#1695) (#1043) * chore(java): update gcp-releasetool and cryptography in java requirements file Source-Link: https://togithub.com/googleapis/synthtool/commit/74d0956884c1bb9dc901b52de35ca2bca025a74e Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:142286d973c7b6d58186070f203b50058a20a7d7b42147996db24921a18da1b0 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 +- java-spanner-jdbc/.kokoro/requirements.in | 7 +- java-spanner-jdbc/.kokoro/requirements.txt | 75 +++++++++++---------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 7c29609707c8..c8316751ebd3 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,5 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:bd316b9a591c45264775ecaba72e37d65905925c323b68e51a08c4126e4b6d0a - + digest: sha256:142286d973c7b6d58186070f203b50058a20a7d7b42147996db24921a18da1b0 diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index 6aa7cf2b55ee..9cc4a1baae11 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -1,7 +1,8 @@ -gcp-docuploader==0.6.3 +gcp-docuploader==0.6.4 google-crc32c==1.3.0 googleapis-common-protos==1.56.3 -gcp-releasetool==1.8.7 +gcp-releasetool==1.9.1 +cryptography==38.0.3 cachetools==4.2.4 cffi==1.15.1 jeepney==0.7.1 @@ -29,5 +30,5 @@ zipp==3.6.0 rsa==4.9 six==1.16.0 attrs==22.1.0 -google-auth==2.11.0 +google-auth==2.14.0 idna==3.4 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 02ae42bb4039..2dce197bf45a 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with python 3.10 # To update, run: # -# pip-compile --allow-unsafe --generate-hashes requirements.in +# pip-compile --generate-hashes requirements.in # attrs==22.1.0 \ --hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \ @@ -104,43 +104,44 @@ colorlog==6.7.0 \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 # via gcp-docuploader -cryptography==38.0.1 \ - --hash=sha256:0297ffc478bdd237f5ca3a7dc96fc0d315670bfa099c04dc3a4a2172008a405a \ - --hash=sha256:10d1f29d6292fc95acb597bacefd5b9e812099d75a6469004fd38ba5471a977f \ - --hash=sha256:16fa61e7481f4b77ef53991075de29fc5bacb582a1244046d2e8b4bb72ef66d0 \ - --hash=sha256:194044c6b89a2f9f169df475cc167f6157eb9151cc69af8a2a163481d45cc407 \ - --hash=sha256:1db3d807a14931fa317f96435695d9ec386be7b84b618cc61cfa5d08b0ae33d7 \ - --hash=sha256:3261725c0ef84e7592597606f6583385fed2a5ec3909f43bc475ade9729a41d6 \ - --hash=sha256:3b72c360427889b40f36dc214630e688c2fe03e16c162ef0aa41da7ab1455153 \ - --hash=sha256:3e3a2599e640927089f932295a9a247fc40a5bdf69b0484532f530471a382750 \ - --hash=sha256:3fc26e22840b77326a764ceb5f02ca2d342305fba08f002a8c1f139540cdfaad \ - --hash=sha256:5067ee7f2bce36b11d0e334abcd1ccf8c541fc0bbdaf57cdd511fdee53e879b6 \ - --hash=sha256:52e7bee800ec869b4031093875279f1ff2ed12c1e2f74923e8f49c916afd1d3b \ - --hash=sha256:64760ba5331e3f1794d0bcaabc0d0c39e8c60bf67d09c93dc0e54189dfd7cfe5 \ - --hash=sha256:765fa194a0f3372d83005ab83ab35d7c5526c4e22951e46059b8ac678b44fa5a \ - --hash=sha256:79473cf8a5cbc471979bd9378c9f425384980fcf2ab6534b18ed7d0d9843987d \ - --hash=sha256:896dd3a66959d3a5ddcfc140a53391f69ff1e8f25d93f0e2e7830c6de90ceb9d \ - --hash=sha256:89ed49784ba88c221756ff4d4755dbc03b3c8d2c5103f6d6b4f83a0fb1e85294 \ - --hash=sha256:ac7e48f7e7261207d750fa7e55eac2d45f720027d5703cd9007e9b37bbb59ac0 \ - --hash=sha256:ad7353f6ddf285aeadfaf79e5a6829110106ff8189391704c1d8801aa0bae45a \ - --hash=sha256:b0163a849b6f315bf52815e238bc2b2346604413fa7c1601eea84bcddb5fb9ac \ - --hash=sha256:b6c9b706316d7b5a137c35e14f4103e2115b088c412140fdbd5f87c73284df61 \ - --hash=sha256:c2e5856248a416767322c8668ef1845ad46ee62629266f84a8f007a317141013 \ - --hash=sha256:ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e \ - --hash=sha256:d1a5bd52d684e49a36582193e0b89ff267704cd4025abefb9e26803adeb3e5fb \ - --hash=sha256:d3971e2749a723e9084dd507584e2a2761f78ad2c638aa31e80bc7a15c9db4f9 \ - --hash=sha256:d4ef6cc305394ed669d4d9eebf10d3a101059bdcf2669c366ec1d14e4fb227bd \ - --hash=sha256:d9e69ae01f99abe6ad646947bba8941e896cb3aa805be2597a0400e0764b5818 +cryptography==38.0.3 \ + --hash=sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d \ + --hash=sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd \ + --hash=sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146 \ + --hash=sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7 \ + --hash=sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436 \ + --hash=sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0 \ + --hash=sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828 \ + --hash=sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b \ + --hash=sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55 \ + --hash=sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36 \ + --hash=sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50 \ + --hash=sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2 \ + --hash=sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a \ + --hash=sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8 \ + --hash=sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0 \ + --hash=sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548 \ + --hash=sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320 \ + --hash=sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748 \ + --hash=sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249 \ + --hash=sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959 \ + --hash=sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f \ + --hash=sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0 \ + --hash=sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd \ + --hash=sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220 \ + --hash=sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c \ + --hash=sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722 # via + # -r requirements.in # gcp-releasetool # secretstorage -gcp-docuploader==0.6.3 \ - --hash=sha256:ba8c9d76b3bbac54b0311c503a373b00edc2dc02d6d54ea9507045adb8e870f7 \ - --hash=sha256:c0f5aaa82ce1854a386197e4e359b120ad6d4e57ae2c812fce42219a3288026b +gcp-docuploader==0.6.4 \ + --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ + --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in -gcp-releasetool==1.8.7 \ - --hash=sha256:3d2a67c9db39322194afb3b427e9cb0476ce8f2a04033695f0aeb63979fc2b37 \ - --hash=sha256:5e4d28f66e90780d77f3ecf1e9155852b0c3b13cbccb08ab07e66b2357c8da8d +gcp-releasetool==1.9.1 \ + --hash=sha256:952f4055d5d986b070ae2a71c4410b250000f9cc5a1e26398fcd55a5bbc5a15f \ + --hash=sha256:d0d3c814a97c1a237517e837d8cfa668ced8df4b882452578ecef4a4e79c583b # via -r requirements.in google-api-core==2.8.2 \ --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \ @@ -149,9 +150,9 @@ google-api-core==2.8.2 \ # -r requirements.in # google-cloud-core # google-cloud-storage -google-auth==2.11.0 \ - --hash=sha256:be62acaae38d0049c21ca90f27a23847245c9f161ff54ede13af2cb6afecbac9 \ - --hash=sha256:ed65ecf9f681832298e29328e1ef0a3676e3732b2e56f41532d45f70a22de0fb +google-auth==2.14.0 \ + --hash=sha256:1ad5b0e6eba5f69645971abb3d2c197537d5914070a8c6d30299dfdb07c5c700 \ + --hash=sha256:cf24817855d874ede2efd071aa22125445f555de1685b739a9782fcf408c2a3d # via # -r requirements.in # gcp-releasetool From 2637471fb697c9fe86b67b9286dce3e5074f2d59 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 13:58:14 +0000 Subject: [PATCH 0815/1979] chore: update google-auth to 2.14.1 (#1703) (#1046) Co-authored-by: Anthonios Partheniou Source-Link: https://togithub.com/googleapis/synthtool/commit/9457e69470097f8e71b6b497ceece5bc423eaf3a Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:a3fe0b4c75f322520f548e535ed329df1e475ace3cb4a979b78e003cb822636a --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/requirements.in | 2 +- java-spanner-jdbc/.kokoro/requirements.txt | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index c8316751ebd3..676aaea0c74d 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:142286d973c7b6d58186070f203b50058a20a7d7b42147996db24921a18da1b0 + digest: sha256:a3fe0b4c75f322520f548e535ed329df1e475ace3cb4a979b78e003cb822636a diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index 9cc4a1baae11..ae1d92e68084 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -30,5 +30,5 @@ zipp==3.6.0 rsa==4.9 six==1.16.0 attrs==22.1.0 -google-auth==2.14.0 +google-auth==2.14.1 idna==3.4 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 2dce197bf45a..9c82529c84ff 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -150,9 +150,8 @@ google-api-core==2.8.2 \ # -r requirements.in # google-cloud-core # google-cloud-storage -google-auth==2.14.0 \ - --hash=sha256:1ad5b0e6eba5f69645971abb3d2c197537d5914070a8c6d30299dfdb07c5c700 \ - --hash=sha256:cf24817855d874ede2efd071aa22125445f555de1685b739a9782fcf408c2a3d +google-auth==2.14.1 \ + --hash=sha256:f5d8701633bebc12e0deea4df8abd8aff31c28b355360597f7f2ee60f2e4d016 # via # -r requirements.in # gcp-releasetool From 18ebc0e8582f0ef748cc53b758e5c0ca02886a68 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 15 Nov 2022 17:40:55 +0100 Subject: [PATCH 0816/1979] test(deps): update dependency org.mockito:mockito-core to v4.9.0 (#1048) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 857e18952642..36c187b4a9a0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.8.1 + 4.9.0 2.2 0.31.1 From 0656258b2afc2e232852aeb2ef433c0b97159fe3 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 15:15:59 -0500 Subject: [PATCH 0817/1979] chore(java): pom generation to look at root versions.txt (#1706) (#1049) * chore(java): pom generation to look at root versions.txt * not to include irrelevant modules in monorepo Co-authored-by: Burke Davison <40617934+burkedavison@users.noreply.github.com> Co-authored-by: Burke Davison <40617934+burkedavison@users.noreply.github.com> Source-Link: https://github.com/googleapis/synthtool/commit/909f3c8707c331ef181941fa45ad4c90c9368e85 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:a57d2ea6d1a77aa96c17ad0850b779ec6295f88b6c1da3d214b2095d140a2066 Co-authored-by: Owl Bot Co-authored-by: Burke Davison <40617934+burkedavison@users.noreply.github.com> --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/requirements.in | 2 +- java-spanner-jdbc/.kokoro/requirements.txt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 676aaea0c74d..c1e4d2da2a82 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:a3fe0b4c75f322520f548e535ed329df1e475ace3cb4a979b78e003cb822636a + digest: sha256:a57d2ea6d1a77aa96c17ad0850b779ec6295f88b6c1da3d214b2095d140a2066 diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index ae1d92e68084..924f94ae6fa1 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -1,4 +1,4 @@ -gcp-docuploader==0.6.4 +gcp-docuploader==0.6.3 google-crc32c==1.3.0 googleapis-common-protos==1.56.3 gcp-releasetool==1.9.1 diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 9c82529c84ff..71fcafc70316 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -135,9 +135,9 @@ cryptography==38.0.3 \ # -r requirements.in # gcp-releasetool # secretstorage -gcp-docuploader==0.6.4 \ - --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ - --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf +gcp-docuploader==0.6.3 \ + --hash=sha256:ba8c9d76b3bbac54b0311c503a373b00edc2dc02d6d54ea9507045adb8e870f7 \ + --hash=sha256:c0f5aaa82ce1854a386197e4e359b120ad6d4e57ae2c812fce42219a3288026b # via -r requirements.in gcp-releasetool==1.9.1 \ --hash=sha256:952f4055d5d986b070ae2a71c4410b250000f9cc5a1e26398fcd55a5bbc5a15f \ From 5955234af2f988f0adaa71bafa69a05bdac9b15e Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Thu, 17 Nov 2022 17:48:32 +0530 Subject: [PATCH 0818/1979] chore: correct spanner project reference for ITs (#1050) --- java-spanner-jdbc/.kokoro/nightly/integration.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/nightly/integration.cfg b/java-spanner-jdbc/.kokoro/nightly/integration.cfg index a2907a257b2b..e51c7b4c6c11 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration.cfg @@ -13,12 +13,12 @@ env_vars: { # TODO: remove this after we've migrated all tests and scripts env_vars: { key: "GCLOUD_PROJECT" - value: "java-docs-samples-testing" + value: "gcloud-devel" } env_vars: { key: "GOOGLE_CLOUD_PROJECT" - value: "java-docs-samples-testing" + value: "gcloud-devel" } env_vars: { From 44fc85c1650c52e3f9e7714775cb7c9279bd4683 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 17 Nov 2022 21:55:21 +0100 Subject: [PATCH 0819/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.33.0 (#1051) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 36c187b4a9a0..b12b0b51e1aa 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.32.0 + 6.33.0 pom import From ad20a88ac29dd8320609572ae98667ce604439fe Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 18 Nov 2022 03:22:13 +0530 Subject: [PATCH 0820/1979] chore: edit scope of gax dep from test to runtime (#1052) This PR reverts scope change of `gax` dependency in https://togithub.com/googleapis/java-spanner-jdbc/pull/918/files. We now set the scope to `runtime`. Fixes #1034 --- java-spanner-jdbc/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b12b0b51e1aa..7e7b1a017d3a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -107,6 +107,11 @@ com.google.api.grpc proto-google-common-protos + + com.google.api + gax + runtime + com.google.cloud google-cloud-spanner @@ -172,11 +177,6 @@ - - com.google.api - gax - test - org.hamcrest hamcrest From 22aa00eb4a24246777909ce66339d0ff3db35744 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 08:55:35 +0530 Subject: [PATCH 0821/1979] chore(main): release 2.8.0 (#1042) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index be31d7fde5bb..089c1eb229ce 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.8.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.13...v2.8.0) (2022-11-17) + + +### Features + +* Jsonb data type support ([#926](https://github.com/googleapis/java-spanner-jdbc/issues/926)) ([cefc290](https://github.com/googleapis/java-spanner-jdbc/commit/cefc290d343a2a973e1efbeee33c349fbf98060c)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.6 ([#1044](https://github.com/googleapis/java-spanner-jdbc/issues/1044)) ([3b00962](https://github.com/googleapis/java-spanner-jdbc/commit/3b0096215b63df415a44df1e2f7cb765f9022630)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.33.0 ([#1051](https://github.com/googleapis/java-spanner-jdbc/issues/1051)) ([e728ac1](https://github.com/googleapis/java-spanner-jdbc/commit/e728ac1eee0987a59ce57bc4c2f76e0c42b840a9)) +* Update dependency io.perfmark:perfmark-api to v0.26.0 ([#1045](https://github.com/googleapis/java-spanner-jdbc/issues/1045)) ([87d578c](https://github.com/googleapis/java-spanner-jdbc/commit/87d578c7408586118f1941b976330357ca658d15)) + ## [2.7.13](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.12...v2.7.13) (2022-10-31) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e7b1a017d3a..bb3fd74b4f03 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7.14-SNAPSHOT + 2.8.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index be6c44eddf9e..0532d8a3c175 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.14-SNAPSHOT + 2.8.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c4db87bc5319..104164edd8c5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.7.13:2.7.14-SNAPSHOT +google-cloud-spanner-jdbc:2.8.0:2.8.0 From e039a594426752adc45837e1f8edd06615333d5b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 04:46:36 +0000 Subject: [PATCH 0822/1979] chore(main): release 2.8.1-SNAPSHOT (#1053) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bb3fd74b4f03..96c9e70dfcaf 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.8.0 + 2.8.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0532d8a3c175..3bc9b79f38c0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.8.0 + 2.8.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 104164edd8c5..a148c5bf2e35 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.8.0:2.8.0 +google-cloud-spanner-jdbc:2.8.0:2.8.1-SNAPSHOT From 819e8802b7b0bf31f9e4d14a8805400974379258 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 18 Nov 2022 07:34:14 +0100 Subject: [PATCH 0823/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.8.0 (#1054) 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.7.12` -> `2.8.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.8.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.8.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.8.0/compatibility-slim/2.7.12)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.8.0/confidence-slim/2.7.12)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.8.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​280-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2713v280-2022-11-17) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.7.12...v2.8.0) ##### Features - Jsonb data type support ([#​926](https://togithub.com/googleapis/java-spanner-jdbc/issues/926)) ([8062ba9](https://togithub.com/googleapis/java-spanner-jdbc/commit/8062ba9a32b24433bcb94f41b69b88f356339c57)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.0.6 ([#​1044](https://togithub.com/googleapis/java-spanner-jdbc/issues/1044)) ([bd2b503](https://togithub.com/googleapis/java-spanner-jdbc/commit/bd2b50364ed1b49b36a58b94877ec9576cf12a29)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.33.0 ([#​1051](https://togithub.com/googleapis/java-spanner-jdbc/issues/1051)) ([44fc85c](https://togithub.com/googleapis/java-spanner-jdbc/commit/44fc85c1650c52e3f9e7714775cb7c9279bd4683)) - Update dependency io.perfmark:perfmark-api to v0.26.0 ([#​1045](https://togithub.com/googleapis/java-spanner-jdbc/issues/1045)) ([5dfd58f](https://togithub.com/googleapis/java-spanner-jdbc/commit/5dfd58fc903d1428b144ea1cdfd0a2527f3ae3fb))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cccec2749a02..69fc313aa094 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.7.12 + 2.8.0 From c72d76e5f58cfe288ff56d72dc98b04ed76a5983 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 21 Nov 2022 00:20:28 +0100 Subject: [PATCH 0824/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.1.5 (#1056) 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.1.4` -> `26.1.5` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.5/compatibility-slim/26.1.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.1.5/confidence-slim/26.1.4)](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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e735290da7bc..0e5a4245f66d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.4 + 26.1.5 pom import From b418b6bb00e10b5f8e48a1f7375a9ca4da6a16d3 Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Mon, 21 Nov 2022 18:30:21 +0530 Subject: [PATCH 0825/1979] feat: add tests for DML with Returning clause (#936) This PR adds tests for running DML with Returning clause using the JDBC driver, and incorporates the following: - Integration tests for running DML statements with Returning clause using PreparedStatement. - Unit tests for running DML statements with Returning clause using JdbcStatement, for each of the available JDBC APIs `execute`, `executeUpdate`, `executeQuery`, `executeBatchUpdate`. - The JDBC driver does not require any code changes for supporting DML with Returning clause, as all the required changes will be made in the Connection API (Connection API changes are being tracked at https://togithub.com/googleapis/java-spanner/pull/1978). --- .../cloud/spanner/jdbc/JdbcStatement.java | 2 +- .../cloud/spanner/jdbc/JdbcStatementTest.java | 93 ++++++++++- .../jdbc/it/ITJdbcPreparedStatementTest.java | 144 ++++++++++++++++++ 3 files changed, 237 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index f37eb21a80d3..051ed9d6d22f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -87,7 +87,7 @@ public long executeLargeUpdate(String sql) throws SQLException { switch (result.getResultType()) { case RESULT_SET: throw JdbcSqlExceptionFactory.of( - "The statement is not an update or DDL statement", Code.INVALID_ARGUMENT); + "The statement is not a non-returning DML or DDL statement", Code.INVALID_ARGUMENT); case UPDATE_COUNT: return result.getUpdateCount(); case NO_RESULT: diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 3ee9edcb6bd9..c7b6a6cbde12 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -17,6 +17,12 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.anyList; import static org.mockito.Mockito.mock; @@ -53,6 +59,8 @@ public class JdbcStatementTest { private static final String SELECT = "SELECT 1"; private static final String UPDATE = "UPDATE FOO SET BAR=1 WHERE BAZ=2"; private static final String LARGE_UPDATE = "UPDATE FOO SET BAR=1 WHERE 1=1"; + private static final String DML_RETURNING_GSQL = "UPDATE FOO SET BAR=1 WHERE 1=1 THEN RETURN *"; + private static final String DML_RETURNING_PG = "UPDATE FOO SET BAR=1 WHERE 1=1 RETURNING *"; private static final String DDL = "CREATE INDEX FOO ON BAR(ID)"; @Parameter public Dialect dialect; @@ -62,11 +70,20 @@ public static Object[] data() { return Dialect.values(); } + private String getDmlReturningSql() { + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + return DML_RETURNING_GSQL; + } + return DML_RETURNING_PG; + } + @SuppressWarnings("unchecked") private JdbcStatement createStatement() throws SQLException { Connection spanner = mock(Connection.class); when(spanner.getDialect()).thenReturn(dialect); + final String DML_RETURNING_SQL = getDmlReturningSql(); + com.google.cloud.spanner.ResultSet resultSet = mock(com.google.cloud.spanner.ResultSet.class); when(resultSet.next()).thenReturn(true, false); when(resultSet.getColumnType(0)).thenReturn(Type.int64()); @@ -88,6 +105,19 @@ private JdbcStatement createStatement() throws SQLException { when(spanner.execute(com.google.cloud.spanner.Statement.of(LARGE_UPDATE))) .thenReturn(largeUpdateResult); + com.google.cloud.spanner.ResultSet dmlReturningResultSet = + mock(com.google.cloud.spanner.ResultSet.class); + when(dmlReturningResultSet.next()).thenReturn(true, false); + when(dmlReturningResultSet.getColumnCount()).thenReturn(1); + when(dmlReturningResultSet.getColumnType(0)).thenReturn(Type.int64()); + when(dmlReturningResultSet.getLong(0)).thenReturn(1L); + + StatementResult dmlReturningResult = mock(StatementResult.class); + when(dmlReturningResult.getResultType()).thenReturn(ResultType.RESULT_SET); + when(dmlReturningResult.getResultSet()).thenReturn(dmlReturningResultSet); + when(spanner.execute(com.google.cloud.spanner.Statement.of(DML_RETURNING_SQL))) + .thenReturn(dmlReturningResult); + StatementResult ddlResult = mock(StatementResult.class); when(ddlResult.getResultType()).thenReturn(ResultType.NO_RESULT); when(spanner.execute(com.google.cloud.spanner.Statement.of(DDL))).thenReturn(ddlResult); @@ -96,6 +126,8 @@ private JdbcStatement createStatement() throws SQLException { when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(UPDATE))) .thenThrow( SpannerExceptionFactory.newSpannerException(ErrorCode.INVALID_ARGUMENT, "not a query")); + when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(DML_RETURNING_SQL))) + .thenReturn(dmlReturningResultSet); when(spanner.executeQuery(com.google.cloud.spanner.Statement.of(DDL))) .thenThrow( SpannerExceptionFactory.newSpannerException(ErrorCode.INVALID_ARGUMENT, "not a query")); @@ -109,6 +141,10 @@ private JdbcStatement createStatement() throws SQLException { .thenThrow( SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, "not an update")); + when(spanner.executeUpdate(com.google.cloud.spanner.Statement.of(DML_RETURNING_SQL))) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.FAILED_PRECONDITION, "cannot execute dml returning over executeUpdate")); when(spanner.executeBatchUpdate(anyList())) .thenAnswer( @@ -219,6 +255,20 @@ public void testExecuteWithDdlStatement() throws SQLException { assertThat(statement.getUpdateCount()).isEqualTo(JdbcConstants.STATEMENT_NO_RESULT); } + @Test + public void testExecuteWithDmlReturningStatement() throws SQLException { + Statement statement = createStatement(); + boolean res = statement.execute(getDmlReturningSql()); + assertTrue(res); + assertEquals(statement.getUpdateCount(), JdbcConstants.STATEMENT_RESULT_SET); + try (ResultSet rs = statement.getResultSet()) { + assertNotNull(rs); + assertTrue(rs.next()); + assertEquals(rs.getLong(1), 1L); + assertFalse(rs.next()); + } + } + @Test public void testExecuteWithGeneratedKeys() throws SQLException { Statement statement = createStatement(); @@ -257,6 +307,17 @@ public void testExecuteQueryWithUpdateStatement() { } } + @Test + public void testExecuteQueryWithDmlReturningStatement() throws SQLException { + Statement statement = createStatement(); + try (ResultSet rs = statement.executeQuery(getDmlReturningSql())) { + assertNotNull(rs); + assertTrue(rs.next()); + assertEquals(rs.getLong(1), 1L); + assertFalse(rs.next()); + } + } + @Test public void testExecuteQueryWithDdlStatement() { try { @@ -353,12 +414,29 @@ public void testExecuteUpdateWithSelectStatement() { } catch (SQLException e) { assertThat( JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, "The statement is not an update or DDL statement") + Code.INVALID_ARGUMENT, + "The statement is not a non-returning DML or DDL statement") .matches(e)) .isTrue(); } } + @Test + public void testExecuteUpdateWithDmlReturningStatement() { + try { + Statement statement = createStatement(); + SQLException e = + assertThrows(SQLException.class, () -> statement.executeUpdate(getDmlReturningSql())); + assertTrue( + JdbcExceptionMatcher.matchCodeAndMessage( + Code.INVALID_ARGUMENT, + "The statement is not a non-returning DML or DDL statement") + .matches(e)); + } catch (SQLException e) { + // ignore exception. + } + } + @Test public void testExecuteUpdateWithDdlStatement() throws SQLException { Statement statement = createStatement(); @@ -438,6 +516,19 @@ public void testDmlBatch() throws SQLException { } } + @Test + public void testDmlBatchWithDmlReturning() throws SQLException { + try (Statement statement = createStatement()) { + // Verify that multiple batches can be executed on the same statement. + for (int i = 0; i < 2; i++) { + statement.addBatch(getDmlReturningSql()); + statement.addBatch(getDmlReturningSql()); + statement.addBatch(getDmlReturningSql()); + assertArrayEquals(statement.executeBatch(), new int[] {1, 1, 1}); + } + } + } + @Test public void testLargeDmlBatch() throws SQLException { try (Statement statement = createStatement()) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index a452fdb0a5a7..c1d841696195 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -36,6 +36,7 @@ import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; +import com.google.common.io.CharStreams; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -263,6 +264,24 @@ private void setPreparedStatement(Connection connection, PreparedStatement ps, D ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices)); } } + + private void assertEqualsFields(Connection connection, ResultSet rs, Dialect dialect) + throws SQLException { + assertEquals(rs.getLong(1), this.venueId); + assertEquals(rs.getLong(2), this.singerId); + if (dialect == Dialect.POSTGRESQL) { + assertEquals(rs.getString(3), this.concertDate.toString()); + assertEquals(rs.getString(4), this.beginTime.toString()); + assertEquals(rs.getString(5), this.endTime.toString()); + } else { + assertEquals(rs.getDate(3), this.concertDate); + assertEquals(rs.getTimestamp(4), this.beginTime); + assertEquals(rs.getTimestamp(5), this.endTime); + assertArrayEquals( + (Object[]) rs.getArray(6).getArray(), + (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray()); + } + } } private static Date parseDate(String value) { @@ -333,6 +352,34 @@ private String getConcertsInsertQuery(Dialect dialect) { return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);"; } + private String getConcertsInsertReturningQuery(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?) RETURNING *;"; + } + return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) THEN RETURN *;"; + } + + private String getSingersInsertReturningQuery(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?) RETURNING *"; + } + return "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?) THEN RETURN *"; + } + + private String getAlbumsInsertReturningQuery(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?) RETURNING *"; + } + return "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?) THEN RETURN *"; + } + + private String getSongsInsertReturningQuery(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) RETURNING *;"; + } + return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) THEN RETURN *;"; + } + private int getConcertExpectedParamCount(Dialect dialect) { if (dialect == Dialect.POSTGRESQL) { return 5; @@ -1150,6 +1197,103 @@ private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedP } } + @Test + public void test12_InsertReturningTestData() throws SQLException { + assumeFalse( + "Emulator does not support DML with returning clause", + EmulatorSpannerHelper.isUsingEmulator()); + try (Connection connection = createConnection(env, database)) { + connection.setAutoCommit(false); + // Delete existing rows from tables populated by other tests, + // so that this test can populate rows from scratch. + Statement deleteStatements = connection.createStatement(); + deleteStatements.addBatch("DELETE FROM Concerts WHERE TRUE"); + deleteStatements.addBatch("DELETE FROM Songs WHERE TRUE"); + deleteStatements.addBatch("DELETE FROM Albums WHERE TRUE"); + deleteStatements.addBatch("DELETE FROM Singers WHERE TRUE"); + deleteStatements.executeBatch(); + try (PreparedStatement ps = + connection.prepareStatement(getSingersInsertReturningQuery(dialect.dialect))) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 5); + for (Singer singer : createSingers()) { + singer.setPreparedStatement(ps, getDialect()); + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); + ps.addBatch(); + // check that adding the current params to a batch will not reset the metadata + assertInsertSingerParameterMetadata(ps.getParameterMetaData()); + } + int[] results = ps.executeBatch(); + for (int res : results) { + assertEquals(1, res); + } + } + try (PreparedStatement ps = + connection.prepareStatement(getAlbumsInsertReturningQuery(dialect.dialect))) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 4); + for (Album album : createAlbums()) { + ps.setLong(1, album.singerId); + ps.setLong(2, album.albumId); + ps.setString(3, album.albumTitle); + ps.setLong(4, album.marketingBudget); + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getLong(1), album.singerId); + assertEquals(rs.getLong(2), album.albumId); + assertEquals(rs.getString(3), album.albumTitle); + assertEquals(rs.getLong(4), album.marketingBudget); + } + // check that calling executeQuery will not reset the metadata + assertInsertAlbumParameterMetadata(ps.getParameterMetaData()); + } + } + try (PreparedStatement ps = + connection.prepareStatement(getSongsInsertReturningQuery(dialect.dialect))) { + assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + for (Song song : createSongs()) { + ps.setByte(1, (byte) song.singerId); + ps.setInt(2, (int) song.albumId); + ps.setShort(3, (short) song.songId); + ps.setNString(4, song.songName); + ps.setLong(5, song.duration); + ps.setCharacterStream(6, new StringReader(song.songGenre)); + assertInsertSongParameterMetadata(ps.getParameterMetaData()); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + assertEquals(rs.getByte(1), (byte) song.singerId); + assertEquals(rs.getInt(2), (int) song.albumId); + assertEquals(rs.getShort(3), (short) song.songId); + assertEquals(rs.getNString(4), song.songName); + assertEquals(rs.getLong(5), song.duration); + assertEquals( + CharStreams.toString(rs.getCharacterStream(6)), + CharStreams.toString(new StringReader(song.songGenre))); + } + // check that calling executeQuery will not reset the metadata + assertInsertSongParameterMetadata(ps.getParameterMetaData()); + } + } catch (IOException e) { + // ignore exception. + } + try (PreparedStatement ps = + connection.prepareStatement(getConcertsInsertReturningQuery(dialect.dialect))) { + assertDefaultParameterMetaData( + ps.getParameterMetaData(), getConcertExpectedParamCount(dialect.dialect)); + for (Concert concert : createConcerts()) { + concert.setPreparedStatement(connection, ps, getDialect()); + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); + try (ResultSet rs = ps.executeQuery()) { + rs.next(); + concert.assertEqualsFields(connection, rs, dialect.dialect); + } + // check that calling executeQuery will not reset the meta data + assertInsertConcertParameterMetadata(ps.getParameterMetaData()); + } + } + connection.commit(); + } + } + private List readValuesFromFile(String filename) { StringBuilder builder = new StringBuilder(); try (InputStream stream = ITJdbcPreparedStatementTest.class.getResourceAsStream(filename)) { From 766802cee6601622ac841cd39e2e3cdf6ab768b0 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 10:19:48 +0530 Subject: [PATCH 0826/1979] chore: upgrade native image checks to graalvm-22.3.0 (#1718) (#1066) chore: upgrade native image checks to graalvm-22.3.0 Source-Link: https://github.com/googleapis/synthtool/commit/5e52896b69b145a3fac6827e4e75e617abdc9dd8 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:27b1b1884dce60460d7521b23c2a73376cba90c0ef3d9f0d32e4bdb786959cfd Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index c1e4d2da2a82..4ca0036da327 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:a57d2ea6d1a77aa96c17ad0850b779ec6295f88b6c1da3d214b2095d140a2066 + digest: sha256:27b1b1884dce60460d7521b23c2a73376cba90c0ef3d9f0d32e4bdb786959cfd diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index a3f7fb9d4943..e20330c3ca60 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.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" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm17:22.3.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 4c7225ec924e..0fd6ba2fa0ce 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.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" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm:22.3.0" } env_vars: { From 3620777e7c1d6f6fcf1261555a998ca3339e7a7f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 7 Dec 2022 09:54:01 +0100 Subject: [PATCH 0827/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.5 (#1068) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 96c9e70dfcaf..9bad1258de93 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.4 + 1.5.5 From a74f257487a6bfca1dfa2fb92672d8c3c2f2e4b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 06:25:13 +0530 Subject: [PATCH 0828/1979] build(deps): bump certifi from 2022.9.24 to 2022.12.7 in /.kokoro (#1070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump certifi from 2022.9.24 to 2022.12.7 in /.kokoro Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.9.24 to 2022.12.7. - [Release notes](https://github.com/certifi/python-certifi/releases) - [Commits](https://github.com/certifi/python-certifi/compare/2022.09.24...2022.12.07) --- updated-dependencies: - dependency-name: certifi dependency-type: direct:production ... 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 4cf8512c73b99c27d0b880efc5757c6efc11b971 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 23:35:57 +0530 Subject: [PATCH 0829/1979] build(deps): bump certifi from 2022.9.24 to 2022.12.7 in /synthtool/gcp/templates/java_library/.kokoro (#1732) (#1071) build(deps): bump certifi Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.9.24 to 2022.12.7. - [Release notes](https://github.com/certifi/python-certifi/releases) - [Commits](https://github.com/certifi/python-certifi/compare/2022.09.24...2022.12.07) --- updated-dependencies: - dependency-name: certifi dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jeff Ching Source-Link: https://github.com/googleapis/synthtool/commit/ae0d43e5f17972981fe501ecf5a5d20055128bea Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:9de537d592b60e5eac73b374a28263969bae91ecdb29b445e894576fbf54851c Signed-off-by: dependabot[bot] Co-authored-by: Owl Bot Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jeff Ching --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/requirements.in | 2 +- java-spanner-jdbc/.kokoro/requirements.txt | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 4ca0036da327..288e394897e6 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:27b1b1884dce60460d7521b23c2a73376cba90c0ef3d9f0d32e4bdb786959cfd + digest: sha256:9de537d592b60e5eac73b374a28263969bae91ecdb29b445e894576fbf54851c diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index 924f94ae6fa1..a5010f77d413 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -17,7 +17,7 @@ pycparser==2.21 pyperclip==1.8.2 python-dateutil==2.8.2 requests==2.27.1 -certifi==2022.9.24 +certifi==2022.12.7 importlib-metadata==4.8.3 zipp==3.6.0 google_api_core==2.8.2 diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 71fcafc70316..15c404aa5a8c 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -16,9 +16,9 @@ cachetools==4.2.4 \ # via # -r requirements.in # google-auth -certifi==2022.9.24 \ - --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \ - --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via # -r requirements.in # requests From 4f4ab660853db814edfccaf0f66e0f9740943726 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Dec 2022 19:12:15 +0100 Subject: [PATCH 0830/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.34.1 (#1072) 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.33.0` -> `6.34.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.34.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.34.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.34.1/compatibility-slim/6.33.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.34.1/confidence-slim/6.33.0)](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**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **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). --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9bad1258de93..27d8badf0299 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,14 +62,14 @@ com.google.cloud google-cloud-spanner-bom - 6.33.0 + 6.34.1 pom import com.google.cloud google-cloud-shared-dependencies - 3.0.6 + 3.1.0 pom import From 88c5864bd9dc22c91415ad5b8f351555f7c82cba Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Dec 2022 19:28:27 +0100 Subject: [PATCH 0831/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.0 (#1069) Co-authored-by: Tomo Suzuki From 496dfb713d43cc3083093fa5ffab4ea816787b92 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 02:18:00 +0530 Subject: [PATCH 0832/1979] chore(main): release 2.9.0 (#1057) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 089c1eb229ce..b23d783c391c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.9.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.8.0...v2.9.0) (2022-12-14) + + +### Features + +* Add tests for DML with Returning clause ([#936](https://github.com/googleapis/java-spanner-jdbc/issues/936)) ([8a86467](https://github.com/googleapis/java-spanner-jdbc/commit/8a86467c6db7a4e99fdf23cdbce2d78382f8cde9)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.0 ([#1069](https://github.com/googleapis/java-spanner-jdbc/issues/1069)) ([c2ff33a](https://github.com/googleapis/java-spanner-jdbc/commit/c2ff33a8f6a7051e1639fee235e1b6bba5916c3a)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.34.1 ([#1072](https://github.com/googleapis/java-spanner-jdbc/issues/1072)) ([0045a5e](https://github.com/googleapis/java-spanner-jdbc/commit/0045a5e51c5a40523f70ec22c9b75bc8707dccb7)) + ## [2.8.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.7.13...v2.8.0) (2022-11-17) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 27d8badf0299..fd691251dc34 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.8.1-SNAPSHOT + 2.9.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3bc9b79f38c0..b39196d3e647 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.8.1-SNAPSHOT + 2.9.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a148c5bf2e35..11ecba39de2a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.8.0:2.8.1-SNAPSHOT +google-cloud-spanner-jdbc:2.9.0:2.9.0 From 15dfb2c24803173032e785f2c69fac8ad5f02c3a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 22:16:14 +0000 Subject: [PATCH 0833/1979] chore(main): release 2.9.1-SNAPSHOT (#1073) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd691251dc34..e37fec8109d6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.0 + 2.9.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b39196d3e647..ffe3442076c8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.0 + 2.9.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 11ecba39de2a..48903a0a99de 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.0:2.9.0 +google-cloud-spanner-jdbc:2.9.0:2.9.1-SNAPSHOT From 954fc51b528805278fc89fccfa7237aa33b33156 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 15 Dec 2022 00:40:15 +0100 Subject: [PATCH 0834/1979] test(deps): update dependency org.mockito:mockito-core to v4.10.0 (#1075) 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.mockito:mockito-core](https://togithub.com/mockito/mockito) | `4.9.0` -> `4.10.0` | [![age](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.10.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.10.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.10.0/compatibility-slim/4.9.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.mockito:mockito-core/4.10.0/confidence-slim/4.9.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mockito/mockito ### [`v4.10.0`](https://togithub.com/mockito/mockito/releases/tag/v4.10.0) [Compare Source](https://togithub.com/mockito/mockito/compare/v4.9.0...v4.10.0) *Changelog generated by [Shipkit Changelog Gradle Plugin](https://togithub.com/shipkit/shipkit-changelog)* ##### 4.10.0 - 2022-12-14 - [13 commit(s)](https://togithub.com/mockito/mockito/compare/v4.9.0...v4.10.0) by Andrei Solntsev, Andriy Redko, Andy Coates, Christopher Lambert, Marcono1234, Vladimir Glinskikh, dependabot\[bot] - Add new artifact mockito-subclass (to use mock-maker-subclass MockMaker) [(#​2821)](https://togithub.com/mockito/mockito/pull/2821) - Bump gradle from 7.5.1 to 7.6 [(#​2817)](https://togithub.com/mockito/mockito/pull/2817) - Fix incorrect Javadoc inline tag for MockitoJUnitRunner [(#​2816)](https://togithub.com/mockito/mockito/pull/2816) - Bump shipkit-auto-version from 1.2.1 to 1.2.2 [(#​2811)](https://togithub.com/mockito/mockito/pull/2811) - Bump com.github.ben-manes.versions from 0.42.0 to 0.44.0 [(#​2810)](https://togithub.com/mockito/mockito/pull/2810) - Bump kotlinVersion from 1.7.21 to 1.7.22 [(#​2809)](https://togithub.com/mockito/mockito/pull/2809) - Bump junit from 1.1.3 to 1.1.4 [(#​2806)](https://togithub.com/mockito/mockito/pull/2806) - Simplify `MatcherApplicationStrategy` [(#​2803)](https://togithub.com/mockito/mockito/pull/2803) - Bump kotlinVersion from 1.7.10 to 1.7.21 [(#​2801)](https://togithub.com/mockito/mockito/pull/2801) - Bump espresso-core from 3.4.0 to 3.5.0 [(#​2800)](https://togithub.com/mockito/mockito/pull/2800) - Bump versions.bytebuddy from 1.12.16 to 1.12.19 [(#​2799)](https://togithub.com/mockito/mockito/pull/2799) - Upgrade errorprone from 2.14.0 to 2.16 [(#​2794)](https://togithub.com/mockito/mockito/pull/2794) - automatically detect class to mock [(#​2779)](https://togithub.com/mockito/mockito/pull/2779)
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e37fec8109d6..9891bd501864 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.9.0 + 4.10.0 2.2 0.31.1 From 0d1a022852d73f8bafee41f1b5c094ec85c59b66 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 15 Dec 2022 00:42:14 +0100 Subject: [PATCH 0835/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.0 (#1074) 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.8.0` -> `2.9.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.0/compatibility-slim/2.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.0/confidence-slim/2.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.9.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​290-httpsgithubcomgoogleapisjava-spanner-jdbccomparev280v290-2022-12-14) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.8.0...v2.9.0) ##### Features - Add tests for DML with Returning clause ([#​936](https://togithub.com/googleapis/java-spanner-jdbc/issues/936)) ([b418b6b](https://togithub.com/googleapis/java-spanner-jdbc/commit/b418b6bb00e10b5f8e48a1f7375a9ca4da6a16d3)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.0 ([#​1069](https://togithub.com/googleapis/java-spanner-jdbc/issues/1069)) ([88c5864](https://togithub.com/googleapis/java-spanner-jdbc/commit/88c5864bd9dc22c91415ad5b8f351555f7c82cba)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.34.1 ([#​1072](https://togithub.com/googleapis/java-spanner-jdbc/issues/1072)) ([4f4ab66](https://togithub.com/googleapis/java-spanner-jdbc/commit/4f4ab660853db814edfccaf0f66e0f9740943726))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 69fc313aa094..bd1a77ed128d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.8.0 + 2.9.0 From f64783fc0d47d3b1e63abfdcc8a09ede3cc223d7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Dec 2022 07:29:09 +0100 Subject: [PATCH 0836/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.2.0 (#1076) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0e5a4245f66d..9eb6742eb6de 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.1.5 + 26.2.0 pom import From 5b4a78effe8d575e967e9d54d76a7b1d0f4ce94d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Jan 2023 05:13:56 +0000 Subject: [PATCH 0837/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.3.0 (#1087) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 9eb6742eb6de..c423c8485b00 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.2.0 + 26.3.0 pom import From 8e636e7c3adda3215d6ae96647284b78362f8963 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Jan 2023 06:36:36 +0000 Subject: [PATCH 0838/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.2 (#1089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.4.1` -> `3.4.2` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.2/compatibility-slim/3.4.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.4.2/confidence-slim/3.4.1)](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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9891bd501864..f8f689be8946 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -398,7 +398,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.1 + 3.4.2 From 02e35b5114659630395b45d945a1ba9937bf1365 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Jan 2023 06:40:13 +0000 Subject: [PATCH 0839/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.1 (#1090) 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/java-shared-dependencies) | `3.1.0` -> `3.1.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.1.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.1.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.1.1/compatibility-slim/3.1.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.1.1/confidence-slim/3.1.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-shared-dependencies ### [`v3.1.1`](https://togithub.com/googleapis/java-shared-dependencies/blob/HEAD/CHANGELOG.md#​311-httpsgithubcomgoogleapisjava-shared-dependenciescomparev310v311-2023-01-09) [Compare Source](https://togithub.com/googleapis/java-shared-dependencies/compare/v3.1.0...v3.1.1) ##### Dependencies - Adding `gapic-generator-java-bom` to `first-party-dependencies` ([#​957](https://togithub.com/googleapis/java-shared-dependencies/issues/957)) ([f051e6e](https://togithub.com/googleapis/java-shared-dependencies/commit/f051e6ee0ad4a705014d9d2f8211ddad464b3ca4)) - Update dependency com.google.api-client:google-api-client-bom to v2.1.2 ([#​956](https://togithub.com/googleapis/java-shared-dependencies/issues/956)) ([dbfde36](https://togithub.com/googleapis/java-shared-dependencies/commit/dbfde36f5b0806192ea99d45382c84cff518f500)) - Update dependency com.google.api:api-common to v2.3.1 ([#​947](https://togithub.com/googleapis/java-shared-dependencies/issues/947)) ([f35c3bf](https://togithub.com/googleapis/java-shared-dependencies/commit/f35c3bf518e8b488ddeb28a6ff86719b24a62df5)) - Update dependency com.google.auth:google-auth-library-bom to v1.14.0 ([#​950](https://togithub.com/googleapis/java-shared-dependencies/issues/950)) ([e5609ca](https://togithub.com/googleapis/java-shared-dependencies/commit/e5609ca23657e1c37825c6d8930da1fb5080b8a6)) - Update dependency com.google.code.gson:gson to v2.10.1 ([#​958](https://togithub.com/googleapis/java-shared-dependencies/issues/958)) ([bd35327](https://togithub.com/googleapis/java-shared-dependencies/commit/bd353274c16d01915923a6fa34796d0b78672fb0)) - Update dependency com.google.errorprone:error_prone_annotations to v2.17.0 ([#​955](https://togithub.com/googleapis/java-shared-dependencies/issues/955)) ([b656786](https://togithub.com/googleapis/java-shared-dependencies/commit/b6567863e659ff3eb6cc7b4b42a42acc7ebd24ed)) - Update dependency com.google.errorprone:error_prone_annotations to v2.18.0 ([#​961](https://togithub.com/googleapis/java-shared-dependencies/issues/961)) ([0c4ff89](https://togithub.com/googleapis/java-shared-dependencies/commit/0c4ff895e103164dc0c95bc9789f9a3dc6c2f1a4)) - Update dependency com.google.protobuf:protobuf-bom to v3.21.12 ([#​948](https://togithub.com/googleapis/java-shared-dependencies/issues/948)) ([812ce38](https://togithub.com/googleapis/java-shared-dependencies/commit/812ce38e95de4db15184f9dd38bbd4c2affa2133)) - Update dependency io.grpc:grpc-bom to v1.51.1 ([#​953](https://togithub.com/googleapis/java-shared-dependencies/issues/953)) ([a86e70a](https://togithub.com/googleapis/java-shared-dependencies/commit/a86e70ac7be07cdb3b69d0cf4fc1afedbf7048fd)) - Update dependency org.checkerframework:checker-qual to v3.29.0 ([#​959](https://togithub.com/googleapis/java-shared-dependencies/issues/959)) ([784a79b](https://togithub.com/googleapis/java-shared-dependencies/commit/784a79b49b109d18858fd603dbdd37a4947280af)) - Update dependency org.threeten:threetenbp to v1.6.5 ([#​946](https://togithub.com/googleapis/java-shared-dependencies/issues/946)) ([403555e](https://togithub.com/googleapis/java-shared-dependencies/commit/403555e4010aef84e909e0b0e48cf5571d9e3184)) - Update google.core.version to v2.9.1 ([#​962](https://togithub.com/googleapis/java-shared-dependencies/issues/962)) ([c1e648d](https://togithub.com/googleapis/java-shared-dependencies/commit/c1e648d5045f871ed5670f949978430ad2d49484)) - Update iam.version to v1.6.23 ([#​954](https://togithub.com/googleapis/java-shared-dependencies/issues/954)) ([bb4730e](https://togithub.com/googleapis/java-shared-dependencies/commit/bb4730e7dcac57b6653825d63c7408d2182b0a27))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f8f689be8946..885be1bf31a1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.1.0 + 3.1.1 pom import From 745f9f1d4e5eae27b7f02874ec82984b571efa42 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 08:06:15 +0000 Subject: [PATCH 0840/1979] chore(main): release 2.9.1 (#1091) :robot: I have created a release *beep* *boop* --- ## [2.9.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.0...v2.9.1) (2023-01-12) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.1 ([#1090](https://togithub.com/googleapis/java-spanner-jdbc/issues/1090)) ([02e35b5](https://togithub.com/googleapis/java-spanner-jdbc/commit/02e35b5114659630395b45d945a1ba9937bf1365)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b23d783c391c..637690664921 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.0...v2.9.1) (2023-01-12) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.1 ([#1090](https://github.com/googleapis/java-spanner-jdbc/issues/1090)) ([ef9ccf8](https://github.com/googleapis/java-spanner-jdbc/commit/ef9ccf84b78057edc338def2cea69b85ec6a75bf)) + ## [2.9.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.8.0...v2.9.0) (2022-12-14) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 885be1bf31a1..32fa5b991e2f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.1-SNAPSHOT + 2.9.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ffe3442076c8..b469edf44077 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.1-SNAPSHOT + 2.9.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 48903a0a99de..185f2c9823e0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.0:2.9.1-SNAPSHOT +google-cloud-spanner-jdbc:2.9.1:2.9.1 From 1d5da5b758b6be19472446516715e98e7470a399 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 09:36:11 +0000 Subject: [PATCH 0841/1979] chore(main): release 2.9.2-SNAPSHOT (#1092) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 32fa5b991e2f..75ff8433c301 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.1 + 2.9.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b469edf44077..a627562d3d33 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.1 + 2.9.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 185f2c9823e0..3d7bffa12a60 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.1:2.9.1 +google-cloud-spanner-jdbc:2.9.1:2.9.2-SNAPSHOT From cff7e9ae57a90373c3ff2b089b2c62e46e511f1b Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 13 Jan 2023 00:02:13 +0530 Subject: [PATCH 0842/1979] chore: add nightly tests against cloud-devel (#1095) --- .../nightly/integration-cloud-devel.cfg | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg diff --git a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg new file mode 100644 index 000000000000..6e5f77e14cd0 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg @@ -0,0 +1,33 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration-cloud-devel" +} + +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "span-cloud-testing" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "span-cloud-testing" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-client-testing" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-client-testing" +} From 84400bd41404bd579c6c95327ed6274d2a758363 Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 13 Jan 2023 00:43:18 +0530 Subject: [PATCH 0843/1979] chore: add continuous tests against cloud-devel (#1094) * chore: add continuous tests against cloud-devel --- java-spanner-jdbc/.kokoro/build.sh | 14 ++++++++ .../continuous/integration-cloud-devel.cfg | 35 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 53a65e6fcf7f..dea990121e33 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -69,6 +69,20 @@ integration) verify RETURN_CODE=$? ;; +integration-cloud-devel) + mvn -B ${INTEGRATION_TEST_ARGS} \ + -ntp \ + -Penable-integration-tests \ + -DtrimStackTrace=false \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dspanner.gce.config.server_url=https://staging-wrenchworks.sandbox.googleapis.com \ + -Dspanner.testenv.instance=projects/span-cloud-testing/instances/spanner-testing-east1 \ + -Dspanner.gce.config.project_id=span-cloud-testing \ + -fae \ + verify + RETURN_CODE=$? + ;; graalvm) # Run Unit and Integration Tests with Native Image. mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" diff --git a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg new file mode 100644 index 000000000000..f005bd50c809 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg @@ -0,0 +1,35 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.txt" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration-cloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-client-testing" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-client-testing" +} From 8fe564ed48a285844769806e6dc033d226fa85ee Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 13 Jan 2023 02:18:12 +0530 Subject: [PATCH 0844/1979] chore: add TRAMPOLINE_IMAGE env var to config (#1096) --- .../.kokoro/continuous/integration-cloud-devel.cfg | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg index f005bd50c809..bd2254315ac4 100644 --- a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg +++ b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg @@ -33,3 +33,14 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-client-testing" } + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "REPORT_COVERAGE" + value: "true" +} From a1011273ccc660fc558d142fc3137a59dcca34aa Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:49:09 +0530 Subject: [PATCH 0845/1979] test: fix ITJdbcConnectTest for custom server url (#1098) * test: fix ITJdbcConnectTest for custom server url --- .../google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index c81a6333807a..bf6d2892cacd 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -60,10 +60,12 @@ public class ITJdbcConnectTest extends ITAbstractJdbcTest { @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); private Database database; + private SpannerOptions options; @Before public void setup() { database = env.getOrCreateDatabase(Dialect.GOOGLE_STANDARD_SQL, Collections.emptyList()); + options = env.getTestHelper().getOptions(); } private String createBaseUrl() { @@ -71,6 +73,11 @@ private String createBaseUrl() { if (EmulatorSpannerHelper.isUsingEmulator()) { url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST")); } + // Extract "//x.y.googleapis.com" from "https://x.y.googleapis.com" and append it to + // url. + if (options.getHost() != null) { + url.append(options.getHost().substring(options.getHost().indexOf(':') + 1)); + } url.append("/").append(database.getId().getName()); if (EmulatorSpannerHelper.isUsingEmulator()) { url.append(";usePlainText=true"); From 1cd3f3efb4fdc4a4e7b6d1a9f0ed86c88acc453f Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Fri, 13 Jan 2023 17:00:12 +0530 Subject: [PATCH 0846/1979] test: nightly/continuous ITs against cloud-staging (#1099) --- java-spanner-jdbc/.kokoro/build.sh | 14 ++++++ .../continuous/integration-cloud-staging.cfg | 46 +++++++++++++++++++ .../nightly/integration-cloud-staging.cfg | 33 +++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg create mode 100644 java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index dea990121e33..f315d0cc9727 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -83,6 +83,20 @@ integration-cloud-devel) verify RETURN_CODE=$? ;; +integration-cloud-staging) + mvn -B ${INTEGRATION_TEST_ARGS} \ + -ntp \ + -Penable-integration-tests \ + -DtrimStackTrace=false \ + -Dclirr.skip=true \ + -Denforcer.skip=true \ + -Dspanner.gce.config.server_url=https://preprod-spanner.sandbox.googleapis.com \ + -Dspanner.testenv.instance=projects/span-cloud-testing/instances/spanner-testing \ + -Dspanner.gce.config.project_id=span-cloud-testing \ + -fae \ + verify + RETURN_CODE=$? + ;; graalvm) # Run Unit and Integration Tests with Native Image. mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" diff --git a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg new file mode 100644 index 000000000000..6136ab744f0a --- /dev/null +++ b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg @@ -0,0 +1,46 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.txt" + } +} + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/java-spanner-jdbc/.kokoro/build.sh" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration-cloud-staging" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-client-testing" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-client-testing" +} + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "REPORT_COVERAGE" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg new file mode 100644 index 000000000000..a660c90d6eba --- /dev/null +++ b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg @@ -0,0 +1,33 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/java8" +} + +env_vars: { + key: "JOB_TYPE" + value: "integration-cloud-staging" +} + +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "span-cloud-testing" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "span-cloud-testing" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-client-testing" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-client-testing" +} From 9fe5f9d61ea125514e91be08150cc11bb0fd2fcd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Jan 2023 07:25:57 +0000 Subject: [PATCH 0847/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.1 (#1093) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index bd1a77ed128d..5bb5021428d6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.0 + 2.9.1 From fc92bd9d522fceff06e2705e2a7c8f339c7d84e3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Jan 2023 07:26:13 +0000 Subject: [PATCH 0848/1979] test(deps): update dependency org.mockito:mockito-core to v4.11.0 (#1086) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 75ff8433c301..54b596f013ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -52,7 +52,7 @@ 4.13.2 3.0.2 1.1.3 - 4.10.0 + 4.11.0 2.2 0.31.1 From 84eda19f34a73c52864518ae19ae72c92b8b06f2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Jan 2023 07:26:34 +0000 Subject: [PATCH 0849/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.0 (#1097) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 54b596f013ef..de0afe7dadd6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.34.1 + 6.35.0 pom import From 6de8c15cc349de28104993067c357a0d579bc948 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Jan 2023 08:48:11 +0000 Subject: [PATCH 0850/1979] chore(main): release 2.9.2 (#1100) :robot: I have created a release *beep* *boop* --- ## [2.9.2](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.1...v2.9.2) (2023-01-14) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.0 ([#1097](https://togithub.com/googleapis/java-spanner-jdbc/issues/1097)) ([84eda19](https://togithub.com/googleapis/java-spanner-jdbc/commit/84eda19f34a73c52864518ae19ae72c92b8b06f2)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 637690664921..863816d7210a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.1...v2.9.2) (2023-01-14) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.0 ([#1097](https://github.com/googleapis/java-spanner-jdbc/issues/1097)) ([d8d11c3](https://github.com/googleapis/java-spanner-jdbc/commit/d8d11c3d46197680ffa28c85261736651a64eb63)) + ## [2.9.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.0...v2.9.1) (2023-01-12) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index de0afe7dadd6..269921c9567d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.2-SNAPSHOT + 2.9.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a627562d3d33..fa21ae692813 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.2-SNAPSHOT + 2.9.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3d7bffa12a60..4c0f20d295be 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.1:2.9.2-SNAPSHOT +google-cloud-spanner-jdbc:2.9.2:2.9.2 From 0fb2fb71117549d06bac2ff73ade2960bae7eb20 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Jan 2023 10:14:12 +0000 Subject: [PATCH 0851/1979] chore(main): release 2.9.3-SNAPSHOT (#1102) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 269921c9567d..ee27030df3f6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.2 + 2.9.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fa21ae692813..c11220e8aa19 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.2 + 2.9.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4c0f20d295be..d80d1e9bd6d5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.2:2.9.2 +google-cloud-spanner-jdbc:2.9.2:2.9.3-SNAPSHOT From e9ebbf2c0fed922d23c4765db61e8cc36753ee6b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Jan 2023 07:41:59 +0000 Subject: [PATCH 0852/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.2 (#1103) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5bb5021428d6..8eee38fa53c1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.1 + 2.9.2 From 94ed060dcf2ddc8dca5d31aa052fdf3606813a14 Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Tue, 17 Jan 2023 20:00:48 +0530 Subject: [PATCH 0853/1979] chore: enable flakybot for nightly/continuous ITs (#1104) * chore: enable flakybot on integration test jobs --- .../continuous/integration-cloud-devel.cfg | 5 +++++ .../continuous/integration-cloud-staging.cfg | 5 +++++ .../.kokoro/nightly/integration-cloud-devel.cfg | 16 +++++----------- .../nightly/integration-cloud-staging.cfg | 16 +++++----------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg index bd2254315ac4..feff61e0dedf 100644 --- a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg +++ b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-devel.cfg @@ -44,3 +44,8 @@ env_vars: { key: "REPORT_COVERAGE" value: "true" } + +env_vars: { + key: "ENABLE_FLAKYBOT" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg index 6136ab744f0a..1f8dc6eff179 100644 --- a/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg +++ b/java-spanner-jdbc/.kokoro/continuous/integration-cloud-staging.cfg @@ -44,3 +44,8 @@ env_vars: { key: "REPORT_COVERAGE" value: "true" } + +env_vars: { + key: "ENABLE_FLAKYBOT" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg index 6e5f77e14cd0..0f0b1195cfcf 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-devel.cfg @@ -11,17 +11,6 @@ env_vars: { value: "integration-cloud-devel" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "span-cloud-testing" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "span-cloud-testing" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" value: "secret_manager/java-client-testing" @@ -31,3 +20,8 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-client-testing" } + +env_vars: { + key: "ENABLE_FLAKYBOT" + value: "true" +} diff --git a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg index a660c90d6eba..4c62b963df6b 100644 --- a/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/integration-cloud-staging.cfg @@ -11,17 +11,6 @@ env_vars: { value: "integration-cloud-staging" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "span-cloud-testing" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "span-cloud-testing" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" value: "secret_manager/java-client-testing" @@ -31,3 +20,8 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-client-testing" } + +env_vars: { + key: "ENABLE_FLAKYBOT" + value: "true" +} From 9d664f7e66a793484714c9517c2e7504a2fa19b3 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 13:36:53 +0530 Subject: [PATCH 0854/1979] fix(java): skip fixing poms for special modules (#1744) (#1108) fix(java): handle empty modules Fixes https://github.com/googleapis/synthtool/issues/1743 Source-Link: https://github.com/googleapis/synthtool/commit/482d649d5d705c18028076985f64b214f6b6c14e Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:bd5071596a47614d1fe15eb766c4255bae330f823b606e1196a3b0c8d2e96fd1 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +- java-spanner-jdbc/.kokoro/requirements.in | 40 +---- java-spanner-jdbc/.kokoro/requirements.txt | 184 ++++++++------------ 3 files changed, 76 insertions(+), 152 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 288e394897e6..f8a8575314cc 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 Google LLC +# 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. @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:9de537d592b60e5eac73b374a28263969bae91ecdb29b445e894576fbf54851c + digest: sha256:bd5071596a47614d1fe15eb766c4255bae330f823b606e1196a3b0c8d2e96fd1 diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index a5010f77d413..b19a8dbfdd5e 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -1,34 +1,6 @@ -gcp-docuploader==0.6.3 -google-crc32c==1.3.0 -googleapis-common-protos==1.56.3 -gcp-releasetool==1.9.1 -cryptography==38.0.3 -cachetools==4.2.4 -cffi==1.15.1 -jeepney==0.7.1 -jinja2==3.0.3 -markupsafe==2.0.1 -keyring==23.4.1 -packaging==21.3 -protobuf==3.19.5 -pyjwt==2.4.0 -pyparsing==3.0.9 -pycparser==2.21 -pyperclip==1.8.2 -python-dateutil==2.8.2 -requests==2.27.1 -certifi==2022.12.7 -importlib-metadata==4.8.3 -zipp==3.6.0 -google_api_core==2.8.2 -google-cloud-storage==2.0.0 -google-resumable-media==2.3.3 -google-cloud-core==2.3.1 -typing-extensions==4.1.1 -urllib3==1.26.12 -zipp==3.6.0 -rsa==4.9 -six==1.16.0 -attrs==22.1.0 -google-auth==2.14.1 -idna==3.4 \ No newline at end of file +gcp-docuploader +gcp-releasetool +wheel +setuptools +typing-extensions +click<8.1.0 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 15c404aa5a8c..4895c9631fd8 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -1,27 +1,21 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # -# pip-compile --generate-hashes requirements.in +# pip-compile --allow-unsafe --generate-hashes requirements.in # attrs==22.1.0 \ --hash=sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6 \ --hash=sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool cachetools==4.2.4 \ --hash=sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693 \ --hash=sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1 - # via - # -r requirements.in - # google-auth + # via google-auth certifi==2022.12.7 \ --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 - # via - # -r requirements.in - # requests + # via requests cffi==1.15.1 \ --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ @@ -87,9 +81,7 @@ cffi==1.15.1 \ --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 - # via - # -r requirements.in - # cryptography + # via cryptography charset-normalizer==2.0.12 \ --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \ --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df @@ -98,6 +90,7 @@ click==8.0.4 \ --hash=sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1 \ --hash=sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb # via + # -r requirements.in # gcp-docuploader # gcp-releasetool colorlog==6.7.0 \ @@ -132,12 +125,11 @@ cryptography==38.0.3 \ --hash=sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c \ --hash=sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722 # via - # -r requirements.in # gcp-releasetool # secretstorage -gcp-docuploader==0.6.3 \ - --hash=sha256:ba8c9d76b3bbac54b0311c503a373b00edc2dc02d6d54ea9507045adb8e870f7 \ - --hash=sha256:c0f5aaa82ce1854a386197e4e359b120ad6d4e57ae2c812fce42219a3288026b +gcp-docuploader==0.6.4 \ + --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ + --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in gcp-releasetool==1.9.1 \ --hash=sha256:952f4055d5d986b070ae2a71c4410b250000f9cc5a1e26398fcd55a5bbc5a15f \ @@ -147,13 +139,12 @@ google-api-core==2.8.2 \ --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \ --hash=sha256:93c6a91ccac79079ac6bbf8b74ee75db970cc899278b97d53bc012f35908cf50 # via - # -r requirements.in # google-cloud-core # google-cloud-storage google-auth==2.14.1 \ + --hash=sha256:ccaa901f31ad5cbb562615eb8b664b3dd0bf5404a67618e642307f00613eda4d \ --hash=sha256:f5d8701633bebc12e0deea4df8abd8aff31c28b355360597f7f2ee60f2e4d016 # via - # -r requirements.in # gcp-releasetool # google-api-core # google-cloud-core @@ -161,15 +152,11 @@ google-auth==2.14.1 \ google-cloud-core==2.3.1 \ --hash=sha256:113ba4f492467d5bd442c8d724c1a25ad7384045c3178369038840ecdd19346c \ --hash=sha256:34334359cb04187bdc80ddcf613e462dfd7a3aabbc3fe4d118517ab4b9303d53 - # via - # -r requirements.in - # google-cloud-storage + # via google-cloud-storage google-cloud-storage==2.0.0 \ --hash=sha256:a57a15aead0f9dfbd4381f1bfdbe8bf89818a4bd75bab846cafcefb2db846c47 \ --hash=sha256:ec4be60bb223a3a960f0d01697d849b86d91cad815a84915a32ed3635e93a5e7 - # via - # -r requirements.in - # gcp-docuploader + # via gcp-docuploader google-crc32c==1.3.0 \ --hash=sha256:04e7c220798a72fd0f08242bc8d7a05986b2a08a0573396187fd32c1dcdd58b3 \ --hash=sha256:05340b60bf05b574159e9bd940152a47d38af3fb43803ffe71f11d704b7696a6 \ @@ -214,52 +201,37 @@ google-crc32c==1.3.0 \ --hash=sha256:fe31de3002e7b08eb20823b3735b97c86c5926dd0581c7710a680b418a8709d4 \ --hash=sha256:fec221a051150eeddfdfcff162e6db92c65ecf46cb0f7bb1bf812a1520ec026b \ --hash=sha256:ff71073ebf0e42258a42a0b34f2c09ec384977e7f6808999102eedd5b49920e3 - # via - # -r requirements.in - # google-resumable-media + # via google-resumable-media google-resumable-media==2.3.3 \ --hash=sha256:27c52620bd364d1c8116eaac4ea2afcbfb81ae9139fb3199652fcac1724bfb6c \ --hash=sha256:5b52774ea7a829a8cdaa8bd2d4c3d4bc660c91b30857ab2668d0eb830f4ea8c5 - # via - # -r requirements.in - # google-cloud-storage + # via google-cloud-storage googleapis-common-protos==1.56.3 \ --hash=sha256:6f1369b58ed6cf3a4b7054a44ebe8d03b29c309257583a2bbdc064cd1e4a1442 \ --hash=sha256:87955d7b3a73e6e803f2572a33179de23989ebba725e05ea42f24838b792e461 - # via - # -r requirements.in - # google-api-core + # via google-api-core idna==3.4 \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 - # via - # -r requirements.in - # requests + # via requests importlib-metadata==4.8.3 \ --hash=sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e \ --hash=sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668 + # via keyring +jeepney==0.8.0 \ + --hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \ + --hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755 # via - # -r requirements.in - # keyring -jeepney==0.7.1 \ - --hash=sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac \ - --hash=sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f - # via - # -r requirements.in # keyring # secretstorage jinja2==3.0.3 \ --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \ --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7 - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool keyring==23.4.1 \ --hash=sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca \ --hash=sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55 - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool markupsafe==2.0.1 \ --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \ --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \ @@ -330,49 +302,39 @@ markupsafe==2.0.1 \ --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \ --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \ --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872 - # via - # -r requirements.in - # jinja2 + # via jinja2 packaging==21.3 \ --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 + # 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 # via - # -r requirements.in - # gcp-releasetool -protobuf==3.19.5 \ - --hash=sha256:1867f93b06a183f87696871bb8d1e99ee71dbb69d468ce1f0cc8bf3d30f982f3 \ - --hash=sha256:3c4160b601220627f7e91154e572baf5e161a9c3f445a8242d536ee3d0b7b17c \ - --hash=sha256:4ee2af7051d3b10c8a4fe6fd1a2c69f201fea36aeee7086cf202a692e1b99ee1 \ - --hash=sha256:5266c36cc0af3bb3dbf44f199d225b33da66a9a5c3bdc2b14865ad10eddf0e37 \ - --hash=sha256:5470f892961af464ae6eaf0f3099e2c1190ae8c7f36f174b89491281341f79ca \ - --hash=sha256:66d14b5b90090353efe75c9fb1bf65ef7267383034688d255b500822e37d5c2f \ - --hash=sha256:67efb5d20618020aa9596e17bfc37ca068c28ec0c1507d9507f73c93d46c9855 \ - --hash=sha256:696e6cfab94cc15a14946f2bf72719dced087d437adbd994fff34f38986628bc \ - --hash=sha256:6a02172b9650f819d01fb8e224fc69b0706458fc1ab4f1c669281243c71c1a5e \ - --hash=sha256:6eca9ae238ba615d702387a2ddea635d535d769994a9968c09a4ca920c487ab9 \ - --hash=sha256:950abd6c00e7b51f87ae8b18a0ce4d69fea217f62f171426e77de5061f6d9850 \ - --hash=sha256:9e1d74032f56ff25f417cfe84c8147047732e5059137ca42efad20cbbd25f5e0 \ - --hash=sha256:9e42b1cf2ecd8a1bd161239e693f22035ba99905ae6d7efeac8a0546c7ec1a27 \ - --hash=sha256:9f957ef53e872d58a0afd3bf6d80d48535d28c99b40e75e6634cbc33ea42fd54 \ - --hash=sha256:a89aa0c042e61e11ade320b802d6db4ee5391d8d973e46d3a48172c1597789f8 \ - --hash=sha256:c0f80876a8ff0ae7064084ed094eb86497bd5a3812e6fc96a05318b92301674e \ - --hash=sha256:c44e3282cff74ad18c7e8a0375f407f69ee50c2116364b44492a196293e08b21 \ - --hash=sha256:d249519ba5ecf5dd6b18150c9b6bcde510b273714b696f3923ff8308fc11ae49 \ - --hash=sha256:d3973a2d58aefc7d1230725c2447ce7f86a71cbc094b86a77c6ee1505ac7cdb1 \ - --hash=sha256:dca2284378a5f2a86ffed35c6ac147d14c48b525eefcd1083e5a9ce28dfa8657 \ - --hash=sha256:e63b0b3c42e51c94add62b010366cd4979cb6d5f06158bcae8faac4c294f91e1 \ - --hash=sha256:f2b599a21c9a32e171ec29a2ac54e03297736c578698e11b099d031f79da114b \ - --hash=sha256:f2bde37667b18c2b5280df83bc799204394a5d2d774e4deaf9de0eb741df6833 \ - --hash=sha256:f4f909f4dde413dec435a44b0894956d55bb928ded7d6e3c726556ca4c796e84 \ - --hash=sha256:f976234e20ab2785f54224bcdafa027674e23663b132fa3ca0caa291a6cfbde7 \ - --hash=sha256:f9cebda093c2f6bfed88f1c17cdade09d4d96096421b344026feee236532d4de - # via - # -r requirements.in # gcp-docuploader # gcp-releasetool # google-api-core # google-cloud-storage - # googleapis-common-protos pyasn1==0.4.8 \ --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \ --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba @@ -386,71 +348,61 @@ pyasn1-modules==0.2.8 \ pycparser==2.21 \ --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 - # via - # -r requirements.in - # cffi + # via cffi pyjwt==2.4.0 \ --hash=sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf \ --hash=sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool pyparsing==3.0.9 \ --hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \ --hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc - # via - # -r requirements.in - # packaging + # via packaging pyperclip==1.8.2 \ --hash=sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57 - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 - # via - # -r requirements.in - # gcp-releasetool + # via gcp-releasetool requests==2.27.1 \ --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d # via - # -r requirements.in # gcp-releasetool # google-api-core # google-cloud-storage rsa==4.9 \ --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 - # via - # -r requirements.in - # google-auth + # via google-auth secretstorage==3.3.3 \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 # via keyring +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via -r requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via - # -r requirements.in # gcp-docuploader # google-auth # python-dateutil -typing-extensions==4.1.1 \ - --hash=sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42 \ - --hash=sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2 +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e # via -r requirements.in urllib3==1.26.12 \ --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 - # via - # -r requirements.in - # requests + # via requests +wheel==0.38.4 \ + --hash=sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac \ + --hash=sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8 + # via -r requirements.in zipp==3.6.0 \ --hash=sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832 \ --hash=sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc - # via - # -r requirements.in - # importlib-metadata + # via importlib-metadata From 76b1624892222ddd560ade9031c128dcbd33707b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Jan 2023 09:30:12 +0000 Subject: [PATCH 0855/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.4.0 (#1105) 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.3.0` -> `26.4.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.4.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.4.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.4.0/compatibility-slim/26.3.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/26.4.0/confidence-slim/26.3.0)](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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c423c8485b00..215aa1c02ebd 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.3.0 + 26.4.0 pom import From fa6d6aa346e151032a8e3548d08b18b09f0e6ca1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Jan 2023 09:32:11 +0000 Subject: [PATCH 0856/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.1 (#1106) 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.35.0` -> `6.35.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.1/compatibility-slim/6.35.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.1/confidence-slim/6.35.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.35.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6351-httpsgithubcomgoogleapisjava-spannercomparev6350v6351-2023-01-18) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.35.0...v6.35.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.9.0 ([#​2230](https://togithub.com/googleapis/java-spanner/issues/2230)) ([717f70f](https://togithub.com/googleapis/java-spanner/commit/717f70f76f915e15a7283b32a83a6f4ac64fc931)) - Update dependency com.google.cloud:google-cloud-trace to v2.8.0 ([#​2231](https://togithub.com/googleapis/java-spanner/issues/2231)) ([557ea16](https://togithub.com/googleapis/java-spanner/commit/557ea164ebf948cd78f937c6996fd21e9618d3ae)) - Update dependency org.graalvm.sdk:graal-sdk to v22.3.1 ([#​2238](https://togithub.com/googleapis/java-spanner/issues/2238)) ([d5f5237](https://togithub.com/googleapis/java-spanner/commit/d5f52375394ef617f4fcb823937a374930f941e7)) - Update dependency org.junit.vintage:junit-vintage-engine to v5.9.2 ([#​2223](https://togithub.com/googleapis/java-spanner/issues/2223)) ([3278f91](https://togithub.com/googleapis/java-spanner/commit/3278f9167b1b2688ed090a7dfd5874e88b8945a5))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ee27030df3f6..83084136358e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.35.0 + 6.35.1 pom import From dfbc0ccb87808b348846f6441b9d5aa34659f676 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Jan 2023 17:29:42 +0000 Subject: [PATCH 0857/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.2 (#1109) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 83084136358e..a234edeafa6a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.1.1 + 3.1.2 pom import From 9fda09321d5cbab0f876145b27fe6d0e3aeaefdd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 09:24:23 +0530 Subject: [PATCH 0858/1979] chore(main): release 2.9.3 (#1110) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 863816d7210a..6f7f83a68de3 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.9.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.2...v2.9.3) (2023-01-25) + + +### Bug Fixes + +* **java:** Skip fixing poms for special modules ([#1744](https://github.com/googleapis/java-spanner-jdbc/issues/1744)) ([#1108](https://github.com/googleapis/java-spanner-jdbc/issues/1108)) ([2915d76](https://github.com/googleapis/java-spanner-jdbc/commit/2915d766bf6578f1921f8ffe38d6b9be61c63813)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.2 ([#1109](https://github.com/googleapis/java-spanner-jdbc/issues/1109)) ([3614824](https://github.com/googleapis/java-spanner-jdbc/commit/3614824692899165d38ffd12de8cf3543560ea5c)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.1 ([#1106](https://github.com/googleapis/java-spanner-jdbc/issues/1106)) ([3bd7d6b](https://github.com/googleapis/java-spanner-jdbc/commit/3bd7d6b72ee87b3b83a50e2459f2d4e3b0fd87a2)) + ## [2.9.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.1...v2.9.2) (2023-01-14) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a234edeafa6a..d57a5a6d0309 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.3-SNAPSHOT + 2.9.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c11220e8aa19..8528d1fb0742 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.3-SNAPSHOT + 2.9.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d80d1e9bd6d5..0d4dfb9eb8af 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.2:2.9.3-SNAPSHOT +google-cloud-spanner-jdbc:2.9.3:2.9.3 From c66a51df9cd7f8520a3732e5ace69a5873cba5a5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 05:18:12 +0000 Subject: [PATCH 0859/1979] chore(main): release 2.9.4-SNAPSHOT (#1112) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d57a5a6d0309..ce2cb8cd3da1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.3 + 2.9.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8528d1fb0742..63d63b8a5778 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.3 + 2.9.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0d4dfb9eb8af..338742b86aa5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.3:2.9.3 +google-cloud-spanner-jdbc:2.9.3:2.9.4-SNAPSHOT From 96c3f09c13e637be3fc5e14d622efaf5fa35aa19 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Feb 2023 16:05:40 +0000 Subject: [PATCH 0860/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.2.0 (#1118) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ce2cb8cd3da1..08454f63082a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.1.2 + 3.2.0 pom import From f4cdfe7e8b03777a59cdb4741485de3fa0810b56 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Feb 2023 16:06:06 +0000 Subject: [PATCH 0861/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.6.0 (#1115) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 215aa1c02ebd..ea85b382bff6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.4.0 + 26.6.0 pom import From 3579a3591d30561242e3fed0bd7a2162fc95328b Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Wed, 8 Feb 2023 11:07:50 -0500 Subject: [PATCH 0862/1979] deps: use perfmark-api version via shared dependencies BOM (#1111) The shared dependencies BOM declares perfmark-api version already. No need to declare it in this repository. https://github.com/googleapis/java-shared-dependencies/blob/main/third-party-dependencies/pom.xml#LL72C27-L72C33 --- java-spanner-jdbc/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 08454f63082a..612442e8fcdc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -83,11 +83,6 @@ opencensus-contrib-grpc-util ${opencensus.version}
    - - io.perfmark - perfmark-api - 0.26.0 - From 17725ceb5d97410f5efc2ddd142afa63c8ec5a55 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Feb 2023 16:08:17 +0000 Subject: [PATCH 0863/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.3 (#1113) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 8eee38fa53c1..7cc26bffc942 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.2 + 2.9.3 From ea141a711987be685f5d2a736b4b725fefd12f0f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Feb 2023 17:46:17 +0000 Subject: [PATCH 0864/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.2 (#1114) 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.35.1` -> `6.35.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.2/compatibility-slim/6.35.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.35.2/confidence-slim/6.35.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.35.2`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6352-httpsgithubcomgoogleapisjava-spannercomparev6351v6352-2023-01-24) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.35.1...v6.35.2) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.10.0 ([#​2249](https://togithub.com/googleapis/java-spanner/issues/2249)) ([d18780e](https://togithub.com/googleapis/java-spanner/commit/d18780ec0278fc49495939647fe6a2f9e0b4f94e)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.1.2 ([#​2246](https://togithub.com/googleapis/java-spanner/issues/2246)) ([1adaf7c](https://togithub.com/googleapis/java-spanner/commit/1adaf7cae629ba7b9903d6512adc7b13b6d1208e)) - Update dependency com.google.cloud:google-cloud-trace to v2.9.0 ([#​2250](https://togithub.com/googleapis/java-spanner/issues/2250)) ([3cd5ab0](https://togithub.com/googleapis/java-spanner/commit/3cd5ab05e1fd24090fd58c2320b6875135e49b69))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 612442e8fcdc..abd8dc6fd3ad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.35.1 + 6.35.2 pom import From 8cee80a471f214e55d9dadac6ea44c1267346c1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 23:43:10 +0530 Subject: [PATCH 0865/1979] build(deps): bump cryptography from 38.0.3 to 39.0.1 in /.kokoro (#1119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump cryptography from 38.0.3 to 39.0.1 in /.kokoro Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.3 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/38.0.3...39.0.1) --- 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 493f17e235f81d3126aa49c0980750f12b98891c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 19:36:14 +0000 Subject: [PATCH 0866/1979] chore(main): release 2.9.4 (#1120) :robot: I have created a release *beep* *boop* --- ## [2.9.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.3...v2.9.4) (2023-02-08) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.2.0 ([#1118](https://togithub.com/googleapis/java-spanner-jdbc/issues/1118)) ([96c3f09](https://togithub.com/googleapis/java-spanner-jdbc/commit/96c3f09c13e637be3fc5e14d622efaf5fa35aa19)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.2 ([#1114](https://togithub.com/googleapis/java-spanner-jdbc/issues/1114)) ([ea141a7](https://togithub.com/googleapis/java-spanner-jdbc/commit/ea141a711987be685f5d2a736b4b725fefd12f0f)) * Use perfmark-api version via shared dependencies BOM ([#1111](https://togithub.com/googleapis/java-spanner-jdbc/issues/1111)) ([3579a35](https://togithub.com/googleapis/java-spanner-jdbc/commit/3579a3591d30561242e3fed0bd7a2162fc95328b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 9 +++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6f7f83a68de3..26457100644d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [2.9.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.3...v2.9.4) (2023-02-08) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.2.0 ([#1118](https://github.com/googleapis/java-spanner-jdbc/issues/1118)) ([56ed82b](https://github.com/googleapis/java-spanner-jdbc/commit/56ed82b26e40ccfa88e046eb39f8b146bd647e16)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.35.2 ([#1114](https://github.com/googleapis/java-spanner-jdbc/issues/1114)) ([6575d0c](https://github.com/googleapis/java-spanner-jdbc/commit/6575d0c980fa894a5d50b978f8cc93974e804eb2)) +* Use perfmark-api version via shared dependencies BOM ([#1111](https://github.com/googleapis/java-spanner-jdbc/issues/1111)) ([beb5298](https://github.com/googleapis/java-spanner-jdbc/commit/beb52985676b0e981072ee7df60a4cf9f6139624)) + ## [2.9.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.2...v2.9.3) (2023-01-25) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index abd8dc6fd3ad..e3952588e4f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.4-SNAPSHOT + 2.9.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 63d63b8a5778..2c0a7312234d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.4-SNAPSHOT + 2.9.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 338742b86aa5..6352a94a8f1d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.3:2.9.4-SNAPSHOT +google-cloud-spanner-jdbc:2.9.4:2.9.4 From 972c1713cb5e147b7383ebb59f71524d960dc037 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 21:04:12 +0000 Subject: [PATCH 0867/1979] chore(main): release 2.9.5-SNAPSHOT (#1122) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e3952588e4f0..29b6569f9ce6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.4 + 2.9.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2c0a7312234d..92ed5d609461 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.4 + 2.9.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6352a94a8f1d..d771b9826d56 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.4:2.9.4 +google-cloud-spanner-jdbc:2.9.4:2.9.5-SNAPSHOT From 38d262655f4d5b628dcbb832660aa389ed51d6e2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Feb 2023 19:03:33 +0000 Subject: [PATCH 0868/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.7.0 (#1126) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ea85b382bff6..3ce530e54794 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.6.0 + 26.7.0 pom import From b38cee8e2a2e9ebd29a04b537003dc974b35e506 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Feb 2023 19:04:04 +0000 Subject: [PATCH 0869/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.0 (#1125) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 9b3403e44c4f..2ed3c9c56284 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -38,7 +38,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.0.0 + 3.1.0 true From 9ca789b02e956966befe9f48ab3d1c5cb8ecd643 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Feb 2023 19:04:32 +0000 Subject: [PATCH 0870/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.4 (#1123) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7cc26bffc942..96f238fb61c6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.3 + 2.9.4 From 9667d5875ec702d05c9fdf8e0e94a124ef22903c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Feb 2023 19:05:00 +0000 Subject: [PATCH 0871/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.0 (#1121) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 29b6569f9ce6..8cdf60c8c2d4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.35.2 + 6.36.0 pom import From d6e8af4541d240176ff2d18453409cf5a95363b6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 20:28:13 +0000 Subject: [PATCH 0872/1979] chore(main): release 2.9.5 (#1127) :robot: I have created a release *beep* *boop* --- ## [2.9.5](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.4...v2.9.5) (2023-02-09) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.0 ([#1121](https://togithub.com/googleapis/java-spanner-jdbc/issues/1121)) ([9667d58](https://togithub.com/googleapis/java-spanner-jdbc/commit/9667d5875ec702d05c9fdf8e0e94a124ef22903c)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 26457100644d..dabe9ea7d079 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.4...v2.9.5) (2023-02-09) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.0 ([#1121](https://github.com/googleapis/java-spanner-jdbc/issues/1121)) ([dcb5826](https://github.com/googleapis/java-spanner-jdbc/commit/dcb5826b17b30303b8d6115bf55a4ede0e13ef84)) + ## [2.9.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.3...v2.9.4) (2023-02-08) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8cdf60c8c2d4..2810f6ea7b1a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.5-SNAPSHOT + 2.9.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 92ed5d609461..f33ede0f59e6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.5-SNAPSHOT + 2.9.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d771b9826d56..97553f9fdf79 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.4:2.9.5-SNAPSHOT +google-cloud-spanner-jdbc:2.9.5:2.9.5 From ae65b8bb67bc0a64fdddb826f7e919427bf896b7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 21:54:12 +0000 Subject: [PATCH 0873/1979] chore(main): release 2.9.6-SNAPSHOT (#1128) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2810f6ea7b1a..51aded602b57 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.5 + 2.9.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f33ede0f59e6..8d3d6534ffd6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.5 + 2.9.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 97553f9fdf79..41d3d480a2cd 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.5:2.9.5 +google-cloud-spanner-jdbc:2.9.5:2.9.6-SNAPSHOT From a48832032e77262fa8feb0b3196808b5c0b434f8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Feb 2023 09:46:19 +0000 Subject: [PATCH 0874/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.3.0 (#1133) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 51aded602b57..76f223064dbb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.2.0 + 3.3.0 pom import From 6a74caa4cf5006e4f9a0dab2afb9f3f49f5cb7f9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Feb 2023 09:52:25 +0000 Subject: [PATCH 0875/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.8.0 (#1131) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 3ce530e54794..068794f84ea0 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.7.0 + 26.8.0 pom import From 71d6902c4530e1c78e13a9a8f66b4b6582cd6928 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Feb 2023 09:52:46 +0000 Subject: [PATCH 0876/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.5.0 (#1132) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 76f223064dbb..08da2adf5c70 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -420,7 +420,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.5.0 html From b759710dab80e98e763c240f29067f33408c8f4d Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:23:07 +0530 Subject: [PATCH 0877/1979] build(deps): bump cryptography from 38.0.3 to 39.0.1 in /synthtool/gcp/templates/java_library/.kokoro (#1761) (#1130) * build(deps): bump cryptography Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.3 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/38.0.3...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... * chore: disabling dependabot --------- Source-Link: https://github.com/googleapis/synthtool/commit/0c6f8d4ac5358553ee734e26574f390bc43a736e Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:5ee35ee919254a3d1e7d4f8abbf1b8c8869ade317ceb2e4df709af1b4b3e9ca1 Signed-off-by: dependabot[bot] Co-authored-by: Owl Bot Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tomo Suzuki Co-authored-by: ddixit14 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/dependabot.yml | 14 ++++++ java-spanner-jdbc/.kokoro/requirements.txt | 53 +++++++++------------ 3 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 java-spanner-jdbc/.github/dependabot.yml diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index f8a8575314cc..090264303f34 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:bd5071596a47614d1fe15eb766c4255bae330f823b606e1196a3b0c8d2e96fd1 + digest: sha256:5ee35ee919254a3d1e7d4f8abbf1b8c8869ade317ceb2e4df709af1b4b3e9ca1 diff --git a/java-spanner-jdbc/.github/dependabot.yml b/java-spanner-jdbc/.github/dependabot.yml new file mode 100644 index 000000000000..c8f413b0da30 --- /dev/null +++ b/java-spanner-jdbc/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + # Disable version updates for Maven dependencies + open-pull-requests-limit: 0 + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "daily" + # Disable version updates for pip dependencies + open-pull-requests-limit: 0 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 4895c9631fd8..cfadd22ce9b9 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -97,33 +97,28 @@ colorlog==6.7.0 \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 # via gcp-docuploader -cryptography==38.0.3 \ - --hash=sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d \ - --hash=sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd \ - --hash=sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146 \ - --hash=sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7 \ - --hash=sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436 \ - --hash=sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0 \ - --hash=sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828 \ - --hash=sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b \ - --hash=sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55 \ - --hash=sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36 \ - --hash=sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50 \ - --hash=sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2 \ - --hash=sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a \ - --hash=sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8 \ - --hash=sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0 \ - --hash=sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548 \ - --hash=sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320 \ - --hash=sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748 \ - --hash=sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249 \ - --hash=sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959 \ - --hash=sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f \ - --hash=sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0 \ - --hash=sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd \ - --hash=sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220 \ - --hash=sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c \ - --hash=sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722 +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 # via # gcp-releasetool # secretstorage @@ -379,10 +374,6 @@ secretstorage==3.3.3 \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 # via keyring -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via -r requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 From da499a9d3d88c18ccf8398da34dbc36717350fde Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Feb 2023 09:53:27 +0000 Subject: [PATCH 0878/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.5 (#1129) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 96f238fb61c6..f9507d2ee6bc 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.4 + 2.9.5 From e39a31034faadff2aa0dd56db9630e96f214c63b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 17:14:15 +0000 Subject: [PATCH 0879/1979] chore(main): release 2.9.6 (#1134) :robot: I have created a release *beep* *boop* --- ## [2.9.6](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.5...v2.9.6) (2023-02-20) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.3.0 ([#1133](https://togithub.com/googleapis/java-spanner-jdbc/issues/1133)) ([a488320](https://togithub.com/googleapis/java-spanner-jdbc/commit/a48832032e77262fa8feb0b3196808b5c0b434f8)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index dabe9ea7d079..9b0d6f3dde89 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.5...v2.9.6) (2023-02-20) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.3.0 ([#1133](https://github.com/googleapis/java-spanner-jdbc/issues/1133)) ([57d8c6d](https://github.com/googleapis/java-spanner-jdbc/commit/57d8c6d93d681644fac1e18cc9ba1ab80595feb4)) + ## [2.9.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.4...v2.9.5) (2023-02-09) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 08da2adf5c70..e7927c783859 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.6-SNAPSHOT + 2.9.6 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8d3d6534ffd6..74406429eca5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.6-SNAPSHOT + 2.9.6 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 41d3d480a2cd..a71451443e87 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.5:2.9.6-SNAPSHOT +google-cloud-spanner-jdbc:2.9.6:2.9.6 From c472c71653352d032ff213843019e9c444b7e7d3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 18:38:12 +0000 Subject: [PATCH 0880/1979] chore(main): release 2.9.7-SNAPSHOT (#1135) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e7927c783859..d2a33988a7eb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.6 + 2.9.7-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 74406429eca5..76ce3b9e1b30 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.6 + 2.9.7-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a71451443e87..0837cf41aaa1 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.6:2.9.6 +google-cloud-spanner-jdbc:2.9.6:2.9.7-SNAPSHOT From 552433f5b6c722c26c9b085d2e48863fdbca3424 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 21 Feb 2023 08:58:29 +0000 Subject: [PATCH 0881/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.6 (#1136) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f9507d2ee6bc..833a43622390 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.5 + 2.9.6 From 9de864526120104510841b246c76ca6acb66f11b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 10:26:11 +0000 Subject: [PATCH 0882/1979] build(deps): bump cryptography from 38.0.3 to 39.0.1 in /.kokoro (#1124) Bumps [cryptography](https://togithub.com/pyca/cryptography) from 38.0.3 to 39.0.1.
    Changelog

    Sourced from cryptography's changelog.

    39.0.1 - 2023-02-07

    
    * **SECURITY ISSUE** - Fixed a bug where ``Cipher.update_into`` accepted Python
      buffer protocol objects, but allowed immutable buffers. **CVE-2023-23931**
    * Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.0.8.
    

    .. _v39-0-0:

    39.0.0 - 2023-01-01

    • BACKWARDS INCOMPATIBLE: Support for OpenSSL 1.1.0 has been removed. Users on older version of OpenSSL will need to upgrade.
    • BACKWARDS INCOMPATIBLE: Dropped support for LibreSSL < 3.5. The new minimum LibreSSL version is 3.5.0. Going forward our policy is to support versions of LibreSSL that are available in versions of OpenBSD that are still receiving security support.
    • BACKWARDS INCOMPATIBLE: Removed the encode_point and from_encoded_point methods on :class:~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers, which had been deprecated for several years. :meth:~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.public_bytes and :meth:~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point should be used instead.
    • BACKWARDS INCOMPATIBLE: Support for using MD5 or SHA1 in :class:~cryptography.x509.CertificateBuilder, other X.509 builders, and PKCS7 has been removed.
    • BACKWARDS INCOMPATIBLE: Dropped support for macOS 10.10 and 10.11, macOS users must upgrade to 10.12 or newer.
    • ANNOUNCEMENT: The next version of cryptography (40.0) will change the way we link OpenSSL. This will only impact users who build cryptography from source (i.e., not from a wheel), and specify their own version of OpenSSL. For those users, the CFLAGS, LDFLAGS, INCLUDE, LIB, and CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS environment variables will no longer be respected. Instead, users will need to configure their builds as documented here_.
    • Added support for :ref:disabling the legacy provider in OpenSSL 3.0.x<legacy-provider>.
    • Added support for disabling RSA key validation checks when loading RSA keys via :func:~cryptography.hazmat.primitives.serialization.load_pem_private_key, :func:~cryptography.hazmat.primitives.serialization.load_der_private_key, and :meth:~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers.private_key. This speeds up key loading but is :term:unsafe if you are loading potentially attacker supplied keys.
    • Significantly improved performance for :class:~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305

    ... (truncated)

    Commits

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cryptography&package-manager=pip&previous-version=38.0.3&new-version=39.0.1)](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) - `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language - `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language - `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language - `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language 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 5ed6119b9602885f5f6f7f089d6ab85998f61b10 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 21 Feb 2023 11:28:11 +0000 Subject: [PATCH 0883/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.1 (#1138) 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.36.0` -> `6.36.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.36.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.36.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.36.1/compatibility-slim/6.36.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.36.1/confidence-slim/6.36.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.36.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6361-httpsgithubcomgoogleapisjava-spannercomparev6360v6361-2023-02-21) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.36.0...v6.36.1) ##### Bug Fixes - Prevent illegal negative timeout values into thread sleep() method while retrying exceptions in unit tests. ([#​2268](https://togithub.com/googleapis/java-spanner/issues/2268)) ([ce66098](https://togithub.com/googleapis/java-spanner/commit/ce66098c7139ea13d5ea91cf6fbceb5c732b392d)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-spanner-executor-v1 to v1.2.0 ([#​2256](https://togithub.com/googleapis/java-spanner/issues/2256)) ([f0ca86a](https://togithub.com/googleapis/java-spanner/commit/f0ca86a0858bde84cc38f1ad8fae5f3c4f4f3395)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.12.0 ([#​2284](https://togithub.com/googleapis/java-spanner/issues/2284)) ([0be701a](https://togithub.com/googleapis/java-spanner/commit/0be701a8b59277f2cfb990a88e4f1dafcbafdd97)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.3.0 ([#​2285](https://togithub.com/googleapis/java-spanner/issues/2285)) ([bb5d5c6](https://togithub.com/googleapis/java-spanner/commit/bb5d5c66e78812b943a85e0fd888e7021c11bde1)) - Update dependency com.google.cloud:google-cloud-trace to v2.11.0 ([#​2286](https://togithub.com/googleapis/java-spanner/issues/2286)) ([3c80932](https://togithub.com/googleapis/java-spanner/commit/3c80932d577de0ea108e695d0a4e542fbfc01deb)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.20 ([#​2280](https://togithub.com/googleapis/java-spanner/issues/2280)) ([685d1ea](https://togithub.com/googleapis/java-spanner/commit/685d1ea1c3bf59cd71093a68c260276c605d835f)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.20 ([#​2281](https://togithub.com/googleapis/java-spanner/issues/2281)) ([f2aabc2](https://togithub.com/googleapis/java-spanner/commit/f2aabc24770d1b9c505dfc96b39fe81c6a0ad5a5))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d2a33988a7eb..a9084080e6e6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.36.0 + 6.36.1 pom import From f8509c39f0186941d1d043ed884e12f44898977e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 12:54:12 +0000 Subject: [PATCH 0884/1979] chore(main): release 2.9.7 (#1139) :robot: I have created a release *beep* *boop* --- ## [2.9.7](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.6...v2.9.7) (2023-02-21) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.1 ([#1138](https://togithub.com/googleapis/java-spanner-jdbc/issues/1138)) ([5ed6119](https://togithub.com/googleapis/java-spanner-jdbc/commit/5ed6119b9602885f5f6f7f089d6ab85998f61b10)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 9b0d6f3dde89..a4beb9ad2b58 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.6...v2.9.7) (2023-02-21) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.36.1 ([#1138](https://github.com/googleapis/java-spanner-jdbc/issues/1138)) ([b7b9916](https://github.com/googleapis/java-spanner-jdbc/commit/b7b99166febdb833e7af17a6c3f38ac7e3f8f767)) + ## [2.9.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.5...v2.9.6) (2023-02-20) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a9084080e6e6..2fe973851bc0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.7-SNAPSHOT + 2.9.7 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 76ce3b9e1b30..3cfc093beac5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.7-SNAPSHOT + 2.9.7 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0837cf41aaa1..afcc58e2a2cf 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.6:2.9.7-SNAPSHOT +google-cloud-spanner-jdbc:2.9.7:2.9.7 From 3c0b2773bb733a4468aa3177ff79857b8f40062f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 14:20:11 +0000 Subject: [PATCH 0885/1979] chore(main): release 2.9.8-SNAPSHOT (#1140) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2fe973851bc0..f7a71642ac09 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.7 + 2.9.8-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3cfc093beac5..920ddc0a2935 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.7 + 2.9.8-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index afcc58e2a2cf..4f1bf7d61a6d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.7:2.9.7 +google-cloud-spanner-jdbc:2.9.7:2.9.8-SNAPSHOT From acd0ff3ca571a2b391256b432b9651a46b2b6c28 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Feb 2023 20:30:42 +0000 Subject: [PATCH 0886/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.9.0 (#1144) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 068794f84ea0..a9e29ba0a60e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.8.0 + 26.9.0 pom import From 7f3c203f959725ed393c5c18233ee08806d3f875 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Feb 2023 20:31:12 +0000 Subject: [PATCH 0887/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.7 (#1141) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 833a43622390..bb0a4055d96e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.6 + 2.9.7 From 2c653ca34ae6f74d592f9d47c8bd0049d88ec430 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 21:58:12 +0000 Subject: [PATCH 0888/1979] build(deps): update releasetool version for release scripts (#1768) (#1142) This should fix release script reporting back to the release PRs Source-Link: https://togithub.com/googleapis/synthtool/commit/4c15ec0960687db8e6da43535fa1ee0e92fbb817 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:e62f3ea524b11c1cd6ff7f80362736d86c0056631346b5b106a421686fce2726 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/requirements.in | 2 +- java-spanner-jdbc/.kokoro/requirements.txt | 12 ++++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 090264303f34..a5361a30a366 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:5ee35ee919254a3d1e7d4f8abbf1b8c8869ade317ceb2e4df709af1b4b3e9ca1 + digest: sha256:e62f3ea524b11c1cd6ff7f80362736d86c0056631346b5b106a421686fce2726 diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in index b19a8dbfdd5e..2092cc741d9c 100644 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ b/java-spanner-jdbc/.kokoro/requirements.in @@ -1,5 +1,5 @@ gcp-docuploader -gcp-releasetool +gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x wheel setuptools typing-extensions diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index cfadd22ce9b9..c80f0a87cc53 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.9 +# This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --allow-unsafe --generate-hashes requirements.in @@ -126,9 +126,9 @@ gcp-docuploader==0.6.4 \ --hash=sha256:01486419e24633af78fd0167db74a2763974765ee8078ca6eb6964d0ebd388af \ --hash=sha256:70861190c123d907b3b067da896265ead2eeb9263969d6955c9e0bb091b5ccbf # via -r requirements.in -gcp-releasetool==1.9.1 \ - --hash=sha256:952f4055d5d986b070ae2a71c4410b250000f9cc5a1e26398fcd55a5bbc5a15f \ - --hash=sha256:d0d3c814a97c1a237517e837d8cfa668ced8df4b882452578ecef4a4e79c583b +gcp-releasetool==1.10.5 \ + --hash=sha256:174b7b102d704b254f2a26a3eda2c684fd3543320ec239baf771542a2e58e109 \ + --hash=sha256:e29d29927fe2ca493105a82958c6873bb2b90d503acac56be2c229e74de0eec9 # via -r requirements.in google-api-core==2.8.2 \ --hash=sha256:06f7244c640322b508b125903bb5701bebabce8832f85aba9335ec00b3d02edc \ @@ -374,6 +374,10 @@ 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 From e891fa5bb002cc1cc86fdb40fe32857cf6169172 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 4 Mar 2023 05:56:29 +0000 Subject: [PATCH 0889/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.4.0 (#1145) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f7a71642ac09..609520e9767c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.3.0 + 3.4.0 pom import From e87751706a1fe2518cd2fe0da871203639e6d1d1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 4 Mar 2023 07:22:47 +0000 Subject: [PATCH 0890/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.37.0 (#1146) 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.36.1` -> `6.37.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.37.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.37.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.37.0/compatibility-slim/6.36.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.37.0/confidence-slim/6.36.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.37.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6370-httpsgithubcomgoogleapisjava-spannercomparev6361v6370-2023-03-03) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.36.1...v6.37.0) ##### Features - Adding new fields for Serverless analytics ([#​2315](https://togithub.com/googleapis/java-spanner/issues/2315)) ([ce9cd74](https://togithub.com/googleapis/java-spanner/commit/ce9cd7469e2fed15711a8dffe944934cdaa45ce8)) ##### Bug Fixes - Update test certificate name. ([#​2300](https://togithub.com/googleapis/java-spanner/issues/2300)) ([18e76d6](https://togithub.com/googleapis/java-spanner/commit/18e76d6636c530c9cfc0ac872d72e321e75c990e)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-spanner-executor-v1 to v1.3.0 ([#​2306](https://togithub.com/googleapis/java-spanner/issues/2306)) ([8372250](https://togithub.com/googleapis/java-spanner/commit/8372250e0aaae68b0d610d59c1ee88c4dc0d9e8b)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.13.0 ([#​2311](https://togithub.com/googleapis/java-spanner/issues/2311)) ([6ba613b](https://togithub.com/googleapis/java-spanner/commit/6ba613b44598e48699aca320683e65572a730fc7)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.4.0 ([#​2312](https://togithub.com/googleapis/java-spanner/issues/2312)) ([266c49c](https://togithub.com/googleapis/java-spanner/commit/266c49cc58beaa935a328599a3e75d3b1fb4988d)) - Update dependency com.google.cloud:google-cloud-trace to v2.12.0 ([#​2313](https://togithub.com/googleapis/java-spanner/issues/2313)) ([e5f76c6](https://togithub.com/googleapis/java-spanner/commit/e5f76c6598887b616d371b4d0b3551e236e080f8)) - Update dependency org.json:json to v20230227 ([#​2310](https://togithub.com/googleapis/java-spanner/issues/2310)) ([badcc14](https://togithub.com/googleapis/java-spanner/commit/badcc14182244929042412f97e5a7e05799eea22))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 609520e9767c..f73e9fd928da 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.36.1 + 6.37.0 pom import From 996910e5b2c1b7ba6395921968f80095b24a66e6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 4 Mar 2023 08:52:36 +0000 Subject: [PATCH 0891/1979] chore(main): release 2.9.8 (#1147) :robot: I have created a release *beep* *boop* --- ## [2.9.8](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.7...v2.9.8) (2023-03-04) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.4.0 ([#1145](https://togithub.com/googleapis/java-spanner-jdbc/issues/1145)) ([e891fa5](https://togithub.com/googleapis/java-spanner-jdbc/commit/e891fa5bb002cc1cc86fdb40fe32857cf6169172)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.37.0 ([#1146](https://togithub.com/googleapis/java-spanner-jdbc/issues/1146)) ([e877517](https://togithub.com/googleapis/java-spanner-jdbc/commit/e87751706a1fe2518cd2fe0da871203639e6d1d1)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a4beb9ad2b58..91bdac73366c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.9.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.7...v2.9.8) (2023-03-04) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.4.0 ([#1145](https://github.com/googleapis/java-spanner-jdbc/issues/1145)) ([34864e7](https://github.com/googleapis/java-spanner-jdbc/commit/34864e73fc78399d08be7972c220e4794ac16dfb)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.37.0 ([#1146](https://github.com/googleapis/java-spanner-jdbc/issues/1146)) ([541a1f0](https://github.com/googleapis/java-spanner-jdbc/commit/541a1f0323c5d7d72cb33acd696660dd94224858)) + ## [2.9.7](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.6...v2.9.7) (2023-02-21) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f73e9fd928da..cc5157c3a8e6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.8-SNAPSHOT + 2.9.8 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 920ddc0a2935..940289008928 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.8-SNAPSHOT + 2.9.8 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4f1bf7d61a6d..27ad0441fe54 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.7:2.9.8-SNAPSHOT +google-cloud-spanner-jdbc:2.9.8:2.9.8 From 04be1101b06f8bf236db9490ab340b378c1699e7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 4 Mar 2023 10:18:47 +0000 Subject: [PATCH 0892/1979] chore(main): release 2.9.9-SNAPSHOT (#1148) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cc5157c3a8e6..de49578f232b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.8 + 2.9.9-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 940289008928..d06f0b5c53f7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.8 + 2.9.9-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 27ad0441fe54..2e1bea571543 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.8:2.9.8 +google-cloud-spanner-jdbc:2.9.8:2.9.9-SNAPSHOT From 0b88cecb3ce482aa87593eb2d060d4768ac289a4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 17 Mar 2023 09:42:25 +0000 Subject: [PATCH 0893/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.10.0 (#1151) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a9e29ba0a60e..6303085e5f4b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.9.0 + 26.10.0 pom import From 24915aba0049c61cf12249558b16c62cf75ac976 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 17 Mar 2023 09:42:42 +0000 Subject: [PATCH 0894/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.8 (#1149) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index bb0a4055d96e..0981a3e50b2a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.7 + 2.9.8 From 7caa2f9d8695b94ee0538b801996018bfc9d6704 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Mar 2023 08:53:28 +0000 Subject: [PATCH 0895/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.5.0 (#1153) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index de49578f232b..144c88e465b7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.4.0 + 3.5.0 pom import From a9149f08a44ca058454b7bb6e31a9562f05208f2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 Mar 2023 10:33:44 +0000 Subject: [PATCH 0896/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.0 (#1154) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 144c88e465b7..4af2ee7ccec3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.37.0 + 6.38.0 pom import From 6cc93a6f66ca5bde4040b7c9610944c90c754fc0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 12:02:12 +0000 Subject: [PATCH 0897/1979] chore(main): release 2.9.9 (#1155) :robot: I have created a release *beep* *boop* --- ## [2.9.9](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.8...v2.9.9) (2023-03-20) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.5.0 ([#1153](https://togithub.com/googleapis/java-spanner-jdbc/issues/1153)) ([7caa2f9](https://togithub.com/googleapis/java-spanner-jdbc/commit/7caa2f9d8695b94ee0538b801996018bfc9d6704)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.0 ([#1154](https://togithub.com/googleapis/java-spanner-jdbc/issues/1154)) ([a9149f0](https://togithub.com/googleapis/java-spanner-jdbc/commit/a9149f08a44ca058454b7bb6e31a9562f05208f2)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 91bdac73366c..e48a538cadfa 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.9.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.8...v2.9.9) (2023-03-20) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.5.0 ([#1153](https://github.com/googleapis/java-spanner-jdbc/issues/1153)) ([81969b5](https://github.com/googleapis/java-spanner-jdbc/commit/81969b512072443dac418dc82180cb49ee4113c1)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.0 ([#1154](https://github.com/googleapis/java-spanner-jdbc/issues/1154)) ([fe81de9](https://github.com/googleapis/java-spanner-jdbc/commit/fe81de965c170315554f438488ac8b1ef4667999)) + ## [2.9.8](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.7...v2.9.8) (2023-03-04) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4af2ee7ccec3..ae20c1ca39ec 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.9-SNAPSHOT + 2.9.9 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d06f0b5c53f7..0cac76da52f6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.9-SNAPSHOT + 2.9.9 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2e1bea571543..f6056bd41a00 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.8:2.9.9-SNAPSHOT +google-cloud-spanner-jdbc:2.9.9:2.9.9 From 0a030fa768cfdd600af8ac924f7f60c48adb6ccf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 10:35:17 +0100 Subject: [PATCH 0898/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.6.0 (#1160) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ae20c1ca39ec..df96d6f0e5a0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.5.0 + 3.6.0 pom import From 8401a849fb989301c7f56707cc2c4fbdc8bf928d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 10:35:43 +0100 Subject: [PATCH 0899/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.1 (#1159) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 2ed3c9c56284..b31e3d0bdf20 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -38,7 +38,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.0 + 3.1.1 true From 03d4f8dbb8715d5d08183b2792c1aaaa4083c743 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 10:36:04 +0100 Subject: [PATCH 0900/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.11.0 (#1158) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6303085e5f4b..6289a8567fd7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.10.0 + 26.11.0 pom import From 83c1186800c0ad6689d3dd7db275da41fda5f110 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 10:36:24 +0100 Subject: [PATCH 0901/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.9 (#1157) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0981a3e50b2a..44b88393aa45 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.8 + 2.9.9 From 2bdaafbb913110e592bd1c6e9b22ed9639a6b654 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 11:00:22 +0000 Subject: [PATCH 0902/1979] chore(main): release 2.9.10-SNAPSHOT (#1156) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index df96d6f0e5a0..7b8f49634893 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.9 + 2.9.10-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0cac76da52f6..21febe3e94c9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.9 + 2.9.10-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f6056bd41a00..5defa14c3cad 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.9:2.9.9 +google-cloud-spanner-jdbc:2.9.9:2.9.10-SNAPSHOT From 37357959f6de0f69afd8ffe38fdff709a207fd5e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 12:40:13 +0000 Subject: [PATCH 0903/1979] chore(main): release 2.9.10 (#1161) :robot: I have created a release *beep* *boop* --- ## [2.9.10](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.9...v2.9.10) (2023-03-29) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.6.0 ([#1160](https://togithub.com/googleapis/java-spanner-jdbc/issues/1160)) ([0a030fa](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a030fa768cfdd600af8ac924f7f60c48adb6ccf)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e48a538cadfa..61dd8a4be6fe 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.9...v2.9.10) (2023-03-29) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.6.0 ([#1160](https://github.com/googleapis/java-spanner-jdbc/issues/1160)) ([392819e](https://github.com/googleapis/java-spanner-jdbc/commit/392819e7705cd6a2b978b69c09fdb79f534a1215)) + ## [2.9.9](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.8...v2.9.9) (2023-03-20) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7b8f49634893..14a36317dcf6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.10-SNAPSHOT + 2.9.10 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 21febe3e94c9..e449fc0cfa66 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.10-SNAPSHOT + 2.9.10 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5defa14c3cad..41bd66f8408d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.9:2.9.10-SNAPSHOT +google-cloud-spanner-jdbc:2.9.10:2.9.10 From d035dc416a6f2f91008990721c712a5a9e8e8f9a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 15:02:13 +0100 Subject: [PATCH 0904/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.1 (#1162) 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.38.0` -> `6.38.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.38.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.38.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.38.1/compatibility-slim/6.38.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.38.1/confidence-slim/6.38.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.38.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6381-httpsgithubcomgoogleapisjava-spannercomparev6380v6381-2023-03-29) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.38.0...v6.38.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.6.0 ([#​2352](https://togithub.com/googleapis/java-spanner/issues/2352)) ([19175ce](https://togithub.com/googleapis/java-spanner/commit/19175ce22777ac68f8c825a438c0a2503234aa42))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14a36317dcf6..5e2870a62897 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.38.0 + 6.38.1 pom import From c5d24baeadd08bfbc11dc19d034ef9c9b5a61738 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Mar 2023 16:26:12 +0100 Subject: [PATCH 0905/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.10 (#1164) 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.9.9` -> `2.9.10` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.10/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.10/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.10/compatibility-slim/2.9.9)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.10/confidence-slim/2.9.9)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.9.10`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2910-httpsgithubcomgoogleapisjava-spanner-jdbccomparev299v2910-2023-03-29) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.9...v2.9.10) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.6.0 ([#​1160](https://togithub.com/googleapis/java-spanner-jdbc/issues/1160)) ([0a030fa](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a030fa768cfdd600af8ac924f7f60c48adb6ccf))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 44b88393aa45..0bc41d8fcf04 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.9 + 2.9.10 From ecd2f59bd6403368ed97390636705106bb504384 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 3 Apr 2023 08:05:49 +0100 Subject: [PATCH 0906/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.2 (#1165) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5e2870a62897..3ab5cd878270 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.38.1 + 6.38.2 pom import From 84c60ba7f57473d1197d193634007b8439d89d7b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 08:32:13 +0000 Subject: [PATCH 0907/1979] chore(main): release 2.9.11-SNAPSHOT (#1163) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ab5cd878270..3ad730e43027 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.10 + 2.9.11-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e449fc0cfa66..663dd4cbb55d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.10 + 2.9.11-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 41bd66f8408d..775e457d56c8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.10:2.9.10 +google-cloud-spanner-jdbc:2.9.10:2.9.11-SNAPSHOT From bb958090db894546c7134461281870e483bdc415 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 10:00:18 +0000 Subject: [PATCH 0908/1979] chore(main): release 2.9.11 (#1166) :robot: I have created a release *beep* *boop* --- ## [2.9.11](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.10...v2.9.11) (2023-04-03) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.1 ([#1162](https://togithub.com/googleapis/java-spanner-jdbc/issues/1162)) ([d035dc4](https://togithub.com/googleapis/java-spanner-jdbc/commit/d035dc416a6f2f91008990721c712a5a9e8e8f9a)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.2 ([#1165](https://togithub.com/googleapis/java-spanner-jdbc/issues/1165)) ([ecd2f59](https://togithub.com/googleapis/java-spanner-jdbc/commit/ecd2f59bd6403368ed97390636705106bb504384)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 61dd8a4be6fe..0f1b23b3c904 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.9.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.10...v2.9.11) (2023-04-03) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.1 ([#1162](https://github.com/googleapis/java-spanner-jdbc/issues/1162)) ([e114284](https://github.com/googleapis/java-spanner-jdbc/commit/e114284185fba67b983b0839b787affcfd741bb4)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.38.2 ([#1165](https://github.com/googleapis/java-spanner-jdbc/issues/1165)) ([8cbf519](https://github.com/googleapis/java-spanner-jdbc/commit/8cbf519905456b69e223d1f3d3e7d29b83ffd477)) + ## [2.9.10](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.9...v2.9.10) (2023-03-29) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ad730e43027..5e4fef01f3f1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.11-SNAPSHOT + 2.9.11 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 663dd4cbb55d..3e01b249f28b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.11-SNAPSHOT + 2.9.11 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 775e457d56c8..5ba8473aef44 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.10:2.9.11-SNAPSHOT +google-cloud-spanner-jdbc:2.9.11:2.9.11 From e4fbf946ce77b350ca1ecddc9013a1ef9b25a4d5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:34:12 +0000 Subject: [PATCH 0909/1979] chore(main): release 2.9.12-SNAPSHOT (#1167) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5e4fef01f3f1..035a1a7c7af7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.11 + 2.9.12-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3e01b249f28b..019deae6a8f7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.11 + 2.9.12-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5ba8473aef44..a6a1c33b4052 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.11:2.9.11 +google-cloud-spanner-jdbc:2.9.11:2.9.12-SNAPSHOT From 9ee7e8be65a40f1a9da8c1b2d054f33bc498b586 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 13 Apr 2023 22:08:45 +0100 Subject: [PATCH 0910/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.12.0 (#1169) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6289a8567fd7..7b5e6724e6a4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.11.0 + 26.12.0 pom import From 9c96789b129dbea7428a5dee6bf73c7c4baf74af Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 13 Apr 2023 22:09:05 +0100 Subject: [PATCH 0911/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.11 (#1168) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0bc41d8fcf04..31f313bb52f1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.10 + 2.9.11 From e0260091c6b663685395e3a329dd1ea6034cbff0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 19 Apr 2023 18:28:37 +0200 Subject: [PATCH 0912/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.7.0 (#1204) 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/gapic-generator-java) | `3.6.0` -> `3.7.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.7.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.7.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.7.0/compatibility-slim/3.6.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-dependencies/3.7.0/confidence-slim/3.6.0)](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://app.renovatebot.com/dashboard#github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 035a1a7c7af7..81664d22130b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.6.0 + 3.7.0 pom import From c83b8c2c690f67c7eb73e466c16079c96948f5e9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 19 Apr 2023 23:12:06 +0200 Subject: [PATCH 0913/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.3 (#1203) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 81664d22130b..908ab9917a5a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.2 + 3.4.3 From 96b7e911f4daceb32623e93511c50f0e5fe6fdfa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 19:43:41 +0530 Subject: [PATCH 0914/1979] chore(main): release 2.9.12 (#1206) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 0f1b23b3c904..cfa10aeee81e 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.12](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.11...v2.9.12) (2023-04-19) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.7.0 ([#1204](https://github.com/googleapis/java-spanner-jdbc/issues/1204)) ([370e237](https://github.com/googleapis/java-spanner-jdbc/commit/370e237da3cd04a0ad50ba306cc2bcb7e3a8ec22)) + ## [2.9.11](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.10...v2.9.11) (2023-04-03) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 908ab9917a5a..1f28854f7bb6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.12-SNAPSHOT + 2.9.12 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 019deae6a8f7..ae8ff1006fcf 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.12-SNAPSHOT + 2.9.12 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a6a1c33b4052..6c09cac5fea0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.11:2.9.12-SNAPSHOT +google-cloud-spanner-jdbc:2.9.12:2.9.12 From 7fdb78c41b8ffcacde53729bf1ee6ccb23775d84 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 15:40:12 +0000 Subject: [PATCH 0915/1979] chore(main): release 2.9.13-SNAPSHOT (#1208) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1f28854f7bb6..3e5f928aebc0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.12 + 2.9.13-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ae8ff1006fcf..23d62facd605 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.12 + 2.9.13-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6c09cac5fea0..3977760339fb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.12:2.9.12 +google-cloud-spanner-jdbc:2.9.12:2.9.13-SNAPSHOT From 68e34f4557d53f3ebc4ef100bd41a1f3e0172c06 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Apr 2023 22:14:20 +0200 Subject: [PATCH 0916/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.13.0 (#1210) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7b5e6724e6a4..fd0b2f9a1c52 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.12.0 + 26.13.0 pom import From 41ad7b0ce2ae8280d7443a9b1591afed2053a548 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Apr 2023 22:14:40 +0200 Subject: [PATCH 0917/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.12 (#1209) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 31f313bb52f1..fbc545bf7182 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.11 + 2.9.12 From 7f4c8dda83955576efd00b4388bbca661698976a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 25 Apr 2023 22:06:52 +0200 Subject: [PATCH 0918/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.8.0 (#1211) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3e5f928aebc0..e94922b3d41a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.7.0 + 3.8.0 pom import From 9a013f1e30c7d16e165a9b0f3daa1e1c1097358f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Apr 2023 19:24:12 +0200 Subject: [PATCH 0919/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.40.1 (#1207) 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.38.2` -> `6.40.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.40.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.40.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.40.1/compatibility-slim/6.38.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.40.1/confidence-slim/6.38.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.40.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6401-httpsgithubcomgoogleapisjava-spannercomparev6400v6401-2023-04-17) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.40.0...v6.40.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.16.0 ([#​2383](https://togithub.com/googleapis/java-spanner/issues/2383)) ([5d5c33a](https://togithub.com/googleapis/java-spanner/commit/5d5c33ae7c01e10112c72777f202187a50b55ac3)) - Update dependency com.google.cloud:google-cloud-trace to v2.15.0 ([#​2384](https://togithub.com/googleapis/java-spanner/issues/2384)) ([6b4ce1f](https://togithub.com/googleapis/java-spanner/commit/6b4ce1fc7ffd837fab6250e36269589d95f5b8c6)) ### [`v6.40.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6400-httpsgithubcomgoogleapisjava-spannercomparev6390v6400-2023-04-14) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.39.0...v6.40.0) ##### Features - Savepoints ([#​2278](https://togithub.com/googleapis/java-spanner/issues/2278)) ([b02f584](https://togithub.com/googleapis/java-spanner/commit/b02f58435b97346cc8e08a96635affe8383981bb)) ##### Performance Improvements - Remove custom transport executor ([#​2366](https://togithub.com/googleapis/java-spanner/issues/2366)) ([e27dbe5](https://togithub.com/googleapis/java-spanner/commit/e27dbe5f58229dab208eeeed44d53e741700c814)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.7.0 ([#​2377](https://togithub.com/googleapis/java-spanner/issues/2377)) ([40402af](https://togithub.com/googleapis/java-spanner/commit/40402af54f94f16619d018e252181db29ae6855e)) - Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.21 ([#​2379](https://togithub.com/googleapis/java-spanner/issues/2379)) ([ae7262d](https://togithub.com/googleapis/java-spanner/commit/ae7262d37391c0ec2fee1dcbb24899e4fa16ae17)) - Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.21 ([#​2380](https://togithub.com/googleapis/java-spanner/issues/2380)) ([0cb159e](https://togithub.com/googleapis/java-spanner/commit/0cb159efc97f02b42f064244e3812a0fd3d82db6)) ### [`v6.39.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6390-httpsgithubcomgoogleapisjava-spannercomparev6382v6390-2023-04-11) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.38.2...v6.39.0) ##### Features - Capture stack trace for session checkout is now optional ([#​2350](https://togithub.com/googleapis/java-spanner/issues/2350)) ([6b6427a](https://togithub.com/googleapis/java-spanner/commit/6b6427a25af25fde944dfc1dd4bf6a6463682caf))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e94922b3d41a..29e262999ca1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.38.2 + 6.40.1 pom import From 1e98789f5c7878b2d657ea605e4d8cb152a747e2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 18:48:12 +0000 Subject: [PATCH 0920/1979] chore(main): release 2.9.13 (#1213) :robot: I have created a release *beep* *boop* --- ## [2.9.13](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.12...v2.9.13) (2023-04-27) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.8.0 ([#1211](https://togithub.com/googleapis/java-spanner-jdbc/issues/1211)) ([7f4c8dd](https://togithub.com/googleapis/java-spanner-jdbc/commit/7f4c8dda83955576efd00b4388bbca661698976a)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.40.1 ([#1207](https://togithub.com/googleapis/java-spanner-jdbc/issues/1207)) ([9a013f1](https://togithub.com/googleapis/java-spanner-jdbc/commit/9a013f1e30c7d16e165a9b0f3daa1e1c1097358f)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index cfa10aeee81e..8787fcea45a2 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.9.13](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.12...v2.9.13) (2023-04-27) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.8.0 ([#1211](https://github.com/googleapis/java-spanner-jdbc/issues/1211)) ([a7e762d](https://github.com/googleapis/java-spanner-jdbc/commit/a7e762dddc2e0165bbf8e3e722df3b46c2b9a089)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.40.1 ([#1207](https://github.com/googleapis/java-spanner-jdbc/issues/1207)) ([44ea7f8](https://github.com/googleapis/java-spanner-jdbc/commit/44ea7f8520230c7a9c632e42b7b668f179d4aa95)) + ## [2.9.12](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.11...v2.9.12) (2023-04-19) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 29e262999ca1..87541b737409 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.13-SNAPSHOT + 2.9.13 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 23d62facd605..382caa1601e6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.13-SNAPSHOT + 2.9.13 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3977760339fb..edc5bc39c9b5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.12:2.9.13-SNAPSHOT +google-cloud-spanner-jdbc:2.9.13:2.9.13 From 22de5e44ce4b5975cfba0707d1fa198004e14dea Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 20:16:13 +0000 Subject: [PATCH 0921/1979] chore(main): release 2.9.14-SNAPSHOT (#1214) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 87541b737409..4d34d55d27d0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.13 + 2.9.14-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 382caa1601e6..569ea6e0938e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.13 + 2.9.14-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index edc5bc39c9b5..49dc4717745e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.13:2.9.13 +google-cloud-spanner-jdbc:2.9.13:2.9.14-SNAPSHOT From 5eb59cb8a461194f6cccf4cecbfa942f4218c34d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Apr 2023 09:12:33 +0200 Subject: [PATCH 0922/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.13 (#1215) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index fbc545bf7182..f5dad4026acb 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.12 + 2.9.13 From 5e695121f7bdbc0fa0256e7a4525f5172f1ff75b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 2 May 2023 07:39:18 +0200 Subject: [PATCH 0923/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.41.0 (#1216) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4d34d55d27d0..55507d22760a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.40.1 + 6.41.0 pom import From d2a7260956459dab2d7859ffbe8b7d9888b93d28 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 07:04:12 +0000 Subject: [PATCH 0924/1979] chore(main): release 2.9.14 (#1219) :robot: I have created a release *beep* *boop* --- ## [2.9.14](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.13...v2.9.14) (2023-05-02) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.41.0 ([#1216](https://togithub.com/googleapis/java-spanner-jdbc/issues/1216)) ([5e69512](https://togithub.com/googleapis/java-spanner-jdbc/commit/5e695121f7bdbc0fa0256e7a4525f5172f1ff75b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8787fcea45a2..e0df17e34f6a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.14](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.13...v2.9.14) (2023-05-02) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.41.0 ([#1216](https://github.com/googleapis/java-spanner-jdbc/issues/1216)) ([9d0be37](https://github.com/googleapis/java-spanner-jdbc/commit/9d0be37fcea0ab90f8408b433295f7640f059f0a)) + ## [2.9.13](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.12...v2.9.13) (2023-04-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 55507d22760a..3cd65a06511c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.14-SNAPSHOT + 2.9.14 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 569ea6e0938e..c4d61c015305 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.14-SNAPSHOT + 2.9.14 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 49dc4717745e..1e393074d44e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.13:2.9.14-SNAPSHOT +google-cloud-spanner-jdbc:2.9.14:2.9.14 From ca34171b4a9cc9d05b093122ea142228c399ae79 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 08:30:38 +0000 Subject: [PATCH 0925/1979] chore(main): release 2.9.15-SNAPSHOT (#1220) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3cd65a06511c..ccf70efa7ad1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.14 + 2.9.15-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c4d61c015305..3a177735b17f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.14 + 2.9.15-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1e393074d44e..1c0dac8fd291 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.14:2.9.14 +google-cloud-spanner-jdbc:2.9.14:2.9.15-SNAPSHOT From 43ef301b4538d247ace00865ec196fb7ab8c2624 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 2 May 2023 12:02:12 +0200 Subject: [PATCH 0926/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.14 (#1222) 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.9.13` -> `2.9.14` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.14/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.14/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.14/compatibility-slim/2.9.13)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.9.14/confidence-slim/2.9.13)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.9.14`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2914-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2913v2914-2023-05-02) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.13...v2.9.14) ##### Dependencies - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.41.0 ([#​1216](https://togithub.com/googleapis/java-spanner-jdbc/issues/1216)) ([5e69512](https://togithub.com/googleapis/java-spanner-jdbc/commit/5e695121f7bdbc0fa0256e7a4525f5172f1ff75b))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f5dad4026acb..88f873d13041 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.13 + 2.9.14 From e9ab094337627c16305969f5357c277cf7a78b16 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 May 2023 10:01:05 +0200 Subject: [PATCH 0927/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.9.0 (#1227) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ccf70efa7ad1..d0d636c78aac 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.8.0 + 3.9.0 pom import From f42e782696d08b7c24c23d8a5be5fd18fab2377c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 May 2023 10:01:23 +0200 Subject: [PATCH 0928/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.14.0 (#1226) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fd0b2f9a1c52..fcbbc8e01ec8 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.13.0 + 26.14.0 pom import From f041855647b661bb732dcac53aadad1aceccd6dc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 May 2023 10:01:40 +0200 Subject: [PATCH 0929/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 (#1225) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 88f873d13041..f51dd65f7289 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3a177735b17f..0b7dc9e035fd 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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 43698ca08f14fa73b528566838db9a25fbb328e5 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 22:15:21 +0530 Subject: [PATCH 0930/1979] chore(deps): update ghcr.io/graalvm/graalvm-ce docker tag to v22.3.2 (#1793) (#1223) Source-Link: https://github.com/googleapis/synthtool/commit/99ad07938fb6bcddcc7b1b586be699d72440758b Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:8dd8395defb6a5069b0b10c435058bf13980606ba1967e2b3925ed50fc3cb22f Co-authored-by: Owl Bot Co-authored-by: Mridula <66699525+mpeddada1@users.noreply.github.com> --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index a5361a30a366..35478afe3fdd 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:e62f3ea524b11c1cd6ff7f80362736d86c0056631346b5b106a421686fce2726 + digest: sha256:8dd8395defb6a5069b0b10c435058bf13980606ba1967e2b3925ed50fc3cb22f diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index e20330c3ca60..f52533545896 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.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.0" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm17:22.3.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 0fd6ba2fa0ce..44b1004875b6 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.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.0" + value: "gcr.io/cloud-devrel-kokoro-resources/graalvm:22.3.2" } env_vars: { From 5cf2d44983f86f0130316e738f5481753b6adc00 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 22:15:53 +0530 Subject: [PATCH 0931/1979] chore(main): release 2.9.15 (#1228) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 4 ++-- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e0df17e34f6a..ca9c7eba2780 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.15](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.14...v2.9.15) (2023-05-15) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.9.0 ([#1227](https://github.com/googleapis/java-spanner-jdbc/issues/1227)) ([329f258](https://github.com/googleapis/java-spanner-jdbc/commit/329f25862a0f7118cc0419568eca3a72a053a055)) + ## [2.9.14](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.13...v2.9.14) (2023-05-02) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d0d636c78aac..e4487d869e15 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.15-SNAPSHOT + 2.9.15 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f51dd65f7289..88f873d13041 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.3.0 add-snippets-source diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0b7dc9e035fd..3844cf0861f3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.15-SNAPSHOT + 2.9.15 @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.4.0 + 3.3.0 add-snippets-source diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1c0dac8fd291..ac72d517e290 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.14:2.9.15-SNAPSHOT +google-cloud-spanner-jdbc:2.9.15:2.9.15 From 12c2b4d420a338163151c97f022fa0cbfd3c3ea9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 18:14:13 +0000 Subject: [PATCH 0932/1979] chore(main): release 2.9.16-SNAPSHOT (#1229) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e4487d869e15..387836917ab5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.15 + 2.9.16-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3844cf0861f3..ef5b3cfee9f0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.15 + 2.9.16-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ac72d517e290..c29c28704a33 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.15:2.9.15 +google-cloud-spanner-jdbc:2.9.15:2.9.16-SNAPSHOT From 2c3b7bc68db24f8e0c6f618f81646b950da0778b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 May 2023 21:37:21 +0200 Subject: [PATCH 0933/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.0 (#1231) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 387836917ab5..4ea5733140a7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.41.0 + 6.42.0 pom import From b59d8851e91273adb7622c73ec479600514fe230 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 May 2023 21:37:39 +0200 Subject: [PATCH 0934/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.15 (#1230) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 88f873d13041..7e5dd84f08f8 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.14 + 2.9.15 From f278b938de2fe2476dfe5d1d923774c79fae58d2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 22:24:12 +0000 Subject: [PATCH 0935/1979] chore(main): release 2.9.16 (#1232) :robot: I have created a release *beep* *boop* --- ## [2.9.16](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.15...v2.9.16) (2023-05-15) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.0 ([#1231](https://togithub.com/googleapis/java-spanner-jdbc/issues/1231)) ([2c3b7bc](https://togithub.com/googleapis/java-spanner-jdbc/commit/2c3b7bc68db24f8e0c6f618f81646b950da0778b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ca9c7eba2780..63e2bbf639f9 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.16](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.15...v2.9.16) (2023-05-15) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.0 ([#1231](https://github.com/googleapis/java-spanner-jdbc/issues/1231)) ([011570f](https://github.com/googleapis/java-spanner-jdbc/commit/011570ffb1d18fafe0a322d5582c5f7206349e09)) + ## [2.9.15](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.14...v2.9.15) (2023-05-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4ea5733140a7..22180dc3be7d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.16-SNAPSHOT + 2.9.16 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7e5dd84f08f8..88f873d13041 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.15 + 2.9.14 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ef5b3cfee9f0..55fd3483a44f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.16-SNAPSHOT + 2.9.16 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c29c28704a33..990caee80d50 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.15:2.9.16-SNAPSHOT +google-cloud-spanner-jdbc:2.9.16:2.9.16 From 4110efbdaa3a927353a779eb3dedf019e10a909c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 23:48:12 +0000 Subject: [PATCH 0936/1979] chore(main): release 2.9.17-SNAPSHOT (#1233) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 22180dc3be7d..9390393f2684 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.16 + 2.9.17-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 55fd3483a44f..80fc675f365d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.16 + 2.9.17-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 990caee80d50..48bb49733ebb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.16:2.9.16 +google-cloud-spanner-jdbc:2.9.16:2.9.17-SNAPSHOT From bc2c4d59281c9189ec53c84b42368c3679217d86 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 17:06:35 +0000 Subject: [PATCH 0937/1979] build: migrate release scripts (#1799) (#1236) Source-Link: https://togithub.com/googleapis/synthtool/commit/1fd6dff029bb3d873a4780e616388f802f086907 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:ad9cabee4c022f1aab04a71332369e0c23841062124818a4490f73337f790337 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 2 +- java-spanner-jdbc/.github/release-trigger.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 35478afe3fdd..aadf54f6438e 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:8dd8395defb6a5069b0b10c435058bf13980606ba1967e2b3925ed50fc3cb22f + digest: sha256:ad9cabee4c022f1aab04a71332369e0c23841062124818a4490f73337f790337 diff --git a/java-spanner-jdbc/.github/release-trigger.yml b/java-spanner-jdbc/.github/release-trigger.yml index d4ca94189e16..5e6624896347 100644 --- a/java-spanner-jdbc/.github/release-trigger.yml +++ b/java-spanner-jdbc/.github/release-trigger.yml @@ -1 +1,2 @@ enabled: true +multiScmName: java-spanner-jdbc From 1faa77b2dbe3e2f622146e5cd788e699e261455c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 26 May 2023 16:20:52 +0200 Subject: [PATCH 0938/1979] feat: support Savepoint (#1212) * feat: support Savepoint Add support for emulated Savepoints that are now supported in the client library. * fix: clirr check --- .../clirr-ignored-differences.xml | 10 + .../spanner/jdbc/AbstractJdbcConnection.java | 22 - .../jdbc/CloudSpannerJdbcConnection.java | 7 + .../cloud/spanner/jdbc/JdbcConnection.java | 66 ++ .../cloud/spanner/jdbc/JdbcSavepoint.java | 58 ++ .../cloud/spanner/jdbc/JdbcSavepointTest.java | 47 ++ .../spanner/jdbc/SavepointMockServerTest.java | 697 ++++++++++++++++++ 7 files changed, 885 insertions(+), 22 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSavepoint.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSavepointTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index 235cb90749a5..a92ad53057b1 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -6,4 +6,14 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection com.google.cloud.spanner.Dialect getDialect() + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.connection.SavepointSupport getSavepointSupport() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setSavepointSupport(com.google.cloud.spanner.connection.SavepointSupport) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 1a6cfe2edd18..33cf3bc574a0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -28,7 +28,6 @@ import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; -import java.sql.Savepoint; import java.sql.Struct; import java.util.Properties; import java.util.concurrent.Executor; @@ -42,7 +41,6 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper "Only isolation level TRANSACTION_SERIALIZABLE is supported"; private static final String ONLY_CLOSE_ALLOWED = "Only holdability CLOSE_CURSORS_AT_COMMIT is supported"; - private static final String SAVEPOINTS_UNSUPPORTED = "Savepoints are not supported"; private static final String SQLXML_UNSUPPORTED = "SQLXML is not supported"; private static final String STRUCTS_UNSUPPORTED = "Structs are not supported"; private static final String ABORT_UNSUPPORTED = "Abort is not supported"; @@ -163,26 +161,6 @@ public void clearWarnings() throws SQLException { lastWarning = null; } - @Override - public Savepoint setSavepoint() throws SQLException { - return checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); - } - - @Override - public Savepoint setSavepoint(String name) throws SQLException { - return checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); - } - - @Override - public void rollback(Savepoint savepoint) throws SQLException { - checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); - } - - @Override - public void releaseSavepoint(Savepoint savepoint) throws SQLException { - checkClosedAndThrowUnsupported(SAVEPOINTS_UNSUPPORTED); - } - @Override public SQLXML createSQLXML() throws SQLException { return checkClosedAndThrowUnsupported(SQLXML_UNSUPPORTED); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 679fa8716c68..588e8e768b65 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.ResultSet; 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.SQLException; @@ -256,6 +257,12 @@ default String getStatementTag() throws SQLException { */ void setRetryAbortsInternally(boolean retryAbortsInternally) throws SQLException; + /** Returns the current savepoint support for this connection. */ + SavepointSupport getSavepointSupport() throws SQLException; + + /** Sets how savepoints should be supported on this connection. */ + void setSavepointSupport(SavepointSupport savepointSupport) throws SQLException; + /** * Writes the specified mutation directly to the database and commits the change. The value is * readable after the successful completion of this method. Writing multiple mutations to a diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 867695fa88e1..a710ac80bae7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -23,6 +23,7 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.connection.AutocommitDmlMode; 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.Iterators; import java.sql.Array; @@ -33,6 +34,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Savepoint; import java.sql.Statement; import java.sql.Timestamp; import java.util.HashMap; @@ -402,6 +404,70 @@ public String getSchema() throws SQLException { return ""; } + @Override + public SavepointSupport getSavepointSupport() throws SQLException { + checkClosed(); + return getSpannerConnection().getSavepointSupport(); + } + + @Override + public void setSavepointSupport(SavepointSupport savepointSupport) throws SQLException { + checkClosed(); + try { + getSpannerConnection().setSavepointSupport(savepointSupport); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public Savepoint setSavepoint() throws SQLException { + checkClosed(); + try { + JdbcSavepoint savepoint = JdbcSavepoint.unnamed(); + getSpannerConnection().savepoint(savepoint.internalGetSavepointName()); + return savepoint; + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + checkClosed(); + try { + JdbcSavepoint savepoint = JdbcSavepoint.named(name); + getSpannerConnection().savepoint(savepoint.internalGetSavepointName()); + return savepoint; + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + checkClosed(); + JdbcPreconditions.checkArgument(savepoint instanceof JdbcSavepoint, savepoint); + JdbcSavepoint jdbcSavepoint = (JdbcSavepoint) savepoint; + try { + getSpannerConnection().rollbackToSavepoint(jdbcSavepoint.internalGetSavepointName()); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + checkClosed(); + JdbcPreconditions.checkArgument(savepoint instanceof JdbcSavepoint, savepoint); + JdbcSavepoint jdbcSavepoint = (JdbcSavepoint) savepoint; + try { + getSpannerConnection().releaseSavepoint(jdbcSavepoint.internalGetSavepointName()); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + @Override public Timestamp getCommitTimestamp() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSavepoint.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSavepoint.java new file mode 100644 index 000000000000..3cd4c41377ef --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSavepoint.java @@ -0,0 +1,58 @@ +/* + * 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 java.sql.SQLException; +import java.sql.Savepoint; +import java.util.concurrent.atomic.AtomicInteger; + +class JdbcSavepoint implements Savepoint { + private static final AtomicInteger COUNTER = new AtomicInteger(); + + static JdbcSavepoint named(String name) { + return new JdbcSavepoint(-1, name); + } + + static JdbcSavepoint unnamed() { + int id = COUNTER.incrementAndGet(); + return new JdbcSavepoint(id, String.format("s_%d", id)); + } + + private final int id; + private final String name; + + private JdbcSavepoint(int id, String name) { + this.id = id; + this.name = name; + } + + @Override + public int getSavepointId() throws SQLException { + JdbcPreconditions.checkState(this.id >= 0, "This is a named savepoint"); + return id; + } + + @Override + public String getSavepointName() throws SQLException { + JdbcPreconditions.checkState(this.id < 0, "This is an unnamed savepoint"); + return name; + } + + String internalGetSavepointName() { + return name; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSavepointTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSavepointTest.java new file mode 100644 index 000000000000..50b000b7df2a --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSavepointTest.java @@ -0,0 +1,47 @@ +/* + * 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 java.sql.SQLException; +import java.sql.Savepoint; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcSavepointTest { + + @Test + public void testNamed() throws SQLException { + Savepoint savepoint = JdbcSavepoint.named("test"); + assertEquals("test", savepoint.getSavepointName()); + assertThrows(SQLException.class, savepoint::getSavepointId); + } + + @Test + public void testUnnamed() throws SQLException { + Savepoint savepoint = JdbcSavepoint.unnamed(); + assertTrue( + String.format("Savepoint id: %d", savepoint.getSavepointId()), + savepoint.getSavepointId() > 0); + assertThrows(SQLException.class, savepoint::getSavepointName); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java new file mode 100644 index 000000000000..2c5d5185def6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java @@ -0,0 +1,697 @@ +/* + * 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.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Mutation; +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.SavepointSupport; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedDueToConcurrentModificationException; +import com.google.common.base.Strings; +import com.google.protobuf.AbstractMessage; +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.RollbackRequest; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.util.List; +import java.util.stream.Collectors; +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 SavepointMockServerTest 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;autoCommit=false", + getPort(), "proj", "inst", "db"); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testCreateSavepoint() throws SQLException { + try (Connection connection = createConnection()) { + connection.setSavepoint("s1"); + + if (dialect == Dialect.POSTGRESQL) { + // PostgreSQL allows multiple savepoints with the same name. + connection.setSavepoint("s1"); + } else { + assertThrows(SQLException.class, () -> connection.setSavepoint("s1")); + } + + // Test invalid identifiers. + assertThrows(SQLException.class, () -> connection.setSavepoint(null)); + assertThrows(SQLException.class, () -> connection.setSavepoint("")); + assertThrows(SQLException.class, () -> connection.setSavepoint("1")); + assertThrows(SQLException.class, () -> connection.setSavepoint("-foo")); + assertThrows(SQLException.class, () -> connection.setSavepoint(Strings.repeat("t", 129))); + } + } + + @Test + public void testCreateSavepointWhenDisabled() throws SQLException { + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.DISABLED); + assertThrows(SQLException.class, () -> connection.setSavepoint("s1")); + } + } + + @Test + public void testReleaseSavepoint() throws SQLException { + try (Connection connection = createConnection()) { + Savepoint s1 = connection.setSavepoint("s1"); + connection.releaseSavepoint(s1); + assertThrows(SQLException.class, () -> connection.releaseSavepoint(s1)); + + Savepoint s1_2 = connection.setSavepoint("s1"); + Savepoint s2 = connection.setSavepoint("s2"); + connection.releaseSavepoint(s1_2); + // Releasing a savepoint also removes all savepoints after it. + assertThrows(SQLException.class, () -> connection.releaseSavepoint(s2)); + + if (dialect == Dialect.POSTGRESQL) { + // PostgreSQL allows multiple savepoints with the same name. + Savepoint savepoint1 = connection.setSavepoint("s1"); + Savepoint savepoint2 = connection.setSavepoint("s2"); + Savepoint savepoint1_2 = connection.setSavepoint("s1"); + connection.releaseSavepoint(savepoint1_2); + connection.releaseSavepoint(savepoint2); + connection.releaseSavepoint(savepoint1); + assertThrows(SQLException.class, () -> connection.releaseSavepoint(savepoint1)); + } + } + } + + @Test + public void testRollbackToSavepoint() throws SQLException { + for (SavepointSupport savepointSupport : + new SavepointSupport[] {SavepointSupport.ENABLED, SavepointSupport.FAIL_AFTER_ROLLBACK}) { + try (Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); + + Savepoint s1 = connection.setSavepoint("s1"); + connection.rollback(s1); + // Rolling back to a savepoint does not remove it, so we can roll back multiple times to the + // same savepoint. + connection.rollback(s1); + + Savepoint s2 = connection.setSavepoint("s2"); + connection.rollback(s1); + // Rolling back to a savepoint removes all savepoints after it. + assertThrows(SQLException.class, () -> connection.rollback(s2)); + + if (dialect == Dialect.POSTGRESQL) { + // PostgreSQL allows multiple savepoints with the same name. + Savepoint savepoint2 = connection.setSavepoint("s2"); + Savepoint savepoint1 = connection.setSavepoint("s1"); + connection.rollback(savepoint1); + connection.rollback(savepoint2); + connection.rollback(savepoint1); + connection.rollback(savepoint1); + connection.releaseSavepoint(savepoint1); + assertThrows(SQLException.class, () -> connection.rollback(savepoint1)); + } + } + } + } + + @Test + public void testSavepointInAutoCommit() throws SQLException { + try (Connection connection = createConnection()) { + connection.setAutoCommit(true); + assertThrows(SQLException.class, () -> connection.setSavepoint("s1")); + + // Starting a 'manual' transaction in autocommit mode should enable savepoints. + connection.createStatement().execute("begin transaction"); + Savepoint s1 = connection.setSavepoint("s1"); + connection.releaseSavepoint(s1); + } + } + + @Test + public void testRollbackToSavepointInReadOnlyTransaction() throws SQLException { + for (SavepointSupport savepointSupport : + new SavepointSupport[] {SavepointSupport.ENABLED, SavepointSupport.FAIL_AFTER_ROLLBACK}) { + try (Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); + connection.setReadOnly(true); + + // Read-only transactions also support savepoints, but they do not do anything. This feature + // is here purely for compatibility. + Savepoint s1 = connection.setSavepoint("s1"); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + + connection.rollback(s1); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + // Committing a read-only transaction is necessary to mark the end of the transaction. + // It is a no-op on Cloud Spanner. + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + BeginTransactionRequest beginRequest = + mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0); + assertTrue(beginRequest.getOptions().hasReadOnly()); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + mockSpanner.clearRequests(); + } + } + + @Test + public void testRollbackToSavepointInReadWriteTransaction() throws SQLException { + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + Savepoint s1 = connection.setSavepoint("s1"); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + + connection.rollback(s1); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + connection.commit(); + + // Read/write transactions are started with inlined Begin transaction options. + assertEquals(0, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + + List requests = + mockSpanner.getRequests().stream() + .filter( + request -> + request instanceof ExecuteSqlRequest + || request instanceof RollbackRequest + || request instanceof CommitRequest) + .collect(Collectors.toList()); + assertEquals(4, requests.size()); + int index = 0; + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(CommitRequest.class, requests.get(index++).getClass()); + } + } + + @Test + public void testRollbackToSavepointWithDmlStatements() throws SQLException { + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + // First do a query that is included in the transaction. + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, count); + } + // Set a savepoint and execute a couple of DML statements. + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + Savepoint s2 = connection.setSavepoint("s2"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + // Rollback the last DML statement and commit. + connection.rollback(s2); + + connection.commit(); + + // Read/write transactions are started with inlined Begin transaction options. + assertEquals(0, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(5, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + + List requests = + mockSpanner.getRequests().stream() + .filter( + request -> + request instanceof ExecuteSqlRequest + || request instanceof RollbackRequest + || request instanceof CommitRequest) + .collect(Collectors.toList()); + assertEquals(7, requests.size()); + int index = 0; + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(CommitRequest.class, requests.get(index++).getClass()); + } + } + + @Test + public void testRollbackToSavepointFails() throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + // Set a savepoint and execute a couple of DML statements. + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + // Change the result of the initial query. + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + // Rollback to before the DML statements. + // This will succeed as long as we don't execute any further statements. + connection.rollback(s1); + + // Trying to commit the transaction or execute any other statements on the transaction will + // fail. + assertThrows(JdbcAbortedDueToConcurrentModificationException.class, connection::commit); + + // Read/write transactions are started with inlined Begin transaction options. + assertEquals(0, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + assertEquals(2, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(4, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + + List requests = + mockSpanner.getRequests().stream() + .filter( + request -> + request instanceof ExecuteSqlRequest + || request instanceof RollbackRequest + || request instanceof CommitRequest) + .collect(Collectors.toList()); + assertEquals(6, requests.size()); + int index = 0; + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + } + } + + @Test + public void testRollbackToSavepointWithFailAfterRollback() throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.FAIL_AFTER_ROLLBACK); + + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + // Set a savepoint and execute a couple of DML statements. + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + // Rollback to before the DML statements. + // This will succeed as long as we don't execute any further statements. + connection.rollback(s1); + + // Trying to commit the transaction or execute any other statements on the transaction will + // fail with an FAILED_PRECONDITION error, as using a transaction after a rollback to + // savepoint has been disabled. + SQLException exception = assertThrows(SQLException.class, connection::commit); + assertEquals( + ErrorCode.FAILED_PRECONDITION.getGrpcStatusCode().value(), exception.getErrorCode()); + assertEquals( + "FAILED_PRECONDITION: Using a read/write transaction after rolling back to a " + + "savepoint is not supported with SavepointSupport=FAIL_AFTER_ROLLBACK", + exception.getMessage()); + } + } + + @Test + public void testRollbackToSavepointSucceedsWithRollback() throws SQLException { + for (SavepointSupport savepointSupport : + new SavepointSupport[] {SavepointSupport.ENABLED, SavepointSupport.FAIL_AFTER_ROLLBACK}) { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); + + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + // Change the result of the initial query and set a savepoint. + Savepoint s1 = connection.setSavepoint("s1"); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + // This will succeed as long as we don't execute any further statements. + connection.rollback(s1); + + // Rolling back the transaction should now be a no-op, as it has already been rolled back. + connection.rollback(); + + // Read/write transactions are started with inlined Begin transaction options. + assertEquals(0, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + mockSpanner.clearRequests(); + } + } + + @Test + public void testMultipleRollbacksWithChangedResults() throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + Savepoint s2 = connection.setSavepoint("s2"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + + // Change the result of the initial query to make sure that any retry will fail. + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + // This will succeed as long as we don't execute any further statements. + connection.rollback(s2); + // Rolling back one further should also work. + connection.rollback(s1); + + // Rolling back the transaction should now be a no-op, as it has already been rolled back. + connection.rollback(); + + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + } + + @Test + public void testMultipleRollbacks() throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + Savepoint s2 = connection.setSavepoint("s2"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + + // First roll back one step and then one more. + connection.rollback(s2); + connection.rollback(s1); + + // This will only commit the SELECT query. + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(4, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + + List requests = + mockSpanner.getRequests().stream() + .filter( + request -> + request instanceof ExecuteSqlRequest + || request instanceof RollbackRequest + || request instanceof CommitRequest) + .collect(Collectors.toList()); + assertEquals(6, requests.size()); + int index = 0; + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(CommitRequest.class, requests.get(index++).getClass()); + } + } + + @Test + public void testRollbackMutations() throws SQLException { + try (Connection con = createConnection()) { + CloudSpannerJdbcConnection connection = con.unwrap(CloudSpannerJdbcConnection.class); + connection.setSavepointSupport(SavepointSupport.ENABLED); + + connection.bufferedWrite(Mutation.newInsertBuilder("foo1").build()); + Savepoint s1 = connection.setSavepoint("s1"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection.bufferedWrite(Mutation.newInsertBuilder("foo2").build()); + connection.setSavepoint("s2"); + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + connection.bufferedWrite(Mutation.newInsertBuilder("foo3").build()); + + connection.rollback(s1); + + // This will only commit the first mutation. + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + CommitRequest commitRequest = mockSpanner.getRequestsOfType(CommitRequest.class).get(0); + assertEquals(1, commitRequest.getMutationsCount()); + assertEquals("foo1", commitRequest.getMutations(0).getInsert().getTable()); + } + } + + @Test + public void testRollbackBatchDml() throws SQLException { + try (Connection connection = createConnection()) { + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + Savepoint s1 = connection.setSavepoint("s1"); + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.executeBatch(); + } + Savepoint s2 = connection.setSavepoint("s2"); + + connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); + Savepoint s3 = connection.setSavepoint("s3"); + try (java.sql.Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.executeBatch(); + } + connection.setSavepoint("s4"); + + connection.rollback(s2); + + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(RollbackRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + + List requests = + mockSpanner.getRequests().stream() + .filter( + request -> + request instanceof ExecuteSqlRequest + || request instanceof RollbackRequest + || request instanceof CommitRequest + || request instanceof ExecuteBatchDmlRequest) + .collect(Collectors.toList()); + assertEquals(8, requests.size()); + int index = 0; + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteBatchDmlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteBatchDmlRequest.class, requests.get(index++).getClass()); + assertEquals(RollbackRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteSqlRequest.class, requests.get(index++).getClass()); + assertEquals(ExecuteBatchDmlRequest.class, requests.get(index++).getClass()); + assertEquals(CommitRequest.class, requests.get(index++).getClass()); + } + } + + @Test + public void testRollbackToSavepointWithoutInternalRetries() throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).setRetryAbortsInternally(false); + + Savepoint s1 = connection.setSavepoint("s1"); + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + // This should work. + connection.rollback(s1); + // Resuming after a rollback is not supported without internal retries enabled. + assertThrows( + SQLException.class, + () -> connection.createStatement().executeUpdate(INSERT_STATEMENT.getSql())); + } + } + + @Test + public void testRollbackToSavepointWithoutInternalRetriesInReadOnlyTransaction() + throws SQLException { + Statement statement = Statement.of("select * from foo where bar=true"); + int numRows = 10; + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); + try (Connection connection = createConnection()) { + connection.unwrap(CloudSpannerJdbcConnection.class).setRetryAbortsInternally(false); + connection.setReadOnly(true); + + Savepoint s1 = connection.setSavepoint("s1"); + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + + // Both rolling back and resuming after a rollback are supported in a read-only transaction, + // even if internal retries have been disabled. + connection.rollback(s1); + try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { + int count = 0; + while (resultSet.next()) { + count++; + } + assertEquals(numRows, count); + } + } + } +} From d57fbdb321e28cae948194df2744114792e1ba6c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 16:02:08 +0200 Subject: [PATCH 0939/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.4 (#1241) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9390393f2684..cfc7f9ad85d3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.3 + 3.4.4 From bb7326f44a0dc1722a9c9bd0e2729eb182cfae67 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 16:10:21 +0200 Subject: [PATCH 0940/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 (#1239) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cfc7f9ad85d3..0db72badf4a6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.9.0 + 3.10.1 pom import From dc47cd22eea5f14c41a7b81412c76a25c4546cca Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 16:15:24 +0200 Subject: [PATCH 0941/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.15.0 (#1235) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fcbbc8e01ec8..fa6b15a53984 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.14.0 + 26.15.0 pom import From 758306cc35465a4fe1991e432c8cccdd6fb549df Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 16:39:47 +0200 Subject: [PATCH 0942/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.9.16 (#1234) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 88f873d13041..f50aa3e306bd 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.14 + 2.9.16 From f18e2cfc11ba8cb8d0eabed68a3779a71595a101 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 15:34:35 +0000 Subject: [PATCH 0943/1979] build(deps): bump requests from 2.27.1 to 2.31.0 in /.kokoro (#1238) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [requests](https://togithub.com/psf/requests) from 2.27.1 to 2.31.0.
    Release notes

    Sourced from requests's releases.

    v2.31.0

    2.31.0 (2023-05-22)

    Security

    • Versions of Requests between v2.3.0 and v2.30.0 are vulnerable to potential forwarding of Proxy-Authorization headers to destination servers when following HTTPS redirects.

      When proxies are defined with user info (https://user:pass@proxy:8080), Requests will construct a Proxy-Authorization header that is attached to the request to authenticate with the proxy.

      In cases where Requests receives a redirect response, it previously reattached the Proxy-Authorization header incorrectly, resulting in the value being sent through the tunneled connection to the destination server. Users who rely on defining their proxy credentials in the URL are strongly encouraged to upgrade to Requests 2.31.0+ to prevent unintentional leakage and rotate their proxy credentials once the change has been fully deployed.

      Users who do not use a proxy or do not supply their proxy credentials through the user information portion of their proxy URL are not subject to this vulnerability.

      Full details can be read in our Github Security Advisory and CVE-2023-32681.

    v2.30.0

    2.30.0 (2023-05-03)

    Dependencies

    v2.29.0

    2.29.0 (2023-04-26)

    Improvements

    • Requests now defers chunked requests to the urllib3 implementation to improve standardization. (#6226)
    • Requests relaxes header component requirements to support bytes/str subclasses. (#6356)

    ... (truncated)

    Changelog

    Sourced from requests's changelog.

    2.31.0 (2023-05-22)

    Security

    • Versions of Requests between v2.3.0 and v2.30.0 are vulnerable to potential forwarding of Proxy-Authorization headers to destination servers when following HTTPS redirects.

      When proxies are defined with user info (https://user:pass@proxy:8080), Requests will construct a Proxy-Authorization header that is attached to the request to authenticate with the proxy.

      In cases where Requests receives a redirect response, it previously reattached the Proxy-Authorization header incorrectly, resulting in the value being sent through the tunneled connection to the destination server. Users who rely on defining their proxy credentials in the URL are strongly encouraged to upgrade to Requests 2.31.0+ to prevent unintentional leakage and rotate their proxy credentials once the change has been fully deployed.

      Users who do not use a proxy or do not supply their proxy credentials through the user information portion of their proxy URL are not subject to this vulnerability.

      Full details can be read in our Github Security Advisory and CVE-2023-32681.

    2.30.0 (2023-05-03)

    Dependencies

    2.29.0 (2023-04-26)

    Improvements

    • Requests now defers chunked requests to the urllib3 implementation to improve standardization. (#6226)
    • Requests relaxes header component requirements to support bytes/str subclasses. (#6356)

    2.28.2 (2023-01-12)

    ... (truncated)

    Commits

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=requests&package-manager=pip&previous-version=2.27.1&new-version=2.31.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 8e85c0767893bb3de1cbebf480dbfe853af8fc92 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 18:12:17 +0200 Subject: [PATCH 0944/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.2 (#1237) 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.0` -> `6.42.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.42.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.42.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.42.2/compatibility-slim/6.42.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-bom/6.42.2/confidence-slim/6.42.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner ### [`v6.42.2`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6422-httpsgithubcomgoogleapisjava-spannercomparev6421v6422-2023-05-30) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.42.1...v6.42.2) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.19.0 ([#​2466](https://togithub.com/googleapis/java-spanner/issues/2466)) ([6de2cf6](https://togithub.com/googleapis/java-spanner/commit/6de2cf6a2d075b4347d69b9af21ac0cf96413884)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 ([#​2465](https://togithub.com/googleapis/java-spanner/issues/2465)) ([0a89f49](https://togithub.com/googleapis/java-spanner/commit/0a89f49cd55311f4cb84a501aa302eab88b46575)) - Update dependency com.google.cloud:google-cloud-trace to v2.18.0 ([#​2467](https://togithub.com/googleapis/java-spanner/issues/2467)) ([45609ed](https://togithub.com/googleapis/java-spanner/commit/45609ed65e49147077eaaf3eb90ab0c732eef80b)) ### [`v6.42.1`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6421-httpsgithubcomgoogleapisjava-spannercomparev6420v6421-2023-05-22) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.42.0...v6.42.1) ##### Dependencies - Update dependency commons-io:commons-io to v2.12.0 ([#​2439](https://togithub.com/googleapis/java-spanner/issues/2439)) ([d08b226](https://togithub.com/googleapis/java-spanner/commit/d08b226d5da6272b2de5f66ee1657d03268e396d))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0db72badf4a6..4b87136ed7b2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.42.0 + 6.42.2 pom import From e452d2f54df267f1b23a9ae699a02328405895d3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 May 2023 23:18:13 +0200 Subject: [PATCH 0945/1979] test(deps): update dependency com.google.truth:truth to v1.1.4 (#1242) 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.truth:truth](https://togithub.com/google/truth) | `1.1.3` -> `1.1.4` | [![age](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.4/compatibility-slim/1.1.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.truth:truth/1.1.4/confidence-slim/1.1.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    google/truth ### [`v1.1.4`](https://togithub.com/google/truth/releases/tag/v1.1.4): 1.1.4 - Updated Truth to build with `-source 8 -target 8`. This means that it no longer runs under Java 7 VMs. It continues to run under Android, even old versions, for all apps that have [enabled support for Java 8 language features](https://developer.android.com/studio/write/java8-support#supported_features). ([`db5db24`](https://togithub.com/google/truth/commit/db5db2429)) - Updated Truth to depend on Guava 32.0.0. That release contains changes related to CVEs. Neither of the CVEs relates to any methods that are used by Truth, so this version bump is just about eliminating any warnings related to the old version and helping tools like Maven to select the newest version of Guava. ([`f8d4dbb`](https://togithub.com/google/truth/commit/f8d4dbba8adc65effba70879d59a39da092dce51), [`99b1df8`](https://togithub.com/google/truth/commit/99b1df8852a25b5638590bea1b55a31ae536936d)) - Added support for `value of: method()` to `expect.that`, matching the existing support for `assertThat`. ([`bd8efd0`](https://togithub.com/google/truth/commit/bd8efd003)) - Enhanced `IterableSubject.containsAtLeastElementsIn().inOrder()` to print an extra line that shows only the expected elements in their actual order. ([`9da7dd1`](https://togithub.com/google/truth/commit/9da7dd184)) - Annotated Truth for nullness. ([`2151add`](https://togithub.com/google/truth/commit/2151add71))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4b87136ed7b2..e05c4491e8af 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.1.3 + 1.1.4 4.11.0 2.2 0.31.1 From 0137630d08dc0cd0d06a93cb81b17b02f1d04e98 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 31 May 2023 07:33:34 +0200 Subject: [PATCH 0946/1979] test(deps): update dependency com.google.truth:truth to v1.1.4 (#1243) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f50aa3e306bd..7ac31aeb4202 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1.3 + 1.1.4 test
    diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 80fc675f365d..0fbf776be239 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1.3 + 1.1.4 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fa6b15a53984..cf10eb51d2cf 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.1.3 + 1.1.4 test From d57805eab90be981382992dfe607315a5a2e42a0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 11:03:55 +0530 Subject: [PATCH 0947/1979] chore(main): release 2.10.0 (#1240) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 63e2bbf639f9..57a583fc9bde 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.10.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.16...v2.10.0) (2023-05-30) + + +### Features + +* Support Savepoint ([#1212](https://github.com/googleapis/java-spanner-jdbc/issues/1212)) ([6833696](https://github.com/googleapis/java-spanner-jdbc/commit/683369633627367342b3a40e3abba4fa81069724)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 ([#1239](https://github.com/googleapis/java-spanner-jdbc/issues/1239)) ([8f7e7a7](https://github.com/googleapis/java-spanner-jdbc/commit/8f7e7a79be6d7326d7e6bdd6018bb76a695cb1b8)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.2 ([#1237](https://github.com/googleapis/java-spanner-jdbc/issues/1237)) ([97961b2](https://github.com/googleapis/java-spanner-jdbc/commit/97961b2c501d428575e283485386e04f4673d968)) + ## [2.9.16](https://github.com/googleapis/java-spanner-jdbc/compare/v2.9.15...v2.9.16) (2023-05-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e05c4491e8af..116956d90958 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.9.17-SNAPSHOT + 2.10.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0fbf776be239..6cd1705d32fb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.17-SNAPSHOT + 2.10.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 48bb49733ebb..363915b72d0c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.9.16:2.9.17-SNAPSHOT +google-cloud-spanner-jdbc:2.10.0:2.10.0 From 03af65486297d48ec3d6057b9ee42dbadf49034e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 07:00:18 +0000 Subject: [PATCH 0948/1979] chore(main): release 2.10.1-SNAPSHOT (#1244) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 116956d90958..781d2c109986 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.0 + 2.10.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6cd1705d32fb..675c8fe271a8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.10.0 + 2.10.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 363915b72d0c..151946b0ba64 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.10.0:2.10.0 +google-cloud-spanner-jdbc:2.10.0:2.10.1-SNAPSHOT From a7a423756a9ae18d406b27f4d5b7b7504289b890 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 31 May 2023 10:28:13 +0200 Subject: [PATCH 0949/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.10.0 (#1246) 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.9.16` -> `2.10.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.10.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.10.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.10.0/compatibility-slim/2.9.16)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner-jdbc/2.10.0/confidence-slim/2.9.16)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc ### [`v2.10.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#​2100-httpsgithubcomgoogleapisjava-spanner-jdbccomparev2916v2100-2023-05-30) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.9.16...v2.10.0) ##### Features - Support Savepoint ([#​1212](https://togithub.com/googleapis/java-spanner-jdbc/issues/1212)) ([1faa77b](https://togithub.com/googleapis/java-spanner-jdbc/commit/1faa77b2dbe3e2f622146e5cd788e699e261455c)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 ([#​1239](https://togithub.com/googleapis/java-spanner-jdbc/issues/1239)) ([bb7326f](https://togithub.com/googleapis/java-spanner-jdbc/commit/bb7326f44a0dc1722a9c9bd0e2729eb182cfae67)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.2 ([#​1237](https://togithub.com/googleapis/java-spanner-jdbc/issues/1237)) ([8e85c07](https://togithub.com/googleapis/java-spanner-jdbc/commit/8e85c0767893bb3de1cbebf480dbfe853af8fc92))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7ac31aeb4202..42875833f78f 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.9.16 + 2.10.0 From 323cf62899b05f20e2ca169ee5aa111b88505015 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 31 May 2023 21:03:46 +0200 Subject: [PATCH 0950/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.3 (#1248) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 781d2c109986..64082e85e6db 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.42.2 + 6.42.3 pom import From 7fea98f339e69aeda444f2207fa9704726742486 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 2 Jun 2023 16:46:12 +0200 Subject: [PATCH 0951/1979] 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index cf10eb51d2cf..06de2d0ece40 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.15.0 + 26.16.0 pom import From b4577cf5dbc95203991d8fd80961be181616af16 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 0952/1979] 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 d08309485b2ac4a322c9afae4c88d3ed29680b14 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 7 Jun 2023 04:43:32 +0200 Subject: [PATCH 0953/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.4.5 (#1253) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 64082e85e6db..3085d49860b1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.4 + 3.4.5 From 863418b77a0107d78c73910c08b9edb45c94dd98 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 0954/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 847f54d3887a..cd1c50a733d7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 3ce105aa747e..5fb4177fc8ad 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index b4c33a802f92..8f21e68d3819 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java index 9da17d7dbec3..d3607d842753 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index ea7c236a4b03..7e2481a239a5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index bbd37122cb60..ff0bff7a98e1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index c1d841696195..2864559c889e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 24579b27208c..153dd773d297 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql index aaba70c19884..6aa8e843cae2 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_Emulator.sql +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index 438d2d5df7b0..c77968b45236 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/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 1d15d79679b667be7faed9122ba41336675a7a8a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 10:36:45 +0200 Subject: [PATCH 0955/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 (#1254) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3085d49860b1..422b4c938254 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.10.1 + 3.11.0 pom import From 528aa6e1861c36871efd01d9fc8713b09a48218a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 16:18:22 +0200 Subject: [PATCH 0956/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.6 (#1250) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 422b4c938254..923ec36debfc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.5 + 1.5.6 From 0468d7cedfd27aecd3e7295519a42e1ca7cae032 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 12 Jun 2023 17:44:14 +0200 Subject: [PATCH 0957/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 923ec36debfc..55e62450c62b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.42.3 + 6.43.0 pom import From d625edc639fb6d868b8fd7ced8df6c77a39a7a55 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 0958/1979] 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)) ([863418b](https://togithub.com/googleapis/java-spanner-jdbc/commit/863418b77a0107d78c73910c08b9edb45c94dd98)) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.11.0 ([#1254](https://togithub.com/googleapis/java-spanner-jdbc/issues/1254)) ([1d15d79](https://togithub.com/googleapis/java-spanner-jdbc/commit/1d15d79679b667be7faed9122ba41336675a7a8a)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.42.3 ([#1248](https://togithub.com/googleapis/java-spanner-jdbc/issues/1248)) ([323cf62](https://togithub.com/googleapis/java-spanner-jdbc/commit/323cf62899b05f20e2ca169ee5aa111b88505015)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.0 ([#1255](https://togithub.com/googleapis/java-spanner-jdbc/issues/1255)) ([0468d7c](https://togithub.com/googleapis/java-spanner-jdbc/commit/0468d7cedfd27aecd3e7295519a42e1ca7cae032)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 57a583fc9bde..d51198acb0d2 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 55e62450c62b..9b0d4aec6aed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 675c8fe271a8..9b0ce3fe4fb7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 151946b0ba64..bee319b9a7bc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 f1b2d0dddd4cf3c35197d5981eb3f3ebd77e5e5a 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 0959/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9b0d4aec6aed..290d63312a95 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9b0ce3fe4fb7..5e328938b89f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bee319b9a7bc..71cbbdd6b0c2 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 28b5de163de2443e536476c2cd1bbf067d30210e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:16:42 +0200 Subject: [PATCH 0960/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.17.0 (#1259) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 06de2d0ece40..d4b7215b9fc6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.16.0 + 26.17.0 pom import From a2e212f1fce8323372b081fe2b539e1f946a4c24 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:17:02 +0200 Subject: [PATCH 0961/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 (#1260) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 42875833f78f..1e2ac9dfd4f0 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5e328938b89f..8559ccd43457 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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 0c460721908303fa97b48e18ae7b216ce1dcfc82 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jun 2023 22:17:24 +0200 Subject: [PATCH 0962/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.0 (#1258) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1e2ac9dfd4f0..8425d143f2f7 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.10.0 + 2.11.0 From d65e539ff4942877cb1207b112212d4b0a9035a0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jun 2023 19:36:50 +0200 Subject: [PATCH 0963/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.0 (#1262) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 290d63312a95..04a5953069f9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -256,7 +256,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.4.1 + 3.5.0 From 470d66f3b55af45d578be36fe454327a4979ece1 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 0964/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 3 ++- java-spanner-jdbc/.github/dependabot.yml | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index aadf54f6438e..73568a1e998c 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/dependabot.yml b/java-spanner-jdbc/.github/dependabot.yml index c8f413b0da30..fde1ced49fb9 100644 --- a/java-spanner-jdbc/.github/dependabot.yml +++ b/java-spanner-jdbc/.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 7f238a4b4ea0c8a1a59a3c51b32728c11817e55f 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 0965/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +-- java-spanner-jdbc/.github/dependabot.yml | 6 +++-- .../.github/sync-repo-settings.yaml | 3 +-- java-spanner-jdbc/.github/workflows/ci.yaml | 26 +++++++++++++++++-- java-spanner-jdbc/.kokoro/build.sh | 3 ++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 73568a1e998c..47a70ea40cf3 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/dependabot.yml b/java-spanner-jdbc/.github/dependabot.yml index fde1ced49fb9..203f9eaccf13 100644 --- a/java-spanner-jdbc/.github/dependabot.yml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 19bc1242ab7d..4879f02a5d4f 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index e3bb26e37719..65436cde4190 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index f315d0cc9727..1f2ae77dadd2 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.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 5b29614876ad2c04afb11aa2c2c13d08a561c8c2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:13:14 +0200 Subject: [PATCH 0966/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.12.0 (#1267) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 04a5953069f9..da881176bea1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.11.0 + 3.12.0 pom import From 5410ed3b18bc34e68e0a1a4f31044a40008f1eb5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:14:44 +0200 Subject: [PATCH 0967/1979] test(deps): update dependency com.google.truth:truth to v1.1.5 (#1264) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 8425d143f2f7..3902fadfa78b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8559ccd43457..fb3b84c008c2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d4b7215b9fc6..fe2761c64737 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -53,7 +53,7 @@ com.google.truth truth - 1.1.4 + 1.1.5 test From e5a7b4d1ad58cbd0200c48973badc9d0ed14dd8c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 20:15:19 +0200 Subject: [PATCH 0968/1979] test(deps): update dependency com.google.truth:truth to v1.1.5 (#1263) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index da881176bea1..7a3359980c06 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 a53df91c386425f22c9b1d1e6e37b16879ea19ce 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 0969/1979] 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)) ([5b29614](https://togithub.com/googleapis/java-spanner-jdbc/commit/5b29614876ad2c04afb11aa2c2c13d08a561c8c2)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d51198acb0d2..6153253200c5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7a3359980c06..e52047829f59 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fb3b84c008c2..95a4b010c5aa 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 71cbbdd6b0c2..37a47637a911 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 f66ae3b720435bb07b2c23cab230ab304cf06907 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jun 2023 22:56:15 +0200 Subject: [PATCH 0970/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e52047829f59..c93cfe9c8336 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.43.0 + 6.43.1 pom import From 28d278131e12e53ea6d36e8c8beae037f0da76e7 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 0971/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c93cfe9c8336..7225e3e6a7aa 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 95a4b010c5aa..104b8d2c9c82 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 37a47637a911..636b8ccd8834 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 5a60bb6882a5c1e0ee57cc5a72ef00ec0546f4ec 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 0972/1979] 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)) ([f66ae3b](https://togithub.com/googleapis/java-spanner-jdbc/commit/f66ae3b720435bb07b2c23cab230ab304cf06907)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6153253200c5..ff5ec7274137 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7225e3e6a7aa..5d9e4405fbb3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 104b8d2c9c82..07c7704a2c3f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 636b8ccd8834..ab9730ca68a0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 b7cdac3b4102f4154f0cc4fa9ecf400b7cd9ae63 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 0973/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5d9e4405fbb3..9827c001dc9a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 07c7704a2c3f..8c6952781144 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ab9730ca68a0..0ba2d4e46e45 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 d7f32355ea02efa26f7137e60d69d0a06d43eb49 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 4 Jul 2023 12:15:25 +0200 Subject: [PATCH 0974/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.2 (#1273) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3902fadfa78b..1ef1d77c7aca 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.0 + 2.11.2 From 485d907982a3b0e0628389b97e7eb10ca1d9d7e3 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 0975/1979] ci: javadoc job (JDK 17) in ci.yaml (#1819) (#1276) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +-- java-spanner-jdbc/.github/workflows/ci.yaml | 26 ++++++++++++++----- .../.github/workflows/samples.yaml | 2 +- .../jdbc/CloudSpannerJdbcConnection.java | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 47a70ea40cf3..258389d1aa68 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 65436cde4190..e27b2c57563c 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index 912ed8b2b027..10d252d77538 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 588e8e768b65..cf368f618aa7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/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 4fbb6a84704f6625649137a9335da1f563d245c0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 9 Jul 2023 05:55:18 +0200 Subject: [PATCH 0976/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.0 (#1278) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9827c001dc9a..9e467f4f9bdc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.12.0 + 3.13.0 pom import From d1c0979e1ab704b83ae1a476c8a26ab0a213687c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 9 Jul 2023 05:55:41 +0200 Subject: [PATCH 0977/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.18.0 (#1277) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fe2761c64737..0d6ea2d4b07b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.17.0 + 26.18.0 pom import From bc99384639345e89806741e9d23bd353072db22e 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 0978/1979] 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)) ([4fbb6a8](https://togithub.com/googleapis/java-spanner-jdbc/commit/4fbb6a84704f6625649137a9335da1f563d245c0)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ff5ec7274137..83a4d2f1dca9 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9e467f4f9bdc..b676d22d3913 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8c6952781144..ffe49a773849 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0d6ea2d4b07b..fe2761c64737 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.18.0 + 26.17.0 pom import diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0ba2d4e46e45..acd558c672ea 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 1a45df59cf902955e5f47c5264d6d47317a9fc07 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 0979/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b676d22d3913..b83d2d1d7f34 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ffe49a773849..822a348ad254 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index acd558c672ea..b6f4fdd38c62 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 a16a2ce91aa1960184094045398fc48ab6541faf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 11 Jul 2023 22:43:54 +0200 Subject: [PATCH 0980/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.3 (#1282) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1ef1d77c7aca..6fc24a99b688 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.2 + 2.11.3 From fb03e887aa6b37e0c9f72fffa61ce0e3bb26d96e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 11 Jul 2023 22:44:35 +0200 Subject: [PATCH 0981/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.18.0 (#1280) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fe2761c64737..0d6ea2d4b07b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.17.0 + 26.18.0 pom import From cd8ef212cf6516e2494e47e8e548ebfde8b75f96 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 12 Jul 2023 08:08:31 +0200 Subject: [PATCH 0982/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.43.2 (#1284) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b83d2d1d7f34..133992aa1cc0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.43.1 + 6.43.2 pom import From 0402902d373093d87f5b29444c92e170b6154205 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 0983/1979] 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)) ([cd8ef21](https://togithub.com/googleapis/java-spanner-jdbc/commit/cd8ef212cf6516e2494e47e8e548ebfde8b75f96)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 83a4d2f1dca9..afaa6625d23a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 133992aa1cc0..7c00c29c2d82 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 822a348ad254..9fc70aace0b6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b6f4fdd38c62..e1aefccd30dd 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 7bfc821e812561bf2024ecbc844098413f9beeeb 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 0984/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7c00c29c2d82..0960a2c62903 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9fc70aace0b6..a107a1997e3d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e1aefccd30dd..66cc4b7e4986 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 754ca5b69377d038d1b95c850eff212e9f0f080f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 17 Jul 2023 06:50:09 +0200 Subject: [PATCH 0985/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.4 (#1287) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6fc24a99b688..756be62c1607 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.3 + 2.11.4 From 4b989ddadb01f9fefff128bf5f88dd0bc892f3e1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 26 Jul 2023 17:14:35 +0200 Subject: [PATCH 0986/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.19.0 (#1289) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0d6ea2d4b07b..69f126379ff6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.18.0 + 26.19.0 pom import From 697be908d1010105f9285c67e52412c3334ab3c3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 26 Jul 2023 17:14:55 +0200 Subject: [PATCH 0987/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.7 (#1290) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0960a2c62903..0d2399a264e6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.6 + 1.5.7 From 1cdd210bd7f30a8286d726fe38a6ed0c14a55107 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 0988/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +- java-spanner-jdbc/.kokoro/requirements.txt | 573 +++++++++++--------- 2 files changed, 332 insertions(+), 245 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 258389d1aa68..d5500ef44246 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index c80f0a87cc53..32989051e7f9 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.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 18720857ec036cc955aa43f6abd2d7680e67ba5f 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 0989/1979] 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 3613970976373f481cf743b4474fecc4610790c0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jul 2023 10:56:46 +0200 Subject: [PATCH 0990/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.13.1 (#1291) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0d2399a264e6..858e36e5ecf9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.13.0 + 3.13.1 pom import From 901283d5a7e28819d1965cfed9d3156f95f27429 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 0991/1979] 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 9195c2ce9dd0fa42fcde4039b53e1ea2d78e9412 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jul 2023 18:06:08 +0200 Subject: [PATCH 0992/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.44.0 (#1295) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 858e36e5ecf9..937b824ff8b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.43.2 + 6.44.0 pom import From 6551dd83a182e97f74d6e086720c9dde740b4a89 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 0993/1979] 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)) ([3613970](https://togithub.com/googleapis/java-spanner-jdbc/commit/3613970976373f481cf743b4474fecc4610790c0)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.44.0 ([#1295](https://togithub.com/googleapis/java-spanner-jdbc/issues/1295)) ([9195c2c](https://togithub.com/googleapis/java-spanner-jdbc/commit/9195c2ce9dd0fa42fcde4039b53e1ea2d78e9412)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index afaa6625d23a..92adec688520 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 937b824ff8b5..05d18280533d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a107a1997e3d..770fdcf51348 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 66cc4b7e4986..62f87e024922 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 5d90ab776866cc8ad32e484b6259050729c86372 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 0994/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 05d18280533d..aaf948e0ac93 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 770fdcf51348..85c28b901229 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 62f87e024922..25e212cc748b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 02c65bde1c2d83114f6a643ec8942c7d6e77a7f0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jul 2023 07:04:38 +0200 Subject: [PATCH 0995/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.20.0 (#1299) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 69f126379ff6..2c5ee2778eab 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.19.0 + 26.20.0 pom import From 1aa743b43b0861523987ac340864cbbac67c081e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jul 2023 07:04:56 +0200 Subject: [PATCH 0996/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.5 (#1298) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 756be62c1607..df67728247d9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.4 + 2.11.5 From 4ad35dfa69f1929dbbb5ecf2c1f8d689f282dc9b 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 0997/1979] 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> --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/requirements.txt | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index d5500ef44246..fa335912bd92 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 32989051e7f9..a73256ab80be 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.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 4cafd707ee89164b919cd0ce56614d071bb0176a 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 0998/1979] chore: update owner to olavloite (#1301) --- java-spanner-jdbc/.github/blunderbuss.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/blunderbuss.yml b/java-spanner-jdbc/.github/blunderbuss.yml index 5e0aa64f7251..73448c1b0e78 100644 --- a/java-spanner-jdbc/.github/blunderbuss.yml +++ b/java-spanner-jdbc/.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 51fd74a6dcac3f4c27b642da1abf25b9c36d6c72 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 5 Aug 2023 13:38:04 +0200 Subject: [PATCH 0999/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.21.0 (#1302) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2c5ee2778eab..7590dbb986c0 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.20.0 + 26.21.0 pom import From 34822f10c01bfe1f4901f7557a361016cfa48d09 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 5 Aug 2023 15:06:14 +0200 Subject: [PATCH 1000/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index aaf948e0ac93..3add37db36f9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.13.1 + 3.14.0 pom import From 4bf1ea30a4b5bb4ef4f7e58916614148a77a7e46 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 5 Aug 2023 18:23:09 +0200 Subject: [PATCH 1001/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.0 (#1305) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3add37db36f9..bd6012d74def 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.44.0 + 6.45.0 pom import From b227f76783367fe6ba57d6173ecc64de2c5f9963 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 1002/1979] 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)) ([34822f1](https://togithub.com/googleapis/java-spanner-jdbc/commit/34822f10c01bfe1f4901f7557a361016cfa48d09)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.0 ([#1305](https://togithub.com/googleapis/java-spanner-jdbc/issues/1305)) ([4bf1ea3](https://togithub.com/googleapis/java-spanner-jdbc/commit/4bf1ea30a4b5bb4ef4f7e58916614148a77a7e46)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 92adec688520..e888c604baba 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bd6012d74def..832c8ff43eff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 85c28b901229..81d144448f9b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 25e212cc748b..7cc99e1142ee 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 01e03679e6516e7a4ef27c993ce21dc79609e8e3 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 1003/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 832c8ff43eff..27f45c539dae 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 81d144448f9b..05252d3e4df8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7cc99e1142ee..5f18f19fdb0e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 9f26065c38df4d40b1f96cd74a5ece971829c928 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 6 Aug 2023 07:14:27 +0200 Subject: [PATCH 1004/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.6 (#1308) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index df67728247d9..e5c2fd93b5cb 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.5 + 2.11.6 From 1085352044a52539862bc94aa35e4c28eca748f8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Aug 2023 09:24:09 +0200 Subject: [PATCH 1005/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.22.0 (#1309) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7590dbb986c0..b0a7026a709a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.21.0 + 26.22.0 pom import From 1618ea52838097bb90c314bbcc2c57d26db16619 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 13 Aug 2023 14:18:12 +0200 Subject: [PATCH 1006/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 27f45c539dae..a05a7daffe21 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.45.0 + 6.45.1 pom import From 445e56bbcb85d3da0c44fa426597c71488ac77be 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 1007/1979] 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)) ([1618ea5](https://togithub.com/googleapis/java-spanner-jdbc/commit/1618ea52838097bb90c314bbcc2c57d26db16619)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e888c604baba..af3d292a3b33 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a05a7daffe21..4847ce9d52a2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 05252d3e4df8..74c89c6c2064 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5f18f19fdb0e..874269315a85 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 a61b0d3acf42d9438954d5098c86a09029e3b414 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 1008/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4847ce9d52a2..3378a232fe03 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 74c89c6c2064..99c50943dd13 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 874269315a85..5459f1d3b23c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 b2ee3e784d1e2c73e8bf736aae814031cb42f380 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 13 Aug 2023 18:32:12 +0200 Subject: [PATCH 1009/1979] 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)) ([1618ea5](https://togithub.com/googleapis/java-spanner-jdbc/commit/1618ea52838097bb90c314bbcc2c57d26db16619))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e5c2fd93b5cb..19226361974e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.6 + 2.11.7 From 3aac29e1c1272530e2903494410fe0b512d7b717 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 1010/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 051ed9d6d22f..3e7c86f9f63c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index c7b6a6cbde12..d445835872ab 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/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 95b57abe3bb1792a66b6b1743acae59df0e75079 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 15 Aug 2023 07:08:48 +0200 Subject: [PATCH 1011/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.2 (#1318) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3378a232fe03..9cc747b20482 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.45.1 + 6.45.2 pom import From f0f2c6de6490785dd8befb5511d72ac2cc916a2e 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 1012/1979] 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)) ([95b57ab](https://togithub.com/googleapis/java-spanner-jdbc/commit/95b57abe3bb1792a66b6b1743acae59df0e75079)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index af3d292a3b33..a1f93aa82053 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9cc747b20482..7e85f5a4531b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 99c50943dd13..73e594f2735c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5459f1d3b23c..e9d28b678b33 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 8be5b83f2d68dcaca89869447fd7ebd7b5393700 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 1013/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e85f5a4531b..c46a8404bef9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 73e594f2735c..4abc54e5244e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e9d28b678b33..f29b5a46c924 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 2834f2f380d8b3a5fefda6bc85daf3ff53edb15c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 15 Aug 2023 13:00:23 +0200 Subject: [PATCH 1014/1979] 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)) ([95b57ab](https://togithub.com/googleapis/java-spanner-jdbc/commit/95b57abe3bb1792a66b6b1743acae59df0e75079))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 19226361974e..9b535bcfd887 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.7 + 2.11.8 From 01397fc2d75058d6264af9fa646ad22530c4b1f5 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Fri, 18 Aug 2023 15:06:52 -0400 Subject: [PATCH 1015/1979] ci: javadoc as a required check (#1326) --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 4879f02a5d4f..a259dc084052 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.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 57457bb899b6696b91ba4d361c091ed73d277e16 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 21 Aug 2023 07:50:29 +0200 Subject: [PATCH 1016/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.45.3 (#1325) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c46a8404bef9..42bdae59c03a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.45.2 + 6.45.3 pom import From 8f56705e94b3ec6cd4cb8358ade97ecf0c6f8d94 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 1017/1979] 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)) ([57457bb](https://togithub.com/googleapis/java-spanner-jdbc/commit/57457bb899b6696b91ba4d361c091ed73d277e16)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a1f93aa82053..39927096cfee 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 42bdae59c03a..84b23656c113 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4abc54e5244e..47da31b3e5d4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f29b5a46c924..9b5dabc438a7 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 882a56a5687c6aa5582253f1c5fbd2d2d254dc4a 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 1018/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 84b23656c113..4a33dea8017b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 47da31b3e5d4..5cc1db04597d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9b5dabc438a7..4a69a3a0a48f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 26b7854b5669d5ffd945ce9fd12c1068d7be843c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 24 Aug 2023 14:42:19 +0200 Subject: [PATCH 1019/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.11.9 (#1329) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9b535bcfd887..be63235012fd 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.8 + 2.11.9 From 518609326be26f452327e0fd40c1edaa251e2978 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 1020/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index f8ab452640d5..94b460420b78 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 024f6c24369b..476c40492d80 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/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 ad15e89b5385f13e88afe94856cecf6d3210295b 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 1021/1979] 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 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 3e7c86f9f63c..3385ef01202d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java new file mode 100644 index 000000000000..f74de663195a --- /dev/null +++ b/java-spanner-jdbc/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 0c34532341b0109580aeca11721253dd4590dcf9 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 1022/1979] 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 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 2ee68afb2f42..e7b1a47f4bff 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index a710ac80bae7..6d6bd80d07e5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index a1b327b23de5..3ab302ce953e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 3385ef01202d..6c6a45a15540 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 8010c2151901..592d404090c8 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 8f21e68d3819..310d1546e90f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index d445835872ab..727e63acf54d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java new file mode 100644 index 000000000000..b88428bdfb1e --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java new file mode 100644 index 000000000000..9cd9068dcd00 --- /dev/null +++ b/java-spanner-jdbc/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 6a5d10f7688a4ee73e8babc6c0f69add9fe4e090 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 1023/1979] chore(main): release 2.12.0 (#1330) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 39927096cfee..1d60dd9de023 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4a33dea8017b..6f1e9cfbc4dc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5cc1db04597d..33389f8dacd1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4a69a3a0a48f..1b9bfe9029c6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 d6b11b135a0ac46ca2a5cc65335988ff00205bee 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 1024/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/renovate.json | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index fa335912bd92..52eaa54d82b2 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 6525dc2a570f..efe64307fcf3 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -10,7 +10,10 @@ ":maintainLockFilesDisabled", ":autodetectPinVersions" ], - "ignorePaths": [".kokoro/requirements.txt"], + "ignorePaths": [ + ".kokoro/requirements.txt", + ".github/workflows/**" + ], "packageRules": [ { "packagePatterns": [ From 0c95f4a68bbfd427214ab5f05e581947fa3167d9 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 1025/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6f1e9cfbc4dc..1ea8a9c6510f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 33389f8dacd1..875835773bda 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1b9bfe9029c6..5d40b59a7266 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 7fe97f60b5d79b6c3dacaacf4d97250260a51b52 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 1026/1979] 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 --- java-spanner-jdbc/samples/snippets/pom.xml | 17 ++--------------- java-spanner-jdbc/synth.metadata | 3 +-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index b0a7026a709a..00126842753a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata index f335115e602b..f877cda09f5f 100644 --- a/java-spanner-jdbc/synth.metadata +++ b/java-spanner-jdbc/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 a508a6b4d87f833968f457db829fde3474885d05 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 6 Sep 2023 14:48:13 +0200 Subject: [PATCH 1027/1979] 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)) ([0c34532](https://togithub.com/googleapis/java-spanner-jdbc/commit/0c34532341b0109580aeca11721253dd4590dcf9)) ##### Bug Fixes - Session leak for invalid update ([#​1323](https://togithub.com/googleapis/java-spanner-jdbc/issues/1323)) ([ad15e89](https://togithub.com/googleapis/java-spanner-jdbc/commit/ad15e89b5385f13e88afe94856cecf6d3210295b))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index be63235012fd..ac3ea89e2945 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.11.9 + 2.12.0 From 0d907438f8b0a0c273c2d50b6ef57d517a3f985d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 9 Sep 2023 08:26:59 +0200 Subject: [PATCH 1028/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.46.0 (#1338) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1ea8a9c6510f..571f071ed9c6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.45.3 + 6.46.0 pom import From 40b63b48acea8360f8a8639ae0cda3bd76a873f8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Sep 2023 19:26:15 +0200 Subject: [PATCH 1029/1979] 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). --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 571f071ed9c6..31789c490903 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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 57394dec8354eb23cb9d63326f5744a9590f295f 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 1030/1979] 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)) ([0d90743](https://togithub.com/googleapis/java-spanner-jdbc/commit/0d907438f8b0a0c273c2d50b6ef57d517a3f985d)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.47.0 ([#1341](https://togithub.com/googleapis/java-spanner-jdbc/issues/1341)) ([40b63b4](https://togithub.com/googleapis/java-spanner-jdbc/commit/40b63b48acea8360f8a8639ae0cda3bd76a873f8)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1d60dd9de023..beda76d7feff 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 31789c490903..6a62e0eaf3ba 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 875835773bda..e7a72cae91fd 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5d40b59a7266..81abcbb2d34b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 e9d5602a1e927c26cd2aaee79b57cc0b4bb54d45 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 1031/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6a62e0eaf3ba..5d2bd1a2274a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e7a72cae91fd..f0f41910a9b9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 81abcbb2d34b..2da2362492fe 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 429fcb2d525253e8b676145ec7db63f4b781c335 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 13 Sep 2023 10:04:06 +0200 Subject: [PATCH 1032/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.12.1 (#1343) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ac3ea89e2945..0e0e2d7ae060 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.12.0 + 2.12.1 From 3335d835940596d271fa538261462ea54916f73c 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 1033/1979] 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 java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/README.md create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/pom.xml create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-cs.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-pg.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/create_schema.sql create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/drop_schema.sql create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-cs.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-pg.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application.properties diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml new file mode 100644 index 000000000000..028a486318ce --- /dev/null +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/samples/spring-data-jdbc/README.md b/java-spanner-jdbc/samples/spring-data-jdbc/README.md new file mode 100644 index 000000000000..da1d69532e84 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml new file mode 100644 index 000000000000..a2f7c377f6df --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java new file mode 100644 index 000000000000..bc55afd554f6 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java new file mode 100644 index 000000000000..eabd04c3b1ba --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java new file mode 100644 index 000000000000..2066647b513b --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java new file mode 100644 index 000000000000..4c6d3f2319a8 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java new file mode 100644 index 000000000000..dfde31af2a35 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java new file mode 100644 index 000000000000..29f2b6d906ef --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java new file mode 100644 index 000000000000..255459a890a8 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java new file mode 100644 index 000000000000..268b6e2b51fa --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java new file mode 100644 index 000000000000..e7855cd01a36 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java new file mode 100644 index 000000000000..de90bf7985dc --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java new file mode 100644 index 000000000000..fb2ce9c5931a --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java new file mode 100644 index 000000000000..a55d02f054be --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java new file mode 100644 index 000000000000..597df5f7cc04 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java new file mode 100644 index 000000000000..f029979adbc9 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000000..afb496e352b7 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-cs.properties new file mode 100644 index 000000000000..96aaae7ff0f9 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-pg.properties new file mode 100644 index 000000000000..894f63ebae0d --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application.properties new file mode 100644 index 000000000000..3347f313779a --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/create_schema.sql new file mode 100644 index 000000000000..60552d3ad107 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/drop_schema.sql new file mode 100644 index 000000000000..23e7b65d3bb1 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java new file mode 100644 index 000000000000..726b32cb3106 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-cs.properties new file mode 100644 index 000000000000..05f7cfa92186 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-pg.properties new file mode 100644 index 000000000000..894f63ebae0d --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application.properties new file mode 100644 index 000000000000..3347f313779a --- /dev/null +++ b/java-spanner-jdbc/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 412e86a6612bd7fd5d27d9edeae4f897408633a3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 14 Sep 2023 15:36:08 +0200 Subject: [PATCH 1034/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.12.1 (#1344) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a2f7c377f6df..d0862d2e49fa 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 8fba81cb702f3a1c318dbc6973c9f420c1ccdaa9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 11:00:44 +0200 Subject: [PATCH 1035/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.23.0 (#1346) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 00126842753a..a00b7a56777d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d0862d2e49fa..ee5a443904b4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 import pom From 76c1a6ba5fc8a52856e1b863ea01797afd74acc4 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 1036/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index e7b1a47f4bff..99bee40fb628 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 6c6a45a15540..fcc09596c588 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index f74de663195a..b62449eb57c1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/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 504c0b3b1ffd5954a1e43d36da92161dd5b78ea6 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 1037/1979] 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 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index a92ad53057b1..acf11c5870e2 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 99bee40fb628..97131724d9eb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index cf368f618aa7..c161ee50a7db 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPartitionedQueryResultSet.java new file mode 100644 index 000000000000..3b6118fba906 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcPreparedStatement.java new file mode 100644 index 000000000000..8e72d9556b0c --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcStatement.java new file mode 100644 index 000000000000..6115c0b23812 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 6d6bd80d07e5..6031afe9336d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPartitionedQueryResultSet.java new file mode 100644 index 000000000000..1d5ef66fd0eb --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 3ab302ce953e..c2e0c1db0b19 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 94b460420b78..4152fa58b8c5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index fcc09596c588..60cc3e5cf6df 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java new file mode 100644 index 000000000000..d6edf9993c6b --- /dev/null +++ b/java-spanner-jdbc/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 1f80c572fe2272653c4039a465dbd5a36723fe34 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 1038/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index c2e0c1db0b19..518807dd11fa 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index b62449eb57c1..65a54a89a5a6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/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 852efd1645673889630449d85ce8c4d0eac2c2ad Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 15:25:44 +0200 Subject: [PATCH 1039/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.0.4 (#1347) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ee5a443904b4..ba78496a4323 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 1ff73e956df709cba1848e3487d36cc7121c3a0f 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 1040/1979] 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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index d6edf9993c6b..7e4e74953d48 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/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 2a5faa72cd2e8538bcb6affc3c39d243a8a42ae3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Sep 2023 17:20:27 +0200 Subject: [PATCH 1041/1979] 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/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index 8ee7c4d5d6b8..f299be4f9cb5 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.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 79ed93647025710abbd3edaea74bc6613a17b21a 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 1042/1979] 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)) ([504c0b3](https://togithub.com/googleapis/java-spanner-jdbc/commit/504c0b3b1ffd5954a1e43d36da92161dd5b78ea6)) ### Bug Fixes * Comments should be sent to Spanner for PostgreSQL databases ([#1331](https://togithub.com/googleapis/java-spanner-jdbc/issues/1331)) ([1f80c57](https://togithub.com/googleapis/java-spanner-jdbc/commit/1f80c572fe2272653c4039a465dbd5a36723fe34)) ### Documentation * Create Spring Data JDBC sample ([#1334](https://togithub.com/googleapis/java-spanner-jdbc/issues/1334)) ([3335d83](https://togithub.com/googleapis/java-spanner-jdbc/commit/3335d835940596d271fa538261462ea54916f73c)) ### Dependencies * Update actions/checkout action to v4 - abandoned ([#1333](https://togithub.com/googleapis/java-spanner-jdbc/issues/1333)) ([2a5faa7](https://togithub.com/googleapis/java-spanner-jdbc/commit/2a5faa72cd2e8538bcb6affc3c39d243a8a42ae3)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1347](https://togithub.com/googleapis/java-spanner-jdbc/issues/1347)) ([852efd1](https://togithub.com/googleapis/java-spanner-jdbc/commit/852efd1645673889630449d85ce8c4d0eac2c2ad)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 23 ++++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index beda76d7feff..af67a88f52c7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5d2bd1a2274a..3535b11a16c3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f0f41910a9b9..a8db364bbe5d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2da2362492fe..192f98ebc700 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 4a786e65984ac0d7c34976cac3906d2201099862 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 1043/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3535b11a16c3..92be04a5a837 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a8db364bbe5d..69d2a1b7bc8b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 192f98ebc700..3ea029151a89 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 5a7ba622f5a4e2e1404990d22be36c539cc13758 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Sep 2023 13:58:25 +0200 Subject: [PATCH 1044/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.0 (#1351) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0e0e2d7ae060..2cf650a89d51 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ba78496a4323..6816cff369be 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 372ed29733e6034a34655fcff756760e3f367dc5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Sep 2023 13:58:43 +0200 Subject: [PATCH 1045/1979] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.6.0 (#1349) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 92be04a5a837..cbdc4b5e53c8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -420,7 +420,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 html From dfce1b4fad11a564b636e6bbf17269431ea61ec3 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 1046/1979] 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 53046b83509972e46b0e56b3d9509862bb28bae4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 21 Sep 2023 20:21:09 +0200 Subject: [PATCH 1047/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.4 (#1353) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 6816cff369be..d9bf6c92ae9b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 c8dbf801995f5b3486d5d5c623107295e03b3267 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 1048/1979] 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)) ([53046b8](https://togithub.com/googleapis/java-spanner-jdbc/commit/53046b83509972e46b0e56b3d9509862bb28bae4)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index af67a88f52c7..2b73e9670ff5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cbdc4b5e53c8..aa9177211707 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 69d2a1b7bc8b..d07587fdb265 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3ea029151a89..e9091c973a7a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 503752acbcea699b7a880a48e8e39050d6874b1e 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 1049/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index aa9177211707..f16371b5d1a1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d07587fdb265..c60583de4a8f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e9091c973a7a..993752b80c77 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 c9b649ba3554caf687032cc8360d72430cfce4ef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 07:38:06 +0200 Subject: [PATCH 1050/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.0 (#1358) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f16371b5d1a1..9e42da0ecb7f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.15.0 + 3.16.0 pom import From d7baf55827c1264769893a322e7238c2eccdc65e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 07:38:39 +0200 Subject: [PATCH 1051/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 (#1359) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d9bf6c92ae9b..576c13c23034 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -88,7 +88,7 @@ com.spotify.fmt fmt-maven-plugin - 2.20 + 2.21.1 From 1ea824c00f14288b9ab992f57c3940c745bb15af Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 23 Sep 2023 09:02:13 +0200 Subject: [PATCH 1052/1979] 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)) ([53046b8](https://togithub.com/googleapis/java-spanner-jdbc/commit/53046b83509972e46b0e56b3d9509862bb28bae4))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 2cf650a89d51..ed2d67e7992b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 576c13c23034..557270816b10 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 c15cf3f389795575e5258c2194ecf240df6aeac4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 25 Sep 2023 07:03:36 +0200 Subject: [PATCH 1053/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.1 (#1362) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9e42da0ecb7f..b69c474d7335 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -256,7 +256,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 From d4e72e08cf6e47d16e4c22e88945d48310ff82a9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 08:47:49 +0200 Subject: [PATCH 1054/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 (#1363) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b69c474d7335..0424a311b40a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.16.0 + 3.16.1 pom import From 88a76ea0caee01e13e61fd35562ee6031ec22c17 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 1055/1979] 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)) ([c9b649b](https://togithub.com/googleapis/java-spanner-jdbc/commit/c9b649ba3554caf687032cc8360d72430cfce4ef)) * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 ([#1363](https://togithub.com/googleapis/java-spanner-jdbc/issues/1363)) ([d4e72e0](https://togithub.com/googleapis/java-spanner-jdbc/commit/d4e72e08cf6e47d16e4c22e88945d48310ff82a9)) * Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1359](https://togithub.com/googleapis/java-spanner-jdbc/issues/1359)) ([d7baf55](https://togithub.com/googleapis/java-spanner-jdbc/commit/d7baf55827c1264769893a322e7238c2eccdc65e)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 9 +++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 2b73e9670ff5..659f4d353b14 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0424a311b40a..8ea55af4bea3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c60583de4a8f..038e5e0d3a74 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 993752b80c77..fc35a6a01d52 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 a799596bc9a78b14e17e8d100eed28832d836a06 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 1056/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8ea55af4bea3..ee49db7d9f4f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 038e5e0d3a74..ec9a8dd956fb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fc35a6a01d52..094a46df1752 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 9797203a3708951ed394fa9b6979578db2fc01a2 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 1057/1979] 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 java-spanner-jdbc/samples/spring-data-mybatis/README.md create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/pom.xml create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-pg.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/create_schema.sql create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/drop_schema.sql create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/README.md b/java-spanner-jdbc/samples/spring-data-mybatis/README.md new file mode 100644 index 000000000000..02cf135d49bc --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml new file mode 100644 index 000000000000..2d9de56fb5db --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java new file mode 100644 index 000000000000..04286b5a9757 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java new file mode 100644 index 000000000000..eabd04c3b1ba --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java new file mode 100644 index 000000000000..2398add31a43 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java new file mode 100644 index 000000000000..2dbffd0e76b5 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java new file mode 100644 index 000000000000..57df330bfca2 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java new file mode 100644 index 000000000000..fa219b16dfe8 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java new file mode 100644 index 000000000000..90dc0e1e0f53 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java new file mode 100644 index 000000000000..51fb756c90fc --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java new file mode 100644 index 000000000000..ff7ee5049a5d --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java new file mode 100644 index 000000000000..85a05f28e652 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java new file mode 100644 index 000000000000..d268b4327fcd --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java new file mode 100644 index 000000000000..7f55466fe8e8 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java new file mode 100644 index 000000000000..5972e27116fc --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java new file mode 100644 index 000000000000..ab81c45cd54c --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java new file mode 100644 index 000000000000..4e326a47cc9a --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000000..6298bb63ebd2 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties new file mode 100644 index 000000000000..cf70836d219b --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-pg.properties new file mode 100644 index 000000000000..0605cd3ab438 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application.properties new file mode 100644 index 000000000000..a6900a8ef0c6 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/create_schema.sql new file mode 100644 index 000000000000..60552d3ad107 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/drop_schema.sql new file mode 100644 index 000000000000..23e7b65d3bb1 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java new file mode 100644 index 000000000000..677e086ecdb5 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties new file mode 100644 index 000000000000..05f7cfa92186 --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties new file mode 100644 index 000000000000..894f63ebae0d --- /dev/null +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties new file mode 100644 index 000000000000..a6900a8ef0c6 --- /dev/null +++ b/java-spanner-jdbc/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 3d14db0d359d7a5d43b328ecaf8639619032da8e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:06:13 +0200 Subject: [PATCH 1058/1979] 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). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 2d9de56fb5db..e522b1756be8 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.3 + 3.1.4 From 7e76957bce16ba5ce7945f796c7f9ddb7e59891f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:08:14 +0200 Subject: [PATCH 1059/1979] 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)) ([c9b649b](https://togithub.com/googleapis/java-spanner-jdbc/commit/c9b649ba3554caf687032cc8360d72430cfce4ef)) - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.16.1 ([#​1363](https://togithub.com/googleapis/java-spanner-jdbc/issues/1363)) ([d4e72e0](https://togithub.com/googleapis/java-spanner-jdbc/commit/d4e72e08cf6e47d16e4c22e88945d48310ff82a9)) - Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#​1359](https://togithub.com/googleapis/java-spanner-jdbc/issues/1359)) ([d7baf55](https://togithub.com/googleapis/java-spanner-jdbc/commit/d7baf55827c1264769893a322e7238c2eccdc65e)) ### [`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)) ([53046b8](https://togithub.com/googleapis/java-spanner-jdbc/commit/53046b83509972e46b0e56b3d9509862bb28bae4)) ### [`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)) ([504c0b3](https://togithub.com/googleapis/java-spanner-jdbc/commit/504c0b3b1ffd5954a1e43d36da92161dd5b78ea6)) ##### Bug Fixes - Comments should be sent to Spanner for PostgreSQL databases ([#​1331](https://togithub.com/googleapis/java-spanner-jdbc/issues/1331)) ([1f80c57](https://togithub.com/googleapis/java-spanner-jdbc/commit/1f80c572fe2272653c4039a465dbd5a36723fe34)) ##### Documentation - Create Spring Data JDBC sample ([#​1334](https://togithub.com/googleapis/java-spanner-jdbc/issues/1334)) ([3335d83](https://togithub.com/googleapis/java-spanner-jdbc/commit/3335d835940596d271fa538261462ea54916f73c)) ##### Dependencies - Update actions/checkout action to v4 - abandoned ([#​1333](https://togithub.com/googleapis/java-spanner-jdbc/issues/1333)) ([2a5faa7](https://togithub.com/googleapis/java-spanner-jdbc/commit/2a5faa72cd2e8538bcb6affc3c39d243a8a42ae3)) - Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#​1347](https://togithub.com/googleapis/java-spanner-jdbc/issues/1347)) ([852efd1](https://togithub.com/googleapis/java-spanner-jdbc/commit/852efd1645673889630449d85ce8c4d0eac2c2ad))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ed2d67e7992b..015e8b35dd1e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 557270816b10..44d3da890443 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index e522b1756be8..d97a09d24887 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/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 a46db0f7651b9faab12e726893b60c9392130218 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 16:12:13 +0200 Subject: [PATCH 1060/1979] 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). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index d97a09d24887..68026c1a2b4e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/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 22abe3694442c18555f4f9ee9073faef89ce554d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:02:06 +0200 Subject: [PATCH 1061/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.23.0 (#1369) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 68026c1a2b4e..a350dc1dd011 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.22.0 + 26.23.0 import pom From e1eee4be6270f55ba7090315b632984e2d226538 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:02:29 +0200 Subject: [PATCH 1062/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.48.0 (#1370) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ee49db7d9f4f..ba88638576da 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.47.0 + 6.48.0 pom import From 39c30d3d54e0f279ebfe02de54bd65ddb62c675f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Sep 2023 17:28:16 +0200 Subject: [PATCH 1063/1979] 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). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index a350dc1dd011..615d6ca27a43 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -98,7 +98,7 @@ com.spotify.fmt fmt-maven-plugin - 2.20 + 2.21.1 From e9af250101410fbdd43a10ce0857e1ff12a6aa6d 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 1064/1979] 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 java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml new file mode 100644 index 000000000000..39be0e6e6a47 --- /dev/null +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 44d3da890443..20f858d95237 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 615d6ca27a43..07563c648ca3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -58,7 +58,6 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2 org.postgresql From 6f94217f05f7bac57a9ae0a11cb9fd7cb2d50f0e 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 1065/1979] 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)) ([e9af250](https://togithub.com/googleapis/java-spanner-jdbc/commit/e9af250101410fbdd43a10ce0857e1ff12a6aa6d)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.48.0 ([#1370](https://togithub.com/googleapis/java-spanner-jdbc/issues/1370)) ([e1eee4b](https://togithub.com/googleapis/java-spanner-jdbc/commit/e1eee4be6270f55ba7090315b632984e2d226538)) * Update dependency com.spotify.fmt:fmt-maven-plugin to v2.21.1 ([#1372](https://togithub.com/googleapis/java-spanner-jdbc/issues/1372)) ([39c30d3](https://togithub.com/googleapis/java-spanner-jdbc/commit/39c30d3d54e0f279ebfe02de54bd65ddb62c675f)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.4 ([#1366](https://togithub.com/googleapis/java-spanner-jdbc/issues/1366)) ([3d14db0](https://togithub.com/googleapis/java-spanner-jdbc/commit/3d14db0d359d7a5d43b328ecaf8639619032da8e)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.4 ([#1367](https://togithub.com/googleapis/java-spanner-jdbc/issues/1367)) ([a46db0f](https://togithub.com/googleapis/java-spanner-jdbc/commit/a46db0f7651b9faab12e726893b60c9392130218)) ### Documentation * Add sample for Spring Data MyBatis ([#1352](https://togithub.com/googleapis/java-spanner-jdbc/issues/1352)) ([9797203](https://togithub.com/googleapis/java-spanner-jdbc/commit/9797203a3708951ed394fa9b6979578db2fc01a2)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 659f4d353b14..a6db5acc0294 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ba88638576da..ab808ec9208b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ec9a8dd956fb..83ae791af765 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 094a46df1752..60ce25154aab 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 bfc1455100b66aac4feceed15cf854764acfad1b 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 1066/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ab808ec9208b..14bae4c9fb12 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 83ae791af765..8da9c02e49be 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 60ce25154aab..2b54a519728f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 741bbc268874ceb2526ae0927d51a8aff1029600 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 1067/1979] 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 77de3b2accf5bc40bd5b480f3e7abc9e936d4a88 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 28 Sep 2023 22:04:25 +0200 Subject: [PATCH 1068/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.49.0 (#1376) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14bae4c9fb12..ff8b7cbcf1ed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.48.0 + 6.49.0 pom import From 4a8173da19a9ed3d6b5afd5a8dde7936ec1c0e9a 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 1069/1979] 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)) ([77de3b2](https://togithub.com/googleapis/java-spanner-jdbc/commit/77de3b2accf5bc40bd5b480f3e7abc9e936d4a88)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a6db5acc0294..65d0eaf138f4 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ff8b7cbcf1ed..bf6670714a4b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8da9c02e49be..e83d7a010da2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2b54a519728f..f042756d0af4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 150d43cdf822eb50ec36105121a4ab1a9db6a9d1 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 1070/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bf6670714a4b..ee537da530b8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e83d7a010da2..4c60212c8ff0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f042756d0af4..d8e1b2e195ff 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 4cbd6298ec68b3885e698166389fc6bd2e6b1fbf 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 1071/1979] build: do not declare javadoc plugin version (#1385) --- java-spanner-jdbc/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ee537da530b8..66f8a9aa40ad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -420,7 +420,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.0 html From 8b9694ad2947a49a693c4d1b22d9e9ef63cc064b 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 1072/1979] 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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 6031afe9336d..9248dace41f8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index b9c7cb8639dc..446339587fd4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 592d404090c8..ff811f370109 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 6a2b0cac0605..9782e964a4cb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 7e2481a239a5..820bdfac91c0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/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/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index ff0bff7a98e1..56d75db1a92d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/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 52353a2cd718180da4ddc77d1abc2c6d7aaba073 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:27:23 +0200 Subject: [PATCH 1073/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.13.4 (#1374) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 015e8b35dd1e..1bc1db91e723 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.2 + 2.13.4 From 66fe92864dbd238bcd933b69b26a666d5fd7e5fb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:27:53 +0200 Subject: [PATCH 1074/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.24.0 (#1379) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a00b7a56777d..31441498d738 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.23.0 + 26.24.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 20f858d95237..5ed1d02df348 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 07563c648ca3..8dbf025208f5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.23.0 + 26.24.0 import pom From beba463ed43cf6fb88846d117d0a0ecbb42965a1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 14:28:34 +0200 Subject: [PATCH 1075/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.5.8 (#1382) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 66f8a9aa40ad..07e029eeda6e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.7 + 1.5.8 From b7b4722b743a4e669c604cc5554437d51b59b772 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 1076/1979] 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> --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/requirements.txt | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 52eaa54d82b2..11fe20466f23 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index a73256ab80be..59de49234092 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.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 ac416f7c453f127db5b0c1ccabe7cde93737766f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 15:54:13 +0200 Subject: [PATCH 1077/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 07e029eeda6e..5f8907216a59 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.49.0 + 6.50.0 pom import From 6f110592acd6d7a9e49403ecda0c9debb1a36fd3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Oct 2023 15:56:13 +0200 Subject: [PATCH 1078/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5f8907216a59..3a2a8240bd05 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.16.1 + 3.17.0 pom import From 8a04bab3d6ec9ac4156d0a9ce3ada87dd0f559b4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Oct 2023 09:55:27 +0200 Subject: [PATCH 1079/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 (#1388) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3a2a8240bd05..82fa683e9f85 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.50.0 + 6.50.1 pom import From 1bc5daaa81b80e1312904b3ff40425c5b96a5aa3 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 1080/1979] 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)) ([8b9694a](https://togithub.com/googleapis/java-spanner-jdbc/commit/8b9694ad2947a49a693c4d1b22d9e9ef63cc064b)) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 ([#1383](https://togithub.com/googleapis/java-spanner-jdbc/issues/1383)) ([6f11059](https://togithub.com/googleapis/java-spanner-jdbc/commit/6f110592acd6d7a9e49403ecda0c9debb1a36fd3)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 ([#1386](https://togithub.com/googleapis/java-spanner-jdbc/issues/1386)) ([ac416f7](https://togithub.com/googleapis/java-spanner-jdbc/commit/ac416f7c453f127db5b0c1ccabe7cde93737766f)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 ([#1388](https://togithub.com/googleapis/java-spanner-jdbc/issues/1388)) ([8a04bab](https://togithub.com/googleapis/java-spanner-jdbc/commit/8a04bab3d6ec9ac4156d0a9ce3ada87dd0f559b4)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 65d0eaf138f4..2259f449d386 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 82fa683e9f85..bff3f8dab8b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4c60212c8ff0..eb6a609deecf 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d8e1b2e195ff..ecc78857029e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 d15da9fdbe827f3e53ec6a1485e4b84864e643b3 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 1081/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bff3f8dab8b5..53221acc91f3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index eb6a609deecf..e64e91e54021 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ecc78857029e..6136c9c9418c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 52882048cfae4d44b25bc3f57fb2e9c049ce112f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Oct 2023 11:56:38 +0200 Subject: [PATCH 1082/1979] 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)) ([8b9694a](https://togithub.com/googleapis/java-spanner-jdbc/commit/8b9694ad2947a49a693c4d1b22d9e9ef63cc064b)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.17.0 ([#​1383](https://togithub.com/googleapis/java-spanner-jdbc/issues/1383)) ([6f11059](https://togithub.com/googleapis/java-spanner-jdbc/commit/6f110592acd6d7a9e49403ecda0c9debb1a36fd3)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.0 ([#​1386](https://togithub.com/googleapis/java-spanner-jdbc/issues/1386)) ([ac416f7](https://togithub.com/googleapis/java-spanner-jdbc/commit/ac416f7c453f127db5b0c1ccabe7cde93737766f)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.50.1 ([#​1388](https://togithub.com/googleapis/java-spanner-jdbc/issues/1388)) ([8a04bab](https://togithub.com/googleapis/java-spanner-jdbc/commit/8a04bab3d6ec9ac4156d0a9ce3ada87dd0f559b4))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1bc1db91e723..086be6b76631 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.13.4 + 2.14.0 From fd8b40629d04d9b9fd587d843f36233005213ef9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:07:31 +0200 Subject: [PATCH 1083/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.51.0 (#1393) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 53221acc91f3..7e2462ca9ee2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.50.1 + 6.51.0 pom import From 7824b39741155fe61cfaf9c13e4a57e90ab04cec Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:07:52 +0200 Subject: [PATCH 1084/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.25.0 (#1392) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 31441498d738..c3a67a6986cb 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.24.0 + 26.25.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5ed1d02df348..28d5e238ec1b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 8dbf025208f5..b00e6b21839e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.24.0 + 26.25.0 import pom From e3a07b9543e5b2ca1ee1f99ab9b3cd0fb68822ad Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Oct 2023 21:08:13 +0200 Subject: [PATCH 1085/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.0.5 (#1391) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 28d5e238ec1b..fc22d388efff 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b00e6b21839e..7afc28b02eed 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/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 ff9bd66fa09de989745de92da12c8577f289da83 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 1086/1979] 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)) ([fd8b406](https://togithub.com/googleapis/java-spanner-jdbc/commit/fd8b40629d04d9b9fd587d843f36233005213ef9)) * Update dependency org.springframework.data:spring-data-bom to v2023.0.5 ([#1391](https://togithub.com/googleapis/java-spanner-jdbc/issues/1391)) ([e3a07b9](https://togithub.com/googleapis/java-spanner-jdbc/commit/e3a07b9543e5b2ca1ee1f99ab9b3cd0fb68822ad)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 2259f449d386..8296568b8dff 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e2462ca9ee2..db7948f5ab3c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e64e91e54021..5339ef48b3df 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6136c9c9418c..02b84e1b4073 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 07c02298906603489ba859a370bf98c3e46d11db 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 1087/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index db7948f5ab3c..e34b75419147 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5339ef48b3df..64656478c96c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 02b84e1b4073..90d9204a5f68 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 9fcb962791f1bbb4cceee227068ad0a660daf295 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Oct 2023 15:58:50 +0200 Subject: [PATCH 1088/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.1 (#1396) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 086be6b76631..b001af5a93a1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.0 + 2.14.1 From 17ba8a154df39970fd54dab590d0d26729121719 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:03:31 +0200 Subject: [PATCH 1089/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.18.0 (#1402) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e34b75419147..30656f94f7c9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.17.0 + 3.18.0 pom import From bd2aa2c1f5fcf1322beaf7679c913b9b1373f44f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:04:16 +0200 Subject: [PATCH 1090/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.1.5 (#1399) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index fc22d388efff..c750693c3c35 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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 9b3676ff72c7a4849fecd41d268a171fa51a9225 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 14:04:37 +0200 Subject: [PATCH 1091/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.1.5 (#1400) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 7afc28b02eed..b908ea79823a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.1.5 From a0d8f46b6687317e7738639d7743ddfe573a87c0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 15:16:14 +0200 Subject: [PATCH 1092/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 30656f94f7c9..3e9336710a34 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.51.0 + 6.52.1 pom import From 7d46174ab38329ffc9701e91a895b06747c08eea Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Oct 2023 17:14:14 +0200 Subject: [PATCH 1093/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3e9336710a34..46480b70381b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.5.8 + 1.6.0 From 6ac0250124c321cacd41931a7d8f0f73a1f66082 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 1094/1979] chore(main): release 2.14.2 (#1404) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8296568b8dff..b179babc3d56 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 46480b70381b..85b3f54c4aae 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 64656478c96c..f910472f8f92 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 90d9204a5f68..8de2b27ed565 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 555de9e05864d48a7c170f88f2d72b2679af1be4 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 1095/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 85b3f54c4aae..dc733197330b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f910472f8f92..920c5a65a9d8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8de2b27ed565..6e526f3fd977 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 db610c83d2a0d58787b5701b824c8ea0bdd4dfa3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Oct 2023 08:48:22 +0200 Subject: [PATCH 1096/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.2 (#1406) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b001af5a93a1..b25a24c49bf2 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.1 + 2.14.2 From 8244faca19753a1dfda548b610bfebb9762e86dc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 28 Oct 2023 12:36:48 +0200 Subject: [PATCH 1097/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.26.0 (#1407) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c3a67a6986cb..d050f886d2f2 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.25.0 + 26.26.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c750693c3c35..3882c0d67df3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b908ea79823a..98e446bd7ada 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.25.0 + 26.26.0 import pom From fd07cc0597c08b19c48c08f63b13aaf9304a1066 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 1098/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg | 1 + java-spanner-jdbc/.kokoro/presubmit/integration.cfg | 1 + java-spanner-jdbc/.kokoro/requirements.txt | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 11fe20466f23..208af343821b 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg b/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg index 58049cc38f11..6a6ef94eff28 100644 --- a/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg +++ b/java-spanner-jdbc/.kokoro/nightly/java11-integration.cfg @@ -35,3 +35,4 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg index dded67a9d54a..5864c603e5ad 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -31,3 +31,4 @@ env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" } + diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index 59de49234092..c5c11bbe7925 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.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 1a8d9bd037310c9d5124a21642044b77c4863c1d 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 1099/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 208af343821b..f930d4846feb 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index f52533545896..fb5bb678ffcc 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 44b1004875b6..59efee340c53 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.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 4108ef16f694a1fb2dea6532f478034b09215d85 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Nov 2023 09:57:42 +0100 Subject: [PATCH 1100/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.6.1 (#1410) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dc733197330b..a7287ec53181 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.6.0 + 1.6.1 From 29e14eaf450185a8c93363a465caaf2140a3e312 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Nov 2023 09:58:01 +0100 Subject: [PATCH 1101/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.19.0 (#1411) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a7287ec53181..fcba765e0abc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.18.0 + 3.19.0 pom import From 8d00568b58c5f6d48c82737d6fc98601f3c0ad74 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 1102/1979] 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)) ([29e14ea](https://togithub.com/googleapis/java-spanner-jdbc/commit/29e14eaf450185a8c93363a465caaf2140a3e312)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b179babc3d56..23d287f96ee9 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fcba765e0abc..49f7bd6179b4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 920c5a65a9d8..59e0af8764a1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6e526f3fd977..90ad0651ced4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 dc10e394da06ecb63d2f4785299cc510539daa2e 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 1103/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 49f7bd6179b4..c21fd6660792 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 59e0af8764a1..c6115f1caa4e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 90ad0651ced4..c07654d0dcc0 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 06218cbae215aaf331ad478e16d7c0b0f1f4b0d4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 5 Nov 2023 15:43:40 +0100 Subject: [PATCH 1104/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.3 (#1414) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b25a24c49bf2..5158d8c9df57 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.2 + 2.14.3 From c34d26e719458748b16263e2ffce1880a22acfe6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Nov 2023 10:09:48 +0100 Subject: [PATCH 1105/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.27.0 (#1416) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d050f886d2f2..8a87cff399e4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.26.0 + 26.27.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 3882c0d67df3..299d4227f5f2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 98e446bd7ada..72fef9dcfd92 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.26.0 + 26.27.0 import pom From b17748990be1c7c28a17bca117454df3b1f84d2a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Nov 2023 10:10:14 +0100 Subject: [PATCH 1106/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.53.0 (#1415) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c21fd6660792..7c4f8a7fdd3a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.52.1 + 6.53.0 pom import From 40991a067d717957ac62fd128f53dfa95c2986a5 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 1107/1979] 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)) ([b177489](https://togithub.com/googleapis/java-spanner-jdbc/commit/b17748990be1c7c28a17bca117454df3b1f84d2a)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 23d287f96ee9..b10c0b0abde5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7c4f8a7fdd3a..cf84cdf1c1f5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index c6115f1caa4e..f60fa36cbab6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c07654d0dcc0..08bc71527525 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 9f8d3c522012f009a16ae865c26f784c4323182a 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 1108/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cf84cdf1c1f5..8b7e513b5130 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f60fa36cbab6..77395be95d0c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 08bc71527525..d79775c9e269 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 46f9c35e6443aa864f29724f8774c5e435fdf7aa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 Nov 2023 20:19:55 +0100 Subject: [PATCH 1109/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.5.0 (#1427) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5158d8c9df57..1952dec56b6a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 77395be95d0c..9d5e19da0922 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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 a01a3f46ae3527a057122d9045f2edf158e2c8e9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 Nov 2023 20:26:14 +0100 Subject: [PATCH 1110/1979] 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)) ([b177489](https://togithub.com/googleapis/java-spanner-jdbc/commit/b17748990be1c7c28a17bca117454df3b1f84d2a))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1952dec56b6a..f74fb2cd7e02 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.3 + 2.14.4 From 7e6fdcf753b0454ee3f948c178daf524166b23c1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:43:53 +0100 Subject: [PATCH 1111/1979] deps: update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.3 (#1426) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 72fef9dcfd92..6fe135cb4111 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/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 010fec169ca94ace739cc8a32e7a619380dfd2b8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:44:16 +0100 Subject: [PATCH 1112/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.5.0 (#1423) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8b7e513b5130..e998ad780913 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -393,7 +393,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.5 + 3.5.0 From f25e1d8d8321a864183bafb880d5b761f222e76a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:45:22 +0100 Subject: [PATCH 1113/1979] deps: update dependency org.postgresql:postgresql to v42.7.0 (#1422) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 299d4227f5f2..d1dd5748b884 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -52,7 +52,7 @@ org.postgresql postgresql - 42.6.0 + 42.7.0 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 6fe135cb4111..4dbd0925b540 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.6.0 + 42.7.0 From fd35dc2dc89f36e3520dd4c83a973af83876c17c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Nov 2023 21:45:44 +0100 Subject: [PATCH 1114/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.54.0 (#1420) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e998ad780913..dceeeb741a04 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.53.0 + 6.54.0 pom import From 73f3a62e4c878c5efc795b1dfdf2e73a662b6660 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 30 Nov 2023 18:23:36 +0100 Subject: [PATCH 1115/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.20.0 (#1430) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dceeeb741a04..db262c30b7e8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.19.0 + 3.20.0 pom import From 0f74fc282604c3799f89644d9c66fdafbe6fe2af 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 1116/1979] chore(main): release 2.14.5 (#1428) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b10c0b0abde5..117cc6e580b4 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index db262c30b7e8..8d0093c285de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9d5e19da0922..3a2bc646b33e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d79775c9e269..8993de1151b3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 610970ee1c2e37ba77a210d13277db205f1ec121 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 1117/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8d0093c285de..b67782f35a07 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3a2bc646b33e..18344f2dcd91 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8993de1151b3..c203137bdfb9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 5c832aab87e69c6c3c2fa6984165e6d759eece35 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Dec 2023 20:42:42 +0100 Subject: [PATCH 1118/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.5 (#1432) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f74fb2cd7e02..80864ee32038 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.4 + 2.14.5 From 3e718e1b084a44d3ce6ff9310811bb6a126431ad 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 1119/1979] 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 --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index f930d4846feb..d304652e1c44 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index e27b2c57563c..ae66b1973b17 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.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 dbd936d514b4f5bdeb8e92f2d7b48f9c58a493d5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 4 Dec 2023 12:31:22 +0100 Subject: [PATCH 1120/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.55.0 (#1434) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b67782f35a07..65860ae8450e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.54.0 + 6.55.0 pom import From 2ce5e3faa2d39650fa3e16c552ed60a538b05e26 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 1121/1979] chore(main): release 2.14.6 (#1435) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 117cc6e580b4..8fdf14867348 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/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/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 65860ae8450e..fdea168b45c4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 18344f2dcd91..3f8deae8dcb0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c203137bdfb9..1b47ecd01afb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 acbaf645410be6cee2a9f2278a70cd7cedbb2373 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 1122/1979] 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fdea168b45c4..90ac8a53daa2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3f8deae8dcb0..ce3483e6ffe6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/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/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1b47ecd01afb..6dc9f85edcc9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/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 dbab83a518653a793f6fa707852fac4e2c578836 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 5 Dec 2023 14:16:16 +0100 Subject: [PATCH 1123/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.14.6 (#1437) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 80864ee32038..d71f8cf03cf7 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.5 + 2.14.6 From a1042f8a21ec3ed6ab102cb61b1d07202acf77f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 19 Dec 2023 07:30:49 +0100 Subject: [PATCH 1124/1979] perf: optimize isValid implementation (#1444) Cloud Spanner JDBC connections do not maintain a physical connection to Cloud Spanner, but are merely a wrapper around the underlying Java client library. This again uses a pool of gRPC channels to communicate with Cloud Spanner. This means that a single JDBC connection will never lose its network connection with Cloud Spanner, and checking whether it is valid or not by executing a query every time is not useful. Instead, the check should: 1. Verify that a connection has successfully been established with Cloud Spanner. The result should be cached for all JDBC connections using the same Cloud Spanner client library instance. 2. Verify that the connection has not been closed. The above can be achieved by checking that the dialect of the database that the connection is connected to has been successfully fetched. This result is cached in the client library, and being able to get that means that there has been a valid connection. This means that the isValid method will still return true if the network connectivity has been lost completely between the client and Cloud Spanner. However, this check is mostly used by connection pools to determine whether a connection is safe to be handed out to an application, and when all network connectivity has been lost, this will apply to all JDBC connections and not just one, meaning that the check is void. The original isValid check can be enabled by setting the System property spanner.jdbc.use_legacy_is_valid_check to true or setting the Environment variable SPANNER_JDBC_USE_LEGACY_IS_VALID_CHECK to true. Fixes #1443 --- .../cloud/spanner/jdbc/JdbcConnection.java | 64 ++++++++++++++++--- .../spanner/jdbc/JdbcConnectionTest.java | 4 +- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 9248dace41f8..4cef6b3f1a82 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -29,6 +29,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.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import java.sql.Array; @@ -57,14 +58,42 @@ 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 IS_VALID_QUERY = "SELECT 1"; + + /** + * This query is used to check the aliveness of the connection if legacy alive check has been + * enabled. As Cloud Spanner JDBC connections do not maintain a physical or logical connection to + * Cloud Spanner, there is also no point in repeatedly executing a simple query to check whether a + * connection is alive. Instead, we rely on the result from the initial query to Spanner that + * determines the dialect to determine whether the connection is alive or not. This result is + * cached for all JDBC connections using the same {@link com.google.cloud.spanner.Spanner} + * instance. + * + *

    The legacy {@link #isValid(int)} check using a SELECT 1 statement can be enabled by setting + * the System property spanner.jdbc.use_legacy_is_valid_check to true or setting the environment + * variable SPANNER_JDBC_USE_LEGACY_IS_VALID_CHECK to true. + */ + static final String LEGACY_IS_VALID_QUERY = "SELECT 1"; static final ImmutableList NO_GENERATED_KEY_COLUMNS = ImmutableList.of(); private Map> typeMap = new HashMap<>(); + private final boolean useLegacyIsValidCheck; + JdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException { super(connectionUrl, options); + this.useLegacyIsValidCheck = useLegacyValidCheck(); + } + + static boolean useLegacyValidCheck() { + String value = System.getProperty("spanner.jdbc.use_legacy_is_valid_check"); + if (Strings.isNullOrEmpty(value)) { + value = System.getenv("SPANNER_JDBC_USE_LEGACY_IS_VALID_CHECK"); + } + if (!Strings.isNullOrEmpty(value)) { + return Boolean.parseBoolean(value); + } + return false; } @Override @@ -347,23 +376,38 @@ public void setTypeMap(Map> map) throws SQLException { this.typeMap = new HashMap<>(map); } + boolean isUseLegacyIsValidCheck() { + return useLegacyIsValidCheck; + } + @Override public boolean isValid(int timeout) throws SQLException { JdbcPreconditions.checkArgument(timeout >= 0, "timeout must be >= 0"); if (!isClosed()) { + if (isUseLegacyIsValidCheck()) { + return legacyIsValid(timeout); + } try { - Statement statement = createStatement(); - statement.setQueryTimeout(timeout); - try (ResultSet rs = statement.executeQuery(IS_VALID_QUERY)) { - if (rs.next()) { - if (rs.getLong(1) == 1L) { - return true; - } + return getDialect() != null; + } catch (Exception ignore) { + // ignore and fall through. + } + } + return false; + } + + private boolean legacyIsValid(int timeout) throws SQLException { + try (Statement statement = createStatement()) { + statement.setQueryTimeout(timeout); + try (ResultSet rs = statement.executeQuery(LEGACY_IS_VALID_QUERY)) { + if (rs.next()) { + if (rs.getLong(1) == 1L) { + return true; } } - } catch (SQLException e) { - // ignore } + } catch (SQLException e) { + // ignore and fall through. } return false; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index ff811f370109..8d26bb31736f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -502,7 +502,7 @@ public void testIsValid() throws SQLException { mock(com.google.cloud.spanner.connection.Connection.class); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); - Statement statement = Statement.of(JdbcConnection.IS_VALID_QUERY); + Statement statement = Statement.of(JdbcConnection.LEGACY_IS_VALID_QUERY); // Verify that an opened connection that returns a result set is valid. try (JdbcConnection connection = new JdbcConnection("url", options)) { @@ -517,7 +517,7 @@ public void testIsValid() throws SQLException { } // Now let the query return an error. isValid should now return false. - when(spannerConnection.executeQuery(statement)) + when(spannerConnection.getDialect()) .thenThrow( SpannerExceptionFactory.newSpannerException( ErrorCode.ABORTED, "the current transaction has been aborted")); From 84cf3f1af0b928d831ca4f23bad6596fd909337d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 19 Dec 2023 07:31:15 +0100 Subject: [PATCH 1125/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.7.1 (#1442) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 90ac8a53daa2..1f01bee35e84 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.6.1 + 1.7.1 From d388bdba4b4d4a05cf6162eee133b63f102f868c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 19 Dec 2023 07:33:01 +0100 Subject: [PATCH 1126/1979] deps: update dependency org.postgresql:postgresql to v42.7.1 (#1441) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d1dd5748b884..1a1130735788 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -52,7 +52,7 @@ org.postgresql postgresql - 42.7.0 + 42.7.1 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 4dbd0925b540..03b3918c4e5f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.7.0 + 42.7.1 From e9a22957ad60d6f1f2888b93e47cd87127cd96e6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 19 Dec 2023 07:40:42 +0100 Subject: [PATCH 1127/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.29.0 (#1440) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 8a87cff399e4..df372f26d8cb 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.27.0 + 26.29.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 1a1130735788..cf500a9efdd3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.27.0 + 26.29.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 03b3918c4e5f..28342f9ae7f1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.27.0 + 26.29.0 import pom From c63e2d5714a54593a032ba1480cfba988e049875 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 07:41:10 +0100 Subject: [PATCH 1128/1979] build(deps): bump cryptography from 41.0.3 to 41.0.6 in /synthtool/gcp/templates/java_library/.kokoro (#1908) (#1439) build(deps): bump cryptography Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.3 to 41.0.6. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.3...41.0.6) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Source-Link: https://github.com/googleapis/synthtool/commit/ea6f80056a7d22f4d3a3e8fee2d59cdc746470bd Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:81f75d962cd28b7ad10740a643b8069b8fa0357cb495b782eef8560bb7a8fd65 Signed-off-by: dependabot[bot] Co-authored-by: Owl Bot Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +- java-spanner-jdbc/.kokoro/requirements.txt | 48 ++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index d304652e1c44..f56920557239 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:6f431774e11cc46619cf093fd1481193c4024031073697fa18f0099b943aab88 -# created: 2023-12-01T19:50:20.444857406Z + digest: sha256:81f75d962cd28b7ad10740a643b8069b8fa0357cb495b782eef8560bb7a8fd65 +# created: 2023-12-05T19:16:19.735195992Z diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt index c5c11bbe7925..445c5c1f0929 100644 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ b/java-spanner-jdbc/.kokoro/requirements.txt @@ -170,30 +170,30 @@ colorlog==6.7.0 \ --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 # via gcp-docuploader -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 +cryptography==41.0.6 \ + --hash=sha256:068bc551698c234742c40049e46840843f3d98ad7ce265fd2bd4ec0d11306596 \ + --hash=sha256:0f27acb55a4e77b9be8d550d762b0513ef3fc658cd3eb15110ebbcbd626db12c \ + --hash=sha256:2132d5865eea673fe6712c2ed5fb4fa49dba10768bb4cc798345748380ee3660 \ + --hash=sha256:3288acccef021e3c3c10d58933f44e8602cf04dba96d9796d70d537bb2f4bbc4 \ + --hash=sha256:35f3f288e83c3f6f10752467c48919a7a94b7d88cc00b0668372a0d2ad4f8ead \ + --hash=sha256:398ae1fc711b5eb78e977daa3cbf47cec20f2c08c5da129b7a296055fbb22aed \ + --hash=sha256:422e3e31d63743855e43e5a6fcc8b4acab860f560f9321b0ee6269cc7ed70cc3 \ + --hash=sha256:48783b7e2bef51224020efb61b42704207dde583d7e371ef8fc2a5fb6c0aabc7 \ + --hash=sha256:4d03186af98b1c01a4eda396b137f29e4e3fb0173e30f885e27acec8823c1b09 \ + --hash=sha256:5daeb18e7886a358064a68dbcaf441c036cbdb7da52ae744e7b9207b04d3908c \ + --hash=sha256:60e746b11b937911dc70d164060d28d273e31853bb359e2b2033c9e93e6f3c43 \ + --hash=sha256:742ae5e9a2310e9dade7932f9576606836ed174da3c7d26bc3d3ab4bd49b9f65 \ + --hash=sha256:7e00fb556bda398b99b0da289ce7053639d33b572847181d6483ad89835115f6 \ + --hash=sha256:85abd057699b98fce40b41737afb234fef05c67e116f6f3650782c10862c43da \ + --hash=sha256:8efb2af8d4ba9dbc9c9dd8f04d19a7abb5b49eab1f3694e7b5a16a5fc2856f5c \ + --hash=sha256:ae236bb8760c1e55b7a39b6d4d32d2279bc6c7c8500b7d5a13b6fb9fc97be35b \ + --hash=sha256:afda76d84b053923c27ede5edc1ed7d53e3c9f475ebaf63c68e69f1403c405a8 \ + --hash=sha256:b27a7fd4229abef715e064269d98a7e2909ebf92eb6912a9603c7e14c181928c \ + --hash=sha256:b648fe2a45e426aaee684ddca2632f62ec4613ef362f4d681a9a6283d10e079d \ + --hash=sha256:c5a550dc7a3b50b116323e3d376241829fd326ac47bc195e04eb33a8170902a9 \ + --hash=sha256:da46e2b5df770070412c46f87bac0849b8d685c5f2679771de277a422c7d0b86 \ + --hash=sha256:f39812f70fc5c71a15aa3c97b2bbe213c3f2a460b79bd21c40d033bb34a9bf36 \ + --hash=sha256:ff369dd19e8fe0528b02e8df9f2aeb2479f89b1270d90f96a63500afe9af5cae # via # gcp-releasetool # secretstorage From 9ee44afa8776f398da21458a4752f97d7c0aa605 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 07:41:44 +0100 Subject: [PATCH 1129/1979] build(deps): bump cryptography from 41.0.2 to 41.0.6 in /.kokoro (#1429) 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.6 in /.kokoro Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.6. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.6) --- 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 390cf85d47dd3d59595a66bb5a17e67384b4eb00 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 21 Dec 2023 15:15:29 +0100 Subject: [PATCH 1130/1979] test(deps): update dependency com.google.truth:truth to v1.2.0 (#1447) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1f01bee35e84..5a343b3993bc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.1.5 + 1.2.0 4.11.0 2.2 0.31.1 From 3f9e161ebbd03cb7e8507e9bbec6daac7659e230 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 21 Dec 2023 15:15:48 +0100 Subject: [PATCH 1131/1979] test(deps): update dependency com.google.truth:truth to v1.2.0 (#1448) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d71f8cf03cf7..86197f23c6c9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.1.5 + 1.2.0 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ce3483e6ffe6..56200a16dbfb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.1.5 + 1.2.0 test From ba8673958ace92735e7a6320fbe78a96ec252b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 22 Dec 2023 11:34:06 +0100 Subject: [PATCH 1132/1979] feat: support PreparedStatement#getParameterMetaData() (#1218) * feat: support PreparedStatement#getParameterMetaData() Add actual support for `PreparedStatement#getParameterMetaData()`. The first time this method is called for a PreparedStatement, the connection will now send the query to Cloud Spanner in analyze mode and without any parameter values. This will instruct Cloud Spanner to return the names and types of any query parameters in the statement. Fixes #35 * fix: restore previous behavior * fix: PostgreSQL string type name should be 'character varying' * fix: update type name to 'character varying' in integration test --- .../cloud/spanner/JdbcDataTypeConverter.java | 29 ++ .../spanner/jdbc/AbstractJdbcWrapper.java | 77 +++- .../cloud/spanner/jdbc/JdbcDataType.java | 8 +- .../spanner/jdbc/JdbcParameterMetaData.java | 139 +++++-- .../spanner/jdbc/JdbcPreparedStatement.java | 30 +- .../spanner/jdbc/AbstractJdbcWrapperTest.java | 67 ++++ .../jdbc/JdbcPreparedStatementTest.java | 56 ++- ...PreparedStatementWithMockedServerTest.java | 182 ++++++++- ...reparedStatementParameterMetadataTest.java | 361 ++++++++++++++++++ .../jdbc/it/ITJdbcPreparedStatementTest.java | 254 +++++++++++- 10 files changed, 1140 insertions(+), 63 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/JdbcDataTypeConverter.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/JdbcDataTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/JdbcDataTypeConverter.java new file mode 100644 index 000000000000..62d52c6c36e8 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/JdbcDataTypeConverter.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; + +import com.google.api.core.InternalApi; + +@InternalApi +public class JdbcDataTypeConverter { + + /** Converts a protobuf type to a Spanner type. */ + @InternalApi + public static Type toSpannerType(com.google.spanner.v1.Type proto) { + return Type.fromProto(proto); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index f577ac3c6586..b56aed037dfb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; import com.google.common.base.Preconditions; @@ -69,7 +70,74 @@ static int extractColumnType(Type type) { } } - /** Extract Spanner type name from {@link java.sql.Types} code. */ + static String getSpannerTypeName(Type type, Dialect dialect) { + // TODO: Use com.google.cloud.spanner.Type#getSpannerTypeName() when available. + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case BOOL: + return dialect == Dialect.POSTGRESQL ? "boolean" : "BOOL"; + case BYTES: + return dialect == Dialect.POSTGRESQL ? "bytea" : "BYTES"; + case DATE: + return dialect == Dialect.POSTGRESQL ? "date" : "DATE"; + case FLOAT64: + return dialect == Dialect.POSTGRESQL ? "double precision" : "FLOAT64"; + case INT64: + return dialect == Dialect.POSTGRESQL ? "bigint" : "INT64"; + case NUMERIC: + return "NUMERIC"; + case PG_NUMERIC: + return "numeric"; + case STRING: + return dialect == Dialect.POSTGRESQL ? "character varying" : "STRING"; + case JSON: + return "JSON"; + case PG_JSONB: + return "jsonb"; + case TIMESTAMP: + return dialect == Dialect.POSTGRESQL ? "timestamp with time zone" : "TIMESTAMP"; + case STRUCT: + return "STRUCT"; + case ARRAY: + switch (type.getArrayElementType().getCode()) { + case BOOL: + return dialect == Dialect.POSTGRESQL ? "boolean[]" : "ARRAY"; + case BYTES: + return dialect == Dialect.POSTGRESQL ? "bytea[]" : "ARRAY"; + case DATE: + return dialect == Dialect.POSTGRESQL ? "date[]" : "ARRAY"; + case FLOAT64: + return dialect == Dialect.POSTGRESQL ? "double precision[]" : "ARRAY"; + case INT64: + return dialect == Dialect.POSTGRESQL ? "bigint[]" : "ARRAY"; + case NUMERIC: + return "ARRAY"; + case PG_NUMERIC: + return "numeric[]"; + case STRING: + return dialect == Dialect.POSTGRESQL ? "character varying[]" : "ARRAY"; + case JSON: + return "ARRAY"; + case PG_JSONB: + return "jsonb[]"; + case TIMESTAMP: + return dialect == Dialect.POSTGRESQL + ? "timestamp with time zone[]" + : "ARRAY"; + case STRUCT: + return "ARRAY"; + } + default: + return null; + } + } + + /** + * Extract Spanner type name from {@link java.sql.Types} code. + * + * @deprecated Use {@link #getSpannerTypeName(Type, Dialect)} instead. + */ + @Deprecated static String getSpannerTypeName(int sqlType) { if (sqlType == Types.BOOLEAN) return Type.bool().getCode().name(); if (sqlType == Types.BINARY) return Type.bytes().getCode().name(); @@ -89,7 +157,12 @@ static String getSpannerTypeName(int sqlType) { return OTHER_NAME; } - /** Get corresponding Java class name from {@link java.sql.Types} code. */ + /** + * Get corresponding Java class name from {@link java.sql.Types} code. + * + * @deprecated Use {@link #getClassName(Type)} instead. + */ + @Deprecated static String getClassName(int sqlType) { if (sqlType == Types.BOOLEAN) return Boolean.class.getName(); if (sqlType == Types.BINARY) return Byte[].class.getName(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index c495bbe1660f..5dd082ef8439 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -390,14 +390,18 @@ public Set> getSupportedJavaClasses() { public static JdbcDataType getType(Class clazz) { for (JdbcDataType type : JdbcDataType.values()) { - if (type.getSupportedJavaClasses().contains(clazz)) return type; + if (type.getSupportedJavaClasses().contains(clazz)) { + return type; + } } return null; } public static JdbcDataType getType(Code code) { for (JdbcDataType type : JdbcDataType.values()) { - if (type.getCode() == code) return type; + if (type.getCode() == code) { + return type; + } } return null; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java index a520e221ec09..82a4b9133c62 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -16,7 +16,13 @@ package com.google.cloud.spanner.jdbc; -import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; +import com.google.cloud.spanner.JdbcDataTypeConverter; +import com.google.cloud.spanner.ResultSet; +import com.google.rpc.Code; +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.math.BigDecimal; import java.sql.Date; import java.sql.ParameterMetaData; @@ -29,9 +35,23 @@ class JdbcParameterMetaData extends AbstractJdbcWrapper implements ParameterMetaData { private final JdbcPreparedStatement statement; - JdbcParameterMetaData(JdbcPreparedStatement statement) throws SQLException { + private final StructType parameters; + + JdbcParameterMetaData(JdbcPreparedStatement statement, ResultSet resultSet) { this.statement = statement; - statement.getParameters().fetchMetaData(statement.getConnection()); + this.parameters = resultSet.getMetadata().getUndeclaredParameters(); + } + + private Field getField(int param) throws SQLException { + JdbcPreconditions.checkArgument(param > 0 && param <= parameters.getFieldsCount(), param); + String paramName = "p" + param; + return parameters.getFieldsList().stream() + .filter(field -> field.getName().equals(paramName)) + .findAny() + .orElseThrow( + () -> + JdbcSqlExceptionFactory.of( + "Unknown parameter: " + paramName, Code.INVALID_ARGUMENT)); } @Override @@ -41,8 +61,7 @@ public boolean isClosed() { @Override public int getParameterCount() { - ParametersInfo info = statement.getParametersInfo(); - return info.numberOfParameters; + return parameters.getFieldsCount(); } @Override @@ -53,7 +72,7 @@ public int isNullable(int param) { } @Override - public boolean isSigned(int param) { + public boolean isSigned(int param) throws SQLException { int type = getParameterType(param); return type == Types.DOUBLE || type == Types.FLOAT @@ -77,9 +96,34 @@ public int getScale(int param) { } @Override - public int getParameterType(int param) { + public int getParameterType(int param) throws SQLException { + JdbcPreconditions.checkArgument(param > 0 && param <= parameters.getFieldsCount(), param); + int typeFromValue = getParameterTypeFromValue(param); + if (typeFromValue != Types.OTHER) { + return typeFromValue; + } + + Type type = getField(param).getType(); + // JDBC only has a generic ARRAY type. + if (type.getCode() == TypeCode.ARRAY) { + return Types.ARRAY; + } + JdbcDataType jdbcDataType = + JdbcDataType.getType(JdbcDataTypeConverter.toSpannerType(type).getCode()); + return jdbcDataType == null ? Types.OTHER : jdbcDataType.getSqlType(); + } + + /** + * This method returns the parameter type based on the parameter value that has been set. This was + * previously the only way to get the parameter types of a statement. Cloud Spanner can now return + * the types and names of parameters in a SQL string, which is what this method should return. + */ + // TODO: Remove this method for the next major version bump. + private int getParameterTypeFromValue(int param) { Integer type = statement.getParameters().getType(param); - if (type != null) return type; + if (type != null) { + return type; + } Object value = statement.getParameters().getParameter(param); if (value == null) { @@ -116,16 +160,49 @@ public int getParameterType(int param) { } @Override - public String getParameterTypeName(int param) { - return getSpannerTypeName(getParameterType(param)); + public String getParameterTypeName(int param) throws SQLException { + JdbcPreconditions.checkArgument(param > 0 && param <= parameters.getFieldsCount(), param); + String typeNameFromValue = getParameterTypeNameFromValue(param); + if (typeNameFromValue != null) { + return typeNameFromValue; + } + + com.google.cloud.spanner.Type type = + JdbcDataTypeConverter.toSpannerType(getField(param).getType()); + return getSpannerTypeName(type, statement.getConnection().getDialect()); + } + + private String getParameterTypeNameFromValue(int param) { + int type = getParameterTypeFromValue(param); + if (type != Types.OTHER) { + return getSpannerTypeName(type); + } + return null; } @Override - public String getParameterClassName(int param) { + public String getParameterClassName(int param) throws SQLException { + JdbcPreconditions.checkArgument(param > 0 && param <= parameters.getFieldsCount(), param); + String classNameFromValue = getParameterClassNameFromValue(param); + if (classNameFromValue != null) { + return classNameFromValue; + } + + com.google.cloud.spanner.Type type = + JdbcDataTypeConverter.toSpannerType(getField(param).getType()); + return getClassName(type); + } + + // TODO: Remove this method for the next major version bump. + private String getParameterClassNameFromValue(int param) { Object value = statement.getParameters().getParameter(param); - if (value != null) return value.getClass().getName(); + if (value != null) { + return value.getClass().getName(); + } Integer type = statement.getParameters().getType(param); - if (type != null) return getClassName(type); + if (type != null) { + return getClassName(type); + } return null; } @@ -136,22 +213,26 @@ public int getParameterMode(int param) { @Override public String toString() { - StringBuilder res = new StringBuilder(); - res.append("CloudSpannerPreparedStatementParameterMetaData, parameter count: ") - .append(getParameterCount()); - for (int param = 1; param <= getParameterCount(); param++) { - res.append("\nParameter ") - .append(param) - .append(":\n\t Class name: ") - .append(getParameterClassName(param)); - res.append(",\n\t Parameter type name: ").append(getParameterTypeName(param)); - res.append(",\n\t Parameter type: ").append(getParameterType(param)); - res.append(",\n\t Parameter precision: ").append(getPrecision(param)); - res.append(",\n\t Parameter scale: ").append(getScale(param)); - res.append(",\n\t Parameter signed: ").append(isSigned(param)); - res.append(",\n\t Parameter nullable: ").append(isNullable(param)); - res.append(",\n\t Parameter mode: ").append(getParameterMode(param)); + try { + StringBuilder res = new StringBuilder(); + res.append("CloudSpannerPreparedStatementParameterMetaData, parameter count: ") + .append(getParameterCount()); + for (int param = 1; param <= getParameterCount(); param++) { + res.append("\nParameter ") + .append(param) + .append(":\n\t Class name: ") + .append(getParameterClassName(param)); + res.append(",\n\t Parameter type name: ").append(getParameterTypeName(param)); + res.append(",\n\t Parameter type: ").append(getParameterType(param)); + res.append(",\n\t Parameter precision: ").append(getPrecision(param)); + res.append(",\n\t Parameter scale: ").append(getScale(param)); + res.append(",\n\t Parameter signed: ").append(isSigned(param)); + res.append(",\n\t Parameter nullable: ").append(isNullable(param)); + res.append(",\n\t Parameter mode: ").append(getParameterMode(param)); + } + return res.toString(); + } catch (SQLException exception) { + return "Failed to get parameter metadata: " + exception; } - return res.toString(); } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 518807dd11fa..9ebbc98f5452 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -40,6 +40,7 @@ class JdbcPreparedStatement extends AbstractJdbcPreparedStatement private static final char POS_PARAM_CHAR = '?'; private final String sql; private final ParametersInfo parameters; + private JdbcParameterMetaData cachedParameterMetadata; private final ImmutableList generatedKeysColumns; JdbcPreparedStatement( @@ -118,7 +119,34 @@ public void addBatch() throws SQLException { @Override public JdbcParameterMetaData getParameterMetaData() throws SQLException { checkClosed(); - return new JdbcParameterMetaData(this); + if (cachedParameterMetadata == null) { + if (getConnection().getParser().isUpdateStatement(sql) + && !getConnection().getParser().checkReturningClause(sql)) { + cachedParameterMetadata = getParameterMetadataForUpdate(); + } else { + cachedParameterMetadata = getParameterMetadataForQuery(); + } + } + return cachedParameterMetadata; + } + + private JdbcParameterMetaData getParameterMetadataForUpdate() { + try (com.google.cloud.spanner.ResultSet resultSet = + getConnection() + .getSpannerConnection() + .analyzeUpdateStatement( + Statement.of(parameters.sqlWithNamedParameters), QueryAnalyzeMode.PLAN)) { + return new JdbcParameterMetaData(this, resultSet); + } + } + + private JdbcParameterMetaData getParameterMetadataForQuery() { + try (com.google.cloud.spanner.ResultSet resultSet = + getConnection() + .getSpannerConnection() + .analyzeQuery(Statement.of(parameters.sqlWithNamedParameters), QueryAnalyzeMode.PLAN)) { + return new JdbcParameterMetaData(this, resultSet); + } } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index 372bbb090346..f8473f638642 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.AbstractJdbcWrapper.getSpannerTypeName; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -23,6 +24,8 @@ import static org.junit.Assert.fail; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Type; import com.google.rpc.Code; import java.math.BigDecimal; import java.math.BigInteger; @@ -426,4 +429,68 @@ public void testParseTimestampWithCalendar() throws SQLException { assertThat(((JdbcSqlException) e).getCode()).isEqualTo(Code.INVALID_ARGUMENT); } } + + @Test + public void testGoogleSQLTypeNames() { + assertEquals("INT64", getSpannerTypeName(Type.int64(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("BOOL", getSpannerTypeName(Type.bool(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("FLOAT64", getSpannerTypeName(Type.float64(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("STRING", getSpannerTypeName(Type.string(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("BYTES", getSpannerTypeName(Type.bytes(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("DATE", getSpannerTypeName(Type.date(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("TIMESTAMP", getSpannerTypeName(Type.timestamp(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("JSON", getSpannerTypeName(Type.json(), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals("NUMERIC", getSpannerTypeName(Type.numeric(), Dialect.GOOGLE_STANDARD_SQL)); + + assertEquals( + "ARRAY", getSpannerTypeName(Type.array(Type.int64()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", getSpannerTypeName(Type.array(Type.bool()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", + getSpannerTypeName(Type.array(Type.float64()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", + getSpannerTypeName(Type.array(Type.string()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", getSpannerTypeName(Type.array(Type.bytes()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", getSpannerTypeName(Type.array(Type.date()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", + getSpannerTypeName(Type.array(Type.timestamp()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", getSpannerTypeName(Type.array(Type.json()), Dialect.GOOGLE_STANDARD_SQL)); + assertEquals( + "ARRAY", + getSpannerTypeName(Type.array(Type.numeric()), Dialect.GOOGLE_STANDARD_SQL)); + } + + @Test + public void testPostgreSQLTypeNames() { + assertEquals("bigint", getSpannerTypeName(Type.int64(), Dialect.POSTGRESQL)); + assertEquals("boolean", getSpannerTypeName(Type.bool(), Dialect.POSTGRESQL)); + assertEquals("double precision", getSpannerTypeName(Type.float64(), Dialect.POSTGRESQL)); + assertEquals("character varying", getSpannerTypeName(Type.string(), Dialect.POSTGRESQL)); + assertEquals("bytea", getSpannerTypeName(Type.bytes(), Dialect.POSTGRESQL)); + assertEquals("date", getSpannerTypeName(Type.date(), Dialect.POSTGRESQL)); + assertEquals( + "timestamp with time zone", getSpannerTypeName(Type.timestamp(), Dialect.POSTGRESQL)); + assertEquals("jsonb", getSpannerTypeName(Type.pgJsonb(), Dialect.POSTGRESQL)); + assertEquals("numeric", getSpannerTypeName(Type.pgNumeric(), Dialect.POSTGRESQL)); + + assertEquals("bigint[]", getSpannerTypeName(Type.array(Type.int64()), Dialect.POSTGRESQL)); + assertEquals("boolean[]", getSpannerTypeName(Type.array(Type.bool()), Dialect.POSTGRESQL)); + assertEquals( + "double precision[]", getSpannerTypeName(Type.array(Type.float64()), Dialect.POSTGRESQL)); + assertEquals( + "character varying[]", getSpannerTypeName(Type.array(Type.string()), Dialect.POSTGRESQL)); + assertEquals("bytea[]", getSpannerTypeName(Type.array(Type.bytes()), Dialect.POSTGRESQL)); + assertEquals("date[]", getSpannerTypeName(Type.array(Type.date()), Dialect.POSTGRESQL)); + assertEquals( + "timestamp with time zone[]", + getSpannerTypeName(Type.array(Type.timestamp()), Dialect.POSTGRESQL)); + assertEquals("jsonb[]", getSpannerTypeName(Type.array(Type.pgJsonb()), Dialect.POSTGRESQL)); + assertEquals("numeric[]", getSpannerTypeName(Type.array(Type.pgNumeric()), Dialect.POSTGRESQL)); + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index 310d1546e90f..c5748d1c71e6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -18,9 +18,9 @@ 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; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; @@ -39,6 +39,10 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.Connection; +import com.google.spanner.v1.ResultSetMetadata; +import com.google.spanner.v1.StructType; +import com.google.spanner.v1.StructType.Field; +import com.google.spanner.v1.TypeCode; import java.io.ByteArrayInputStream; import java.io.StringReader; import java.math.BigDecimal; @@ -55,6 +59,8 @@ import java.util.Collections; import java.util.TimeZone; import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -158,7 +164,8 @@ public void testParameters() throws SQLException, MalformedURLException { final int numberOfParams = 53; String sql = generateSqlWithParameters(numberOfParams); - JdbcConnection connection = createMockConnection(); + Connection spannerConnection = createMockConnectionWithAnalyzeResults(numberOfParams); + JdbcConnection connection = createMockConnection(spannerConnection); try (JdbcPreparedStatement ps = new JdbcPreparedStatement(connection, sql, NO_GENERATED_KEY_COLUMNS)) { ps.setArray(1, connection.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); @@ -252,10 +259,14 @@ public void testParameters() throws SQLException, MalformedURLException { assertEquals(String.class.getName(), pmd.getParameterClassName(35)); assertEquals(String.class.getName(), pmd.getParameterClassName(36)); assertEquals(String.class.getName(), pmd.getParameterClassName(37)); - assertNull(pmd.getParameterClassName(38)); - assertNull(pmd.getParameterClassName(39)); + + // These parameter values are not set, so the driver returns the type that was returned by + // Cloud Spanner. + assertEquals(String.class.getName(), pmd.getParameterClassName(38)); + assertEquals(String.class.getName(), pmd.getParameterClassName(39)); + assertEquals(Short.class.getName(), pmd.getParameterClassName(40)); - assertNull(pmd.getParameterClassName(41)); + assertEquals(String.class.getName(), pmd.getParameterClassName(41)); assertEquals(String.class.getName(), pmd.getParameterClassName(42)); assertEquals(Time.class.getName(), pmd.getParameterClassName(43)); assertEquals(Time.class.getName(), pmd.getParameterClassName(44)); @@ -279,8 +290,11 @@ public void testParameters() throws SQLException, MalformedURLException { public void testSetNullValues() throws SQLException { final int numberOfParameters = 31; String sql = generateSqlWithParameters(numberOfParameters); + + JdbcConnection connection = + createMockConnection(createMockConnectionWithAnalyzeResults(numberOfParameters)); try (JdbcPreparedStatement ps = - new JdbcPreparedStatement(createMockConnection(), sql, NO_GENERATED_KEY_COLUMNS)) { + new JdbcPreparedStatement(connection, sql, NO_GENERATED_KEY_COLUMNS)) { int index = 0; ps.setNull(++index, Types.BLOB); ps.setNull(++index, Types.NVARCHAR); @@ -396,4 +410,34 @@ public void testInvalidSql() { assertEquals( ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value(), jdbcSqlException.getErrorCode()); } + + private Connection createMockConnectionWithAnalyzeResults(int numParams) { + Connection spannerConnection = mock(Connection.class); + ResultSet resultSet = mock(ResultSet.class); + when(spannerConnection.analyzeUpdateStatement(any(Statement.class), eq(QueryAnalyzeMode.PLAN))) + .thenReturn(resultSet); + when(spannerConnection.analyzeQuery(any(Statement.class), eq(QueryAnalyzeMode.PLAN))) + .thenReturn(resultSet); + ResultSetMetadata metadata = + ResultSetMetadata.newBuilder() + .setUndeclaredParameters( + StructType.newBuilder() + .addAllFields( + IntStream.range(0, numParams) + .mapToObj( + i -> + Field.newBuilder() + .setName("p" + (i + 1)) + .setType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.STRING) + .build()) + .build()) + .collect(Collectors.toList())) + .build()) + .build(); + when(resultSet.getMetadata()).thenReturn(metadata); + + return spannerConnection; + } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java index d3607d842753..a3072e31082e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementWithMockedServerTest.java @@ -28,6 +28,13 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlBatchUpdateException; +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.TypeCode; import io.grpc.Server; import io.grpc.Status; import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; @@ -198,11 +205,180 @@ public void testExecuteBatch_withException() throws SQLException { @Test public void testInsertUntypedNullValues() throws SQLException { + String sql = + "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)"; + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of(sql), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setUndeclaredParameters( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("p1") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p2") + .setType( + Type.newBuilder().setCode(TypeCode.FLOAT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p3") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p4") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p5") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p6") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p7") + .setType( + Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p8") + .setType( + Type.newBuilder().setCode(TypeCode.NUMERIC).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p9") + .setType(Type.newBuilder().setCode(TypeCode.JSON).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p10") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.INT64) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p11") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.FLOAT64) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p12") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.BOOL) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p13") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.STRING) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p14") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.BYTES) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p15") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.DATE) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p16") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.TIMESTAMP) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p17") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .build()) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p18") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.JSON) + .build()) + .build()) + .build()) + .build()) + .build()) + .setStats(ResultSetStats.newBuilder().build()) + .build())); 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)") + Statement.newBuilder(sql) .bind("p1") .to((Value) null) .bind("p2") diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java new file mode 100644 index 000000000000..8b7130ed6496 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java @@ -0,0 +1,361 @@ +/* + * Copyright 2022 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 com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl; +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.SpannerPool; +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.sql.Connection; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Types; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class PreparedStatementParameterMetadataTest extends AbstractMockServerTest { + + @After + public void reset() { + // This ensures that each test gets a fresh Spanner instance. This is necessary to get a new + // dialect result for each connection. + SpannerPool.closeSpannerPool(); + } + + @Test + public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); + + String baseSql = + "insert into all_types (col_bool, col_bytes, col_date, col_float64, col_int64, " + + "col_json, col_numeric, col_string, col_timestamp, col_bool_array, col_bytes_array, " + + "col_date_array, col_float64_array, col_int64_array, col_json_array, col_numeric_array, " + + "col_string_array, col_timestamp_array) values (%s)"; + String jdbcSql = + String.format( + baseSql, + IntStream.range(0, 18).mapToObj(ignored -> "?").collect(Collectors.joining(", "))); + String googleSql = + String.format( + baseSql, + IntStream.range(1, 19) + .mapToObj(index -> "@p" + index) + .collect(Collectors.joining(", "))); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of(googleSql), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setUndeclaredParameters( + createAllTypesParameters(Dialect.GOOGLE_STANDARD_SQL)) + .build()) + .setStats(ResultSetStats.newBuilder().build()) + .build())); + + try (Connection connection = createJdbcConnection()) { + try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) { + ParameterMetaData metadata = statement.getParameterMetaData(); + assertEquals(18, metadata.getParameterCount()); + int index = 0; + assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); + assertEquals("BOOL", metadata.getParameterTypeName(index)); + assertEquals(Types.BINARY, metadata.getParameterType(++index)); + assertEquals("BYTES", metadata.getParameterTypeName(index)); + assertEquals(Types.DATE, metadata.getParameterType(++index)); + assertEquals("DATE", metadata.getParameterTypeName(index)); + assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); + assertEquals("FLOAT64", metadata.getParameterTypeName(index)); + assertEquals(Types.BIGINT, metadata.getParameterType(++index)); + assertEquals("INT64", metadata.getParameterTypeName(index)); + assertEquals(JsonType.VENDOR_TYPE_NUMBER, metadata.getParameterType(++index)); + assertEquals("JSON", metadata.getParameterTypeName(index)); + assertEquals(Types.NUMERIC, metadata.getParameterType(++index)); + assertEquals("NUMERIC", metadata.getParameterTypeName(index)); + assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); + assertEquals("STRING", metadata.getParameterTypeName(index)); + assertEquals(Types.TIMESTAMP, metadata.getParameterType(++index)); + assertEquals("TIMESTAMP", metadata.getParameterTypeName(index)); + + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + } + } + } + + @Test + public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException { + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + + String baseSql = + "insert into all_types (col_bool, col_bytes, col_date, col_float64, col_int64, " + + "col_json, col_numeric, col_string, col_timestamp, col_bool_array, col_bytes_array, " + + "col_date_array, col_float64_array, col_int64_array, col_json_array, col_numeric_array, " + + "col_string_array, col_timestamp_array) values (%s)"; + String jdbcSql = + String.format( + baseSql, + IntStream.range(0, 18).mapToObj(ignored -> "?").collect(Collectors.joining(", "))); + String googleSql = + String.format( + baseSql, + IntStream.range(1, 19) + .mapToObj(index -> "$" + index) + .collect(Collectors.joining(", "))); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of(googleSql), + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setUndeclaredParameters(createAllTypesParameters(Dialect.POSTGRESQL)) + .build()) + .setStats(ResultSetStats.newBuilder().build()) + .build())); + + try (Connection connection = createJdbcConnection()) { + try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) { + ParameterMetaData metadata = statement.getParameterMetaData(); + assertEquals(18, metadata.getParameterCount()); + int index = 0; + assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); + assertEquals("boolean", metadata.getParameterTypeName(index)); + assertEquals(Types.BINARY, metadata.getParameterType(++index)); + assertEquals("bytea", metadata.getParameterTypeName(index)); + assertEquals(Types.DATE, metadata.getParameterType(++index)); + assertEquals("date", metadata.getParameterTypeName(index)); + assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); + assertEquals("double precision", metadata.getParameterTypeName(index)); + assertEquals(Types.BIGINT, metadata.getParameterType(++index)); + assertEquals("bigint", metadata.getParameterTypeName(index)); + assertEquals(PgJsonbType.VENDOR_TYPE_NUMBER, metadata.getParameterType(++index)); + assertEquals("jsonb", metadata.getParameterTypeName(index)); + assertEquals(Types.NUMERIC, metadata.getParameterType(++index)); + assertEquals("numeric", metadata.getParameterTypeName(index)); + assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); + assertEquals("character varying", metadata.getParameterTypeName(index)); + assertEquals(Types.TIMESTAMP, metadata.getParameterType(++index)); + assertEquals("timestamp with time zone", metadata.getParameterTypeName(index)); + + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("boolean[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("bytea[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("date[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("double precision[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("bigint[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("jsonb[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("numeric[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("character varying[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("timestamp with time zone[]", metadata.getParameterTypeName(index)); + } + } + } + + static StructType createAllTypesParameters(Dialect dialect) { + return StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("p1") + .setType(Type.newBuilder().setCode(TypeCode.BOOL).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p2") + .setType(Type.newBuilder().setCode(TypeCode.BYTES).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p3") + .setType(Type.newBuilder().setCode(TypeCode.DATE).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p4") + .setType(Type.newBuilder().setCode(TypeCode.FLOAT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p5") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p6") + .setType( + Type.newBuilder() + .setCode(TypeCode.JSON) + .setTypeAnnotation( + dialect == Dialect.POSTGRESQL + ? TypeAnnotationCode.PG_JSONB + : TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p7") + .setType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation( + dialect == Dialect.POSTGRESQL + ? TypeAnnotationCode.PG_NUMERIC + : TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED) + .build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p8") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p9") + .setType(Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p10") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.BOOL).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p11") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.BYTES).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p12") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.DATE).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p13") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.FLOAT64).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p14") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.INT64).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p15") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.JSON) + .setTypeAnnotation( + dialect == Dialect.POSTGRESQL + ? TypeAnnotationCode.PG_JSONB + : TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED) + .build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p16") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation( + dialect == Dialect.POSTGRESQL + ? TypeAnnotationCode.PG_NUMERIC + : TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED) + .build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p17") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.STRING).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p18") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.TIMESTAMP).build())) + .build()) + .build(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 2864559c889e..8f014937a151 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -21,7 +21,6 @@ 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.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; @@ -35,6 +34,7 @@ import com.google.cloud.spanner.jdbc.JsonType; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; import com.google.common.io.CharStreams; import java.io.IOException; @@ -394,7 +394,26 @@ public void test01_InsertTestData() throws SQLException { try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?)")) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 5); + assertParameterMetaData( + ps.getParameterMetaData(), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR) + : ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "character varying", + "character varying", + "bytea", + "character varying") + : ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Long.class, String.class, String.class, byte[].class, String.class) + : ImmutableList.of( + Long.class, String.class, String.class, byte[].class, Date.class)); for (Singer singer : createSingers()) { singer.setPreparedStatement(ps, getDialect()); assertInsertSingerParameterMetadata(ps.getParameterMetaData()); @@ -410,7 +429,13 @@ public void test01_InsertTestData() throws SQLException { try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (?,?,?,?)")) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 4); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of(Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.BIGINT), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of("bigint", "bigint", "character varying", "bigint") + : ImmutableList.of("INT64", "INT64", "STRING", "INT64"), + ImmutableList.of(Long.class, Long.class, String.class, Long.class)); for (Album album : createAlbums()) { ps.setLong(1, album.singerId); ps.setLong(2, album.albumId); @@ -425,7 +450,26 @@ public void test01_InsertTestData() throws SQLException { try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?);")) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.BIGINT, + Types.NVARCHAR, + Types.BIGINT, + Types.NVARCHAR), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "bigint", + "character varying", + "bigint", + "character varying") + : ImmutableList.of("INT64", "INT64", "INT64", "STRING", "INT64", "STRING"), + ImmutableList.of( + Long.class, Long.class, Long.class, String.class, Long.class, String.class)); for (Song song : createSongs()) { ps.setByte(1, (byte) song.singerId); ps.setInt(2, (int) song.albumId); @@ -441,8 +485,36 @@ public void test01_InsertTestData() throws SQLException { } try (PreparedStatement ps = connection.prepareStatement(getConcertsInsertQuery(dialect.dialect))) { - assertDefaultParameterMetaData( - ps.getParameterMetaData(), getConcertExpectedParamCount(dialect.dialect)); + assertParameterMetaData( + ps.getParameterMetaData(), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR) + : ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "character varying", + "character varying", + "character varying") + : ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class) + : ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); for (Concert concert : createConcerts()) { concert.setPreparedStatement(connection, ps, getDialect()); assertInsertConcertParameterMetadata(ps.getParameterMetaData()); @@ -564,7 +636,24 @@ public void test03_Dates() throws SQLException { try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);")) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), + ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); ps.setLong(1, 100); ps.setLong(2, 19); ps.setDate(3, testDate); @@ -660,7 +749,24 @@ public void test04_Timestamps() throws SQLException { try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);")) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), + ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); ps.setLong(1, 100); ps.setLong(2, 19); ps.setDate(3, new Date(System.currentTimeMillis())); @@ -868,7 +974,33 @@ public void test08_InsertAllColumnTypes() throws SQLException { + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { + ParameterMetaData metadata = ps.getParameterMetaData(); + assertEquals(22, metadata.getParameterCount()); int index = 0; + assertEquals(Types.BIGINT, metadata.getParameterType(++index)); + assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); + assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); + assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); + assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); + assertEquals(Types.BINARY, metadata.getParameterType(++index)); + assertEquals(Types.BINARY, metadata.getParameterType(++index)); + assertEquals(Types.DATE, metadata.getParameterType(++index)); + assertEquals(Types.TIMESTAMP, metadata.getParameterType(++index)); + assertEquals(Types.NUMERIC, metadata.getParameterType(++index)); + assertEquals(JsonType.VENDOR_TYPE_NUMBER, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + + index = 0; ps.setLong(++index, 1L); ps.setDouble(++index, 2D); ps.setBoolean(++index, true); @@ -1182,18 +1314,28 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { } } - private void assertDefaultParameterMetaData(ParameterMetaData pmd, int expectedParamCount) + private void assertParameterMetaData( + ParameterMetaData pmd, + ImmutableList sqlTypes, + ImmutableList typeNames, + ImmutableList> classNames) throws SQLException { - assertEquals(expectedParamCount, pmd.getParameterCount()); - for (int param = 1; param <= expectedParamCount; param++) { - assertEquals(Types.OTHER, pmd.getParameterType(param)); - assertEquals("OTHER", pmd.getParameterTypeName(param)); + assertEquals(sqlTypes.size(), typeNames.size()); + assertEquals(sqlTypes.size(), classNames.size()); + + ImmutableList signedTypes = + ImmutableList.of(Types.BIGINT, Types.NUMERIC, Types.DOUBLE); + assertEquals(sqlTypes.size(), pmd.getParameterCount()); + for (int param = 1; param <= sqlTypes.size(); param++) { + String msg = "Param " + param; + assertEquals(msg, sqlTypes.get(param - 1).intValue(), pmd.getParameterType(param)); + assertEquals(msg, typeNames.get(param - 1), pmd.getParameterTypeName(param)); assertEquals(0, pmd.getPrecision(param)); assertEquals(0, pmd.getScale(param)); - assertNull(pmd.getParameterClassName(param)); + assertEquals(msg, classNames.get(param - 1).getName(), pmd.getParameterClassName(param)); assertEquals(ParameterMetaData.parameterModeIn, pmd.getParameterMode(param)); assertEquals(ParameterMetaData.parameterNullableUnknown, pmd.isNullable(param)); - assertFalse(pmd.isSigned(param)); + assertEquals(msg, signedTypes.contains(sqlTypes.get(param - 1)), pmd.isSigned(param)); } } @@ -1214,7 +1356,26 @@ public void test12_InsertReturningTestData() throws SQLException { deleteStatements.executeBatch(); try (PreparedStatement ps = connection.prepareStatement(getSingersInsertReturningQuery(dialect.dialect))) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 5); + assertParameterMetaData( + ps.getParameterMetaData(), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR) + : ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "character varying", + "character varying", + "bytea", + "character varying") + : ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Long.class, String.class, String.class, byte[].class, String.class) + : ImmutableList.of( + Long.class, String.class, String.class, byte[].class, Date.class)); for (Singer singer : createSingers()) { singer.setPreparedStatement(ps, getDialect()); assertInsertSingerParameterMetadata(ps.getParameterMetaData()); @@ -1229,7 +1390,13 @@ public void test12_InsertReturningTestData() throws SQLException { } try (PreparedStatement ps = connection.prepareStatement(getAlbumsInsertReturningQuery(dialect.dialect))) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 4); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of(Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.BIGINT), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of("bigint", "bigint", "character varying", "bigint") + : ImmutableList.of("INT64", "INT64", "STRING", "INT64"), + ImmutableList.of(Long.class, Long.class, String.class, Long.class)); for (Album album : createAlbums()) { ps.setLong(1, album.singerId); ps.setLong(2, album.albumId); @@ -1249,7 +1416,26 @@ public void test12_InsertReturningTestData() throws SQLException { } try (PreparedStatement ps = connection.prepareStatement(getSongsInsertReturningQuery(dialect.dialect))) { - assertDefaultParameterMetaData(ps.getParameterMetaData(), 6); + assertParameterMetaData( + ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.BIGINT, + Types.NVARCHAR, + Types.BIGINT, + Types.NVARCHAR), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "bigint", + "character varying", + "bigint", + "character varying") + : ImmutableList.of("INT64", "INT64", "INT64", "STRING", "INT64", "STRING"), + ImmutableList.of( + Long.class, Long.class, Long.class, String.class, Long.class, String.class)); for (Song song : createSongs()) { ps.setByte(1, (byte) song.singerId); ps.setInt(2, (int) song.albumId); @@ -1277,8 +1463,36 @@ public void test12_InsertReturningTestData() throws SQLException { } try (PreparedStatement ps = connection.prepareStatement(getConcertsInsertReturningQuery(dialect.dialect))) { - assertDefaultParameterMetaData( - ps.getParameterMetaData(), getConcertExpectedParamCount(dialect.dialect)); + assertParameterMetaData( + ps.getParameterMetaData(), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR) + : ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "character varying", + "character varying", + "character varying") + : ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class) + : ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); for (Concert concert : createConcerts()) { concert.setPreparedStatement(connection, ps, getDialect()); assertInsertConcertParameterMetadata(ps.getParameterMetaData()); From b23caddbc5a1ae2a4491573f171b25d3f29d4d6f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 13:30:16 +0000 Subject: [PATCH 1133/1979] chore(main): release 2.15.0 (#1446) :robot: I have created a release *beep* *boop* --- ## [2.15.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.14.6...v2.15.0) (2023-12-22) ### Features * Support PreparedStatement#getParameterMetaData() ([#1218](https://togithub.com/googleapis/java-spanner-jdbc/issues/1218)) ([ba86739](https://togithub.com/googleapis/java-spanner-jdbc/commit/ba8673958ace92735e7a6320fbe78a96ec252b81)) ### Performance Improvements * Optimize isValid implementation ([#1444](https://togithub.com/googleapis/java-spanner-jdbc/issues/1444)) ([a1042f8](https://togithub.com/googleapis/java-spanner-jdbc/commit/a1042f8a21ec3ed6ab102cb61b1d07202acf77f4)), closes [#1443](https://togithub.com/googleapis/java-spanner-jdbc/issues/1443) ### Dependencies * Update dependency org.postgresql:postgresql to v42.7.1 ([#1441](https://togithub.com/googleapis/java-spanner-jdbc/issues/1441)) ([d388bdb](https://togithub.com/googleapis/java-spanner-jdbc/commit/d388bdba4b4d4a05cf6162eee133b63f102f868c)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 17 +++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8fdf14867348..1f9540e33c15 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [2.15.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.6...v2.15.0) (2023-12-22) + + +### Features + +* Support PreparedStatement#getParameterMetaData() ([#1218](https://github.com/googleapis/java-spanner-jdbc/issues/1218)) ([721ff45](https://github.com/googleapis/java-spanner-jdbc/commit/721ff4552104efba47c19ef511282071c3b334c3)) + + +### Performance Improvements + +* Optimize isValid implementation ([#1444](https://github.com/googleapis/java-spanner-jdbc/issues/1444)) ([914e973](https://github.com/googleapis/java-spanner-jdbc/commit/914e973ad7fd638fabc3ec130b7618c51f01f401)), closes [#1443](https://github.com/googleapis/java-spanner-jdbc/issues/1443) + + +### Dependencies + +* Update dependency org.postgresql:postgresql to v42.7.1 ([#1441](https://github.com/googleapis/java-spanner-jdbc/issues/1441)) ([5997555](https://github.com/googleapis/java-spanner-jdbc/commit/59975553826360b86492e50b9d49c29aecc28bab)) + ## [2.14.6](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.5...v2.14.6) (2023-12-04) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a343b3993bc..4240553d32b7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.7-SNAPSHOT + 2.15.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 56200a16dbfb..9ba5de8beea9 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.7-SNAPSHOT + 2.15.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6dc9f85edcc9..b20313946412 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.14.6:2.14.7-SNAPSHOT +google-cloud-spanner-jdbc:2.15.0:2.15.0 From c43501e2406fe3df3f21cf90d73ed16106412d98 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:46:17 +0000 Subject: [PATCH 1134/1979] chore(main): release 2.15.1-SNAPSHOT (#1451) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4240553d32b7..99dd090aa288 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.0 + 2.15.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9ba5de8beea9..9bb5c7c21071 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.0 + 2.15.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b20313946412..dc2b8656016f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.0:2.15.0 +google-cloud-spanner-jdbc:2.15.0:2.15.1-SNAPSHOT From b0544d5eb2e37caff40e6e6016fc51cdf1b3b91f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Dec 2023 11:42:47 +0100 Subject: [PATCH 1135/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.0 (#1452) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 86197f23c6c9..d09f8550309a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.14.6 + 2.15.0 From aab9ac9b98c4dc8eb9c0e32aeecef678dce29f92 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Jan 2024 13:39:46 +0100 Subject: [PATCH 1136/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.21.0 (#1454) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 99dd090aa288..b9fe42504188 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.20.0 + 3.21.0 pom import From 0a848d4913689319a0951722fb0d59bec36d1be6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Jan 2024 17:00:16 +0100 Subject: [PATCH 1137/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.56.0 (#1455) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b9fe42504188..da134382f765 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.55.0 + 6.56.0 pom import From f15efa30c539b04085e3c7fc0dd6b0f3d30964ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 9 Jan 2024 08:04:02 +0100 Subject: [PATCH 1138/1979] chore: modify metadata queries to support named schemas (#1449) Modify metadata queries so these are able to handle multiple named schemas in the same database, potentially with tables and indexes with the same names in different schemas. --- .../cloud/spanner/jdbc/JdbcConnection.java | 1 + .../DatabaseMetaData_GetCrossReferences.sql | 42 +++++++++++++------ .../jdbc/DatabaseMetaData_GetExportedKeys.sql | 11 +++-- .../jdbc/DatabaseMetaData_GetImportedKeys.sql | 9 +++- .../DatabaseMetaData_GetCrossReferences.sql | 11 ++++- .../DatabaseMetaData_GetExportedKeys.sql | 11 ++++- .../DatabaseMetaData_GetImportedKeys.sql | 11 ++++- 7 files changed, 73 insertions(+), 23 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 4cef6b3f1a82..2c7d6cc00823 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -492,6 +492,7 @@ public String getSchema() throws SQLException { @Nonnull String getDefaultSchema() { + // TODO: Update to use getDialect()#getDefaultSchema() when available. switch (getDialect()) { case POSTGRESQL: return "public"; diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql index 7d362ca58e87..622c0ee357e5 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetCrossReferences.sql @@ -16,17 +16,28 @@ SELECT * FROM ( - SELECT PARENT.TABLE_CATALOG AS PKTABLE_CAT, PARENT.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT.TABLE_NAME AS PKTABLE_NAME, - PARENT.COLUMN_NAME AS PKCOLUMN_NAME, CHILD.TABLE_CATALOG AS FKTABLE_CAT, CHILD.TABLE_SCHEMA AS FKTABLE_SCHEM, - CHILD.TABLE_NAME AS FKTABLE_NAME, CHILD.COLUMN_NAME AS FKCOLUMN_NAME, CHILD.ORDINAL_POSITION AS KEY_SEQ, 3 AS UPDATE_RULE, - CASE WHEN TABLES.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 3 END AS DELETE_RULE, NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, + SELECT PARENT_TABLE.TABLE_CATALOG AS PKTABLE_CAT, PARENT_TABLE.TABLE_SCHEMA AS PKTABLE_SCHEM, PARENT_TABLE.TABLE_NAME AS PKTABLE_NAME, + PARENT_INDEX_COLUMNS.COLUMN_NAME AS PKCOLUMN_NAME, CHILD_TABLE.TABLE_CATALOG AS FKTABLE_CAT, CHILD_TABLE.TABLE_SCHEMA AS FKTABLE_SCHEM, + CHILD_TABLE.TABLE_NAME AS FKTABLE_NAME, PARENT_INDEX_COLUMNS.COLUMN_NAME AS FKCOLUMN_NAME, PARENT_INDEX_COLUMNS.ORDINAL_POSITION AS KEY_SEQ, + 3 AS UPDATE_RULE, + CASE WHEN CHILD_TABLE.ON_DELETE_ACTION='CASCADE' THEN 0 ELSE 3 END AS DELETE_RULE, + NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, 7 AS DEFERRABILITY - FROM INFORMATION_SCHEMA.INDEX_COLUMNS PARENT - INNER JOIN INFORMATION_SCHEMA.INDEXES PARENT_INDEX ON PARENT.INDEX_NAME=PARENT_INDEX.INDEX_NAME AND PARENT.TABLE_NAME=PARENT_INDEX.TABLE_NAME AND PARENT.TABLE_SCHEMA=PARENT_INDEX.TABLE_SCHEMA AND PARENT.TABLE_CATALOG=PARENT_INDEX.TABLE_CATALOG AND PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' - INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS CHILD ON NOT PARENT.TABLE_NAME=CHILD.TABLE_NAME AND PARENT.COLUMN_NAME=CHILD.COLUMN_NAME - INNER JOIN INFORMATION_SCHEMA.INDEXES CHILD_INDEX ON CHILD.INDEX_NAME=CHILD_INDEX.INDEX_NAME AND CHILD.TABLE_NAME=CHILD_INDEX.TABLE_NAME AND CHILD.TABLE_SCHEMA=CHILD_INDEX.TABLE_SCHEMA AND CHILD.TABLE_CATALOG=CHILD_INDEX.TABLE_CATALOG AND CHILD_INDEX.INDEX_TYPE='PRIMARY_KEY' - INNER JOIN INFORMATION_SCHEMA.TABLES ON CHILD.TABLE_CATALOG=TABLES.TABLE_CATALOG AND CHILD.TABLE_SCHEMA=TABLES.TABLE_SCHEMA AND CHILD.TABLE_NAME=TABLES.TABLE_NAME AND PARENT.TABLE_NAME=TABLES.PARENT_TABLE_NAME - WHERE PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' AND CHILD.ORDINAL_POSITION IS NOT NULL + FROM INFORMATION_SCHEMA.TABLES PARENT_TABLE + INNER JOIN INFORMATION_SCHEMA.INDEXES PARENT_INDEX ON + PARENT_INDEX.TABLE_NAME=PARENT_TABLE.TABLE_NAME + AND PARENT_INDEX.TABLE_SCHEMA=PARENT_TABLE.TABLE_SCHEMA + AND PARENT_INDEX.TABLE_CATALOG=PARENT_TABLE.TABLE_CATALOG + AND PARENT_INDEX.INDEX_TYPE='PRIMARY_KEY' + INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON + PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT_INDEX.TABLE_NAME + AND PARENT_INDEX_COLUMNS.TABLE_SCHEMA=PARENT_INDEX.TABLE_SCHEMA + AND PARENT_INDEX_COLUMNS.TABLE_CATALOG=PARENT_INDEX.TABLE_CATALOG + AND PARENT_INDEX_COLUMNS.INDEX_NAME=PARENT_INDEX.INDEX_NAME + INNER JOIN INFORMATION_SCHEMA.TABLES CHILD_TABLE ON + CHILD_TABLE.PARENT_TABLE_NAME=PARENT_TABLE.TABLE_NAME + AND CHILD_TABLE.TABLE_SCHEMA=PARENT_TABLE.TABLE_SCHEMA + AND CHILD_TABLE.TABLE_CATALOG=PARENT_TABLE.TABLE_CATALOG UNION ALL @@ -36,8 +47,15 @@ FROM ( 3 AS DELETE_RULE, CONSTRAINTS.CONSTRAINT_NAME AS FK_NAME, CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS PK_NAME, 7 AS DEFERRABILITY FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON + CONSTRAINTS.CONSTRAINT_CATALOG=CHILD.CONSTRAINT_CATALOG + AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA + AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON + CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG=PARENT.CONSTRAINT_CATALOG + AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA + AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME + AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT ) AS CROSS_REF WHERE UPPER(PKTABLE_CAT) LIKE ? AND UPPER(PKTABLE_SCHEM) LIKE ? diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql index 631886d710ed..2eb4e606f96b 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetExportedKeys.sql @@ -26,10 +26,15 @@ FROM ( NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.TABLES PARENT - INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME + INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON + CHILD.TABLE_CATALOG=PARENT.TABLE_CATALOG + AND CHILD.TABLE_SCHEMA=PARENT.TABLE_SCHEMA + AND CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON - PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME - AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' + PARENT_INDEX_COLUMNS.TABLE_CATALOG=PARENT.TABLE_CATALOG + AND PARENT_INDEX_COLUMNS.TABLE_SCHEMA=PARENT.TABLE_SCHEMA + AND PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME + AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' UNION ALL diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql index 50994a55b2a9..3daa6722f73d 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetImportedKeys.sql @@ -26,9 +26,14 @@ FROM ( NULL AS FK_NAME, 'PRIMARY_KEY' AS PK_NAME, 7 AS DEFERRABILITY -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.TABLES PARENT - INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME + INNER JOIN INFORMATION_SCHEMA.TABLES CHILD ON + CHILD.TABLE_CATALOG=PARENT.TABLE_CATALOG + AND CHILD.TABLE_SCHEMA=PARENT.TABLE_SCHEMA + AND CHILD.PARENT_TABLE_NAME=PARENT.TABLE_NAME INNER JOIN INFORMATION_SCHEMA.INDEX_COLUMNS PARENT_INDEX_COLUMNS ON - PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME + PARENT_INDEX_COLUMNS.TABLE_CATALOG=PARENT.TABLE_CATALOG + AND PARENT_INDEX_COLUMNS.TABLE_SCHEMA=PARENT.TABLE_SCHEMA + AND PARENT_INDEX_COLUMNS.TABLE_NAME=PARENT.TABLE_NAME AND PARENT_INDEX_COLUMNS.INDEX_NAME='PRIMARY_KEY' UNION ALL diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql index 33b398dae596..d444404c061a 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetCrossReferences.sql @@ -20,8 +20,15 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC 3 AS "DELETE_RULE", CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON + COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA + AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON + COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA + AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME + AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT WHERE UPPER(COALESCE(PARENT.TABLE_CATALOG, '')) LIKE ? AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? AND UPPER(PARENT.TABLE_NAME) LIKE ? diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql index f2a9fb2f6411..e59a8b81f89d 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetExportedKeys.sql @@ -23,8 +23,15 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON + COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA + AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON + COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA + AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME + AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT WHERE UPPER(COALESCE(PARENT.TABLE_CATALOG, '')) LIKE ? AND UPPER(PARENT.TABLE_SCHEMA) LIKE ? AND UPPER(PARENT.TABLE_NAME) LIKE ? diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql index c921b1c10eb3..fb510a1ce9ea 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetImportedKeys.sql @@ -23,8 +23,15 @@ SELECT PARENT.TABLE_CATALOG AS "PKTABLE_CAT", PARENT.TABLE_SCHEMA AS "PKTABLE_SC CONSTRAINTS.CONSTRAINT_NAME AS "FK_NAME", CONSTRAINTS.UNIQUE_CONSTRAINT_NAME AS "PK_NAME", 7 AS "DEFERRABILITY" -- 7 = importedKeyNotDeferrable FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS CONSTRAINTS - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME - INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CHILD ON + COALESCE(CONSTRAINTS.CONSTRAINT_CATALOG, '')=COALESCE(CHILD.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.CONSTRAINT_SCHEMA= CHILD.CONSTRAINT_SCHEMA + AND CONSTRAINTS.CONSTRAINT_NAME= CHILD.CONSTRAINT_NAME + INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE PARENT ON + COALESCE(CONSTRAINTS.UNIQUE_CONSTRAINT_CATALOG, '')=COALESCE(PARENT.CONSTRAINT_CATALOG, '') + AND CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA=PARENT.CONSTRAINT_SCHEMA + AND CONSTRAINTS.UNIQUE_CONSTRAINT_NAME=PARENT.CONSTRAINT_NAME + AND PARENT.ORDINAL_POSITION=CHILD.POSITION_IN_UNIQUE_CONSTRAINT WHERE UPPER(COALESCE(CHILD.TABLE_CATALOG, '')) LIKE ? AND UPPER(CHILD.TABLE_SCHEMA) LIKE ? AND UPPER(CHILD.TABLE_NAME) LIKE ? From 0594869c987dd88e9dc97e87ce736f415aba4531 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:56:15 +0000 Subject: [PATCH 1139/1979] chore(main): release 2.15.1 (#1456) :robot: I have created a release *beep* *boop* --- ## [2.15.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.15.0...v2.15.1) (2024-01-09) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.21.0 ([#1454](https://togithub.com/googleapis/java-spanner-jdbc/issues/1454)) ([aab9ac9](https://togithub.com/googleapis/java-spanner-jdbc/commit/aab9ac9b98c4dc8eb9c0e32aeecef678dce29f92)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.56.0 ([#1455](https://togithub.com/googleapis/java-spanner-jdbc/issues/1455)) ([0a848d4](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a848d4913689319a0951722fb0d59bec36d1be6)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1f9540e33c15..1a2b89a29989 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.15.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.0...v2.15.1) (2024-01-09) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.21.0 ([#1454](https://github.com/googleapis/java-spanner-jdbc/issues/1454)) ([d1c1d2c](https://github.com/googleapis/java-spanner-jdbc/commit/d1c1d2cf1ad86d987fc285eb97d9b9ca3c53f753)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.56.0 ([#1455](https://github.com/googleapis/java-spanner-jdbc/issues/1455)) ([90fad38](https://github.com/googleapis/java-spanner-jdbc/commit/90fad3870fb3b704d041d1a79f2e8fc6f32631d1)) + ## [2.15.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.14.6...v2.15.0) (2023-12-22) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index da134382f765..5d24c02fa9b6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.1-SNAPSHOT + 2.15.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9bb5c7c21071..fa91392b9b9b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.1-SNAPSHOT + 2.15.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index dc2b8656016f..ad65a178bc83 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.0:2.15.1-SNAPSHOT +google-cloud-spanner-jdbc:2.15.1:2.15.1 From dd5cae119dcdf2b3b7afbbbe9a4c386754c4f536 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:06:18 +0000 Subject: [PATCH 1140/1979] chore(main): release 2.15.2-SNAPSHOT (#1457) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5d24c02fa9b6..cb25571e86c1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.1 + 2.15.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fa91392b9b9b..a2fe5daa0a1c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.1 + 2.15.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ad65a178bc83..1378e8c75de3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.1:2.15.1 +google-cloud-spanner-jdbc:2.15.1:2.15.2-SNAPSHOT From cfae18621ad653925d10021a1f4721f6a38b9efc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 9 Jan 2024 17:14:16 +0100 Subject: [PATCH 1141/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.1 (#1458) 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.15.0` -> `2.15.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.15.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.15.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.15.0/2.15.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.15.0/2.15.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes

    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.15.1`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2151-2024-01-09) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.15.0...v2.15.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.21.0 ([#​1454](https://togithub.com/googleapis/java-spanner-jdbc/issues/1454)) ([aab9ac9](https://togithub.com/googleapis/java-spanner-jdbc/commit/aab9ac9b98c4dc8eb9c0e32aeecef678dce29f92)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.56.0 ([#​1455](https://togithub.com/googleapis/java-spanner-jdbc/issues/1455)) ([0a848d4](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a848d4913689319a0951722fb0d59bec36d1be6))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d09f8550309a..cf689afa07a1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.0 + 2.15.1 From 580a89448c1720c8ecb1f98dccea1959bb8db00d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 19 Jan 2024 11:42:25 +0100 Subject: [PATCH 1142/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.22.0 (#1463) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cb25571e86c1..fd7d250bbb7c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.21.0 + 3.22.0 pom import From 4c3240a7119e2a55ca1db9b553d982f4ae6cef9c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 19 Jan 2024 11:42:51 +0100 Subject: [PATCH 1143/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.22 (#1460) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index cf500a9efdd3..a46015bf0da7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -87,7 +87,7 @@ com.spotify.fmt fmt-maven-plugin - 2.21.1 + 2.22 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 28342f9ae7f1..e57f6370f627 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -97,7 +97,7 @@ com.spotify.fmt fmt-maven-plugin - 2.21.1 + 2.22 From 75233acf55a599db0e0afca20b03917809649a9d Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:56:00 -0500 Subject: [PATCH 1144/1979] chore: Create renovate_config_check.yaml (#1920) (#1468) * chore: Create renovate_config_check.yaml Source-Link: https://github.com/googleapis/synthtool/commit/6612ab8f3afcd5e292aecd647f0fa68812c9f5b5 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:a6aa751984f1e905c3ae5a3aac78fc7b68210626ce91487dc7ff4f0a06f010cc Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 6 ++--- .../workflows/renovate_config_check.yaml | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/renovate_config_check.yaml diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index f56920557239..dc05a72762fe 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.github/.OwlBot.lock.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 Google LLC +# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,5 +13,5 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:81f75d962cd28b7ad10740a643b8069b8fa0357cb495b782eef8560bb7a8fd65 -# created: 2023-12-05T19:16:19.735195992Z + digest: sha256:a6aa751984f1e905c3ae5a3aac78fc7b68210626ce91487dc7ff4f0a06f010cc +# created: 2024-01-22T14:14:20.913785597Z diff --git a/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml b/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml new file mode 100644 index 000000000000..87d8eb2be8cd --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml @@ -0,0 +1,25 @@ +name: Renovate Bot Config Validation + +on: + pull_request: + paths: + - 'renovate.json' + +jobs: + renovate_bot_config_validation: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install Renovate and Config Validator + run: | + npm install -g npm@latest + npm install --global renovate + renovate-config-validator From 5da2255dc8c581a99afc103e9333b6d02b486acb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Jan 2024 18:09:17 +0100 Subject: [PATCH 1145/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.22.1 (#1467) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a46015bf0da7..e6baa669e741 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -87,7 +87,7 @@ com.spotify.fmt fmt-maven-plugin - 2.22 + 2.22.1 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index e57f6370f627..e8e97ed09289 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -97,7 +97,7 @@ com.spotify.fmt fmt-maven-plugin - 2.22 + 2.22.1 From a233911216bdd125e57fc7c503eafca1444969c5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Jan 2024 18:09:37 +0100 Subject: [PATCH 1146/1979] test(deps): update dependency com.google.truth:truth to v1.3.0 (#1466) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cf689afa07a1..902f2d9eabea 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.2.0 + 1.3.0 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a2fe5daa0a1c..0c744d90ef26 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.2.0 + 1.3.0 test From d420dd8aaffc83f7aad78e661154c57aa7c37a74 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Jan 2024 18:09:54 +0100 Subject: [PATCH 1147/1979] test(deps): update dependency com.google.truth:truth to v1.3.0 (#1465) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd7d250bbb7c..c7eaedc000d4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.2.0 + 1.3.0 4.11.0 2.2 0.31.1 From c0a99c30bd5f23413dc845448f32a41c16e84366 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jan 2024 13:49:32 +0100 Subject: [PATCH 1148/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.23.0 (#1470) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c7eaedc000d4..6b3a2f399796 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.22.0 + 3.23.0 pom import From c6e5056fdd2be31672bdebbd0b2e89e803612ada Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jan 2024 15:26:15 +0100 Subject: [PATCH 1149/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.30.0 (#1461) 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.29.0` -> `26.30.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.29.0/26.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.29.0/26.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.30.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26300-2024-01-16) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.29.0...v26.30.0) ##### Bug Fixes - fix pipeline failure due to bigquery Provided Schema does not match Table. ([#​6344](https://togithub.com/googleapis/java-cloud-bom/issues/6344)) ([17c18f1](https://togithub.com/googleapis/java-cloud-bom/commit/17c18f1ec0c92ba51a77ab8e9f3c6189412ecea2)) - specify artifact_id to replace explicitly. ([#​6361](https://togithub.com/googleapis/java-cloud-bom/issues/6361)) ([6af9a9a](https://togithub.com/googleapis/java-cloud-bom/commit/6af9a9af15011cfbf7c31bd34e6e5f9696c250cc)) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.21.0 ([#​6346](https://togithub.com/googleapis/java-cloud-bom/issues/6346)) ([781e799](https://togithub.com/googleapis/java-cloud-bom/commit/781e799039ca873beda3c99c7a03242b14647a11)) - update dependency com.google.cloud:gapic-libraries-bom to v1.27.0 ([#​6353](https://togithub.com/googleapis/java-cloud-bom/issues/6353)) ([c5e7ae6](https://togithub.com/googleapis/java-cloud-bom/commit/c5e7ae647dc95ad7aa6ff4f19b4ce6f5819ff5b0)) - update dependency com.google.cloud:google-cloud-bigquery to v2.36.0 ([#​6359](https://togithub.com/googleapis/java-cloud-bom/issues/6359)) ([556b376](https://togithub.com/googleapis/java-cloud-bom/commit/556b37682fcb8aa7a32dc47d773cdff6f52dc833)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3 ([#​6362](https://togithub.com/googleapis/java-cloud-bom/issues/6362)) ([1348292](https://togithub.com/googleapis/java-cloud-bom/commit/1348292f331160fb83ccfe49c725d4f2b40048bf)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.31.0 ([#​6363](https://togithub.com/googleapis/java-cloud-bom/issues/6363)) ([99f75c3](https://togithub.com/googleapis/java-cloud-bom/commit/99f75c3f71479441c584dbfdd45070b01ca1cab5)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.18.0 ([#​6349](https://togithub.com/googleapis/java-cloud-bom/issues/6349)) ([f69d56a](https://togithub.com/googleapis/java-cloud-bom/commit/f69d56a629ae0e323246c4ed2a8f1b6cb0a9046f)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.16.0 ([#​6360](https://togithub.com/googleapis/java-cloud-bom/issues/6360)) ([cf89ccb](https://togithub.com/googleapis/java-cloud-bom/commit/cf89ccb52d595ba810c0d870e60b87c2b1b0ccd7)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.16.0 ([#​6365](https://togithub.com/googleapis/java-cloud-bom/issues/6365)) ([b098a81](https://togithub.com/googleapis/java-cloud-bom/commit/b098a818dfe306b31b5de9830c3e197bf05479d8)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.15.15 ([#​6354](https://togithub.com/googleapis/java-cloud-bom/issues/6354)) ([83852bb](https://togithub.com/googleapis/java-cloud-bom/commit/83852bb87bec2fb1fbcbe0e9170393c8f8ca34a0)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.130.30-alpha ([#​6355](https://togithub.com/googleapis/java-cloud-bom/issues/6355)) ([7831500](https://togithub.com/googleapis/java-cloud-bom/commit/78315005e7d749d95e9760dbd42a39b5aeafcb31)) - update dependency com.google.cloud:google-cloud-nio to v0.127.9 ([#​6357](https://togithub.com/googleapis/java-cloud-bom/issues/6357)) ([304150f](https://togithub.com/googleapis/java-cloud-bom/commit/304150faa97cfc8546761b5824596cda976bec18)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.126.0 ([#​6364](https://togithub.com/googleapis/java-cloud-bom/issues/6364)) ([3d70a7a](https://togithub.com/googleapis/java-cloud-bom/commit/3d70a7a454ce86004f7f528a22fd04c7a003b5f7)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.12.20 ([#​6358](https://togithub.com/googleapis/java-cloud-bom/issues/6358)) ([f53ecaf](https://togithub.com/googleapis/java-cloud-bom/commit/f53ecaf78f3ec22a6b618d024adc956acde2bf23)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.56.0 ([#​6348](https://togithub.com/googleapis/java-cloud-bom/issues/6348)) ([7cd9ca4](https://togithub.com/googleapis/java-cloud-bom/commit/7cd9ca4369d1dc72f39be0ead871fa26c652d711)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.1 ([#​6350](https://togithub.com/googleapis/java-cloud-bom/issues/6350)) ([be7b7c6](https://togithub.com/googleapis/java-cloud-bom/commit/be7b7c681bd9086010b095bc7be9071ec423e58e)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.31.0 ([#​6352](https://togithub.com/googleapis/java-cloud-bom/issues/6352)) ([f020678](https://togithub.com/googleapis/java-cloud-bom/commit/f020678993b7f9bce4bae31d3ca04479a2b9fda0)) - update dependency com.google.googlejavaformat:google-java-format to v1.19.2 ([#​6347](https://togithub.com/googleapis/java-cloud-bom/issues/6347)) ([1dc554f](https://togithub.com/googleapis/java-cloud-bom/commit/1dc554f2591d36970f6aad1da155cf5a81453698))
    --- ### 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../cloud/spanner/sample/entities/AbstractEntity.java | 6 ++++-- .../com/google/cloud/spanner/sample/ApplicationTest.java | 7 ++++++- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index df372f26d8cb..95879e083779 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.29.0 + 26.30.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e6baa669e741..a386b74f4069 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.29.0 + 26.30.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java index 4c6d3f2319a8..890816c92d4e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java @@ -17,16 +17,18 @@ package com.google.cloud.spanner.sample.entities; import java.time.OffsetDateTime; +import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; public abstract class AbstractEntity { /** This ID is generated using a (bit-reversed) sequence. */ @Id private Long id; - private OffsetDateTime createdAt; + @CreatedDate private OffsetDateTime createdAt; - private OffsetDateTime updatedAt; + @LastModifiedDate private OffsetDateTime updatedAt; @Override public boolean equals(Object o) { diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java index 726b32cb3106..81b0d4c005f8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -138,6 +138,11 @@ public static void setupQueryResults() { .build()) .collect(Collectors.toList())) .build())); + mockSpanner.putPartialStatementResult( + StatementResult.update( + 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)"), + 1L)); mockSpanner.putPartialStatementResult( StatementResult.update( Statement.of( @@ -747,7 +752,7 @@ public void testRunApplication() { SpringApplication.run(Application.class).close(); assertEquals( - 34, + 37, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() .filter(request -> !request.getSql().equals("SELECT 1")) .count()); diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index e8e97ed09289..6c7fb7e4198a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.29.0 + 26.30.0 import pom From cd01aa75ffad483fc12602b757f81919d19af768 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jan 2024 16:38:04 +0100 Subject: [PATCH 1150/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.2 (#1425) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 6c7fb7e4198a..2d3ee2078eb2 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.5 + 3.2.2 From 5c2ee75da7b892fd154df1ba0c7dd4eeebbe0369 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jan 2024 19:04:15 +0100 Subject: [PATCH 1151/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.1.2 (#1421) 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.5` -> `2023.1.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.data:spring-data-bom/2023.1.2?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.1.2?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.5/2023.1.2?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.5/2023.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-data-bom (org.springframework.data:spring-data-bom) ### [`v2023.1.2`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.2) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.1.1...2023.1.2) ##### :shipit: Participating Modules - [Spring Data BOM 2023.1.2](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.2) - [Spring Data Build 3.2.2](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.2.2) - [Spring Data Cassandra 4.2.2](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.2.2) - [Spring Data Commons 3.2.2](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.2.2) - [Spring Data Couchbase 5.2.2](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.2.2) - [Spring Data Elasticsearch 5.2.2](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.2.2) - [Spring Data JPA 3.2.2](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.2.2) - [Spring Data KeyValue 3.2.2](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.2.2) - [Spring Data LDAP 3.2.2](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.2.2) - [Spring Data MongoDB 4.2.2](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.2.2) - [Spring Data Neo4j 7.2.2](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.2.2) - [Spring Data REST 4.2.2](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.2.2) - [Spring Data Redis 3.2.2](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.2.2) - [Spring Data Relational 3.2.2](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.2.2) ### [`v2023.1.1`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.1) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.1.0...2023.1.1) ##### :shipit: Participating Modules - [Spring Data BOM 2023.1.1](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.1) - [Spring Data Build 3.2.1](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.2.1) - [Spring Data Cassandra 4.2.1](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.2.1) - [Spring Data Commons 3.2.1](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.2.1) - [Spring Data Couchbase 5.2.1](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.2.1) - [Spring Data Elasticsearch 5.2.1](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.2.1) - [Spring Data JPA 3.2.1](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.2.1) - [Spring Data KeyValue 3.2.1](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.2.1) - [Spring Data LDAP 3.2.1](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.2.1) - [Spring Data MongoDB 4.2.1](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.2.1) - [Spring Data Neo4j 7.2.1](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.2.1) - [Spring Data REST 4.2.1](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.2.1) - [Spring Data Redis 3.2.1](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.2.1) - [Spring Data Relational 3.2.1](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.2.1) ##### :hammer: Dependency Upgrades - Upgrade to Maven Wrapper 3.9.6 [#​190](https://togithub.com/spring-projects/spring-data-bom/issues/190) ### [`v2023.1.0`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.0) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.0.8...2023.1.0) ##### :shipit: Participating Modules - [Spring Data BOM 2023.1.0](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.1.0) - [Spring Data Build 3.2.0](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.2.0) - [Spring Data Cassandra 4.2.0](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.2.0) - [Spring Data Commons 3.2.0](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.2.0) - [Spring Data Couchbase 5.2.0](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.2.0) - [Spring Data Elasticsearch 5.2.0](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.2.0) - [Spring Data JPA 3.2.0](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.2.0) - [Spring Data KeyValue 3.2.0](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.2.0) - [Spring Data LDAP 3.2.0](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.2.0) - [Spring Data MongoDB 4.2.0](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.2.0) - [Spring Data Neo4j 7.2.0](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.2.0) - [Spring Data REST 4.2.0](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.2.0) - [Spring Data Redis 3.2.0](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.2.0) - [Spring Data Relational 3.2.0](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.2.0) ##### :hammer: Dependency Upgrades - Upgrade to Maven Wrapper 3.9.5 [#​177](https://togithub.com/spring-projects/spring-data-bom/issues/177) - Upgrade to Maven Wrapper 3.9.4 [#​168](https://togithub.com/spring-projects/spring-data-bom/issues/168) - Upgrade to Maven Wrapper 3.9.3 [#​160](https://togithub.com/spring-projects/spring-data-bom/issues/160) - Upgrade to Maven Wrapper 3.9.2 [#​152](https://togithub.com/spring-projects/spring-data-bom/issues/152) ### [`v2023.0.8`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.8) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.0.7...2023.0.8) ##### :shipit: Participating Modules - [Spring Data BOM 2023.0.8](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.8) - [Spring Data Build 3.1.8](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.1.8) - [Spring Data Cassandra 4.1.8](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.1.8) - [Spring Data Commons 3.1.8](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.1.8) - [Spring Data Couchbase 5.1.8](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.1.8) - [Spring Data Elasticsearch 5.1.8](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.1.8) - [Spring Data JPA 3.1.8](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.1.8) - [Spring Data KeyValue 3.1.8](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.1.8) - [Spring Data LDAP 3.1.8](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.1.8) - [Spring Data MongoDB 4.1.8](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.1.8) - [Spring Data Neo4j 7.1.8](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.1.8) - [Spring Data REST 4.1.8](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.1.8) - [Spring Data Redis 3.1.8](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.1.8) - [Spring Data Relational 3.1.8](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.1.8) ### [`v2023.0.7`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.7) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.0.6...2023.0.7) ##### :shipit: Participating Modules - [Spring Data BOM 2023.0.7](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.7) - [Spring Data Build 3.1.7](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.1.7) - [Spring Data Cassandra 4.1.7](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.1.7) - [Spring Data Commons 3.1.7](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.1.7) - [Spring Data Couchbase 5.1.7](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.1.7) - [Spring Data Elasticsearch 5.1.7](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.1.7) - [Spring Data JPA 3.1.7](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.1.7) - [Spring Data KeyValue 3.1.7](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.1.7) - [Spring Data LDAP 3.1.7](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.1.7) - [Spring Data MongoDB 4.1.7](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.1.7) - [Spring Data Neo4j 7.1.7](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.1.7) - [Spring Data REST 4.1.7](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.1.7) - [Spring Data Redis 3.1.7](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.1.7) - [Spring Data Relational 3.1.7](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.1.7) ##### :hammer: Dependency Upgrades - Upgrade to Maven Wrapper 3.9.6 [#​191](https://togithub.com/spring-projects/spring-data-bom/issues/191) ### [`v2023.0.6`](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.6) [Compare Source](https://togithub.com/spring-projects/spring-data-bom/compare/2023.0.5...2023.0.6) ##### :shipit: Participating Modules - [Spring Data BOM 2023.0.6](https://togithub.com/spring-projects/spring-data-bom/releases/tag/2023.0.6) - [Spring Data Build 3.1.6](https://togithub.com/spring-projects/spring-data-build/releases/tag/3.1.6) - [Spring Data Cassandra 4.1.6](https://togithub.com/spring-projects/spring-data-cassandra/releases/tag/4.1.6) - [Spring Data Commons 3.1.6](https://togithub.com/spring-projects/spring-data-commons/releases/tag/3.1.6) - [Spring Data Couchbase 5.1.6](https://togithub.com/spring-projects/spring-data-couchbase/releases/tag/5.1.6) - [Spring Data Elasticsearch 5.1.6](https://togithub.com/spring-projects/spring-data-elasticsearch/releases/tag/5.1.6) - [Spring Data JPA 3.1.6](https://togithub.com/spring-projects/spring-data-jpa/releases/tag/3.1.6) - [Spring Data KeyValue 3.1.6](https://togithub.com/spring-projects/spring-data-keyvalue/releases/tag/3.1.6) - [Spring Data LDAP 3.1.6](https://togithub.com/spring-projects/spring-data-ldap/releases/tag/3.1.6) - [Spring Data MongoDB 4.1.6](https://togithub.com/spring-projects/spring-data-mongodb/releases/tag/4.1.6) - [Spring Data Neo4j 7.1.6](https://togithub.com/spring-projects/spring-data-neo4j/releases/tag/7.1.6) - [Spring Data REST 4.1.6](https://togithub.com/spring-projects/spring-data-rest/releases/tag/4.1.6) - [Spring Data Redis 3.1.6](https://togithub.com/spring-projects/spring-data-redis/releases/tag/3.1.6) - [Spring Data Relational 3.1.6](https://togithub.com/spring-projects/spring-data-relational/releases/tag/3.1.6)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR 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). --- java-spanner-jdbc/samples/pom.xml | 1 + java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../google/cloud/spanner/sample/entities/AbstractEntity.java | 4 ++++ .../java/com/google/cloud/spanner/sample/entities/Album.java | 2 ++ .../com/google/cloud/spanner/sample/entities/Concert.java | 4 ++++ .../java/com/google/cloud/spanner/sample/entities/Singer.java | 2 ++ .../java/com/google/cloud/spanner/sample/entities/Track.java | 4 ++++ .../java/com/google/cloud/spanner/sample/entities/Venue.java | 4 ++++ java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 9 files changed, 23 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index b31e3d0bdf20..1e8df92bd6c2 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -19,6 +19,7 @@ com.google.cloud.samples shared-configuration 1.2.0 +
    diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a386b74f4069..65d9df89f8f6 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.0.5 + 2023.1.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java index 890816c92d4e..5992f262de5f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java @@ -20,6 +20,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.annotation.PersistenceCreator; public abstract class AbstractEntity { @@ -30,6 +31,9 @@ public abstract class AbstractEntity { @LastModifiedDate private OffsetDateTime updatedAt; + @PersistenceCreator + public AbstractEntity() {} + @Override public boolean equals(Object o) { if (!(o instanceof AbstractEntity)) { diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java index dfde31af2a35..b6b7ac8b01a4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java @@ -18,6 +18,7 @@ import java.math.BigDecimal; import java.time.LocalDate; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.relational.core.mapping.Table; @Table("albums") @@ -33,6 +34,7 @@ public class Album extends AbstractEntity { private Long singerId; + @PersistenceCreator public Album() {} public Album(String title) { diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java index 29f2b6d906ef..1075eed3d503 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.sample.entities; import java.time.OffsetDateTime; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.relational.core.mapping.Table; @Table("concerts") @@ -32,6 +33,9 @@ public class Concert extends AbstractEntity { private OffsetDateTime endTime; + @PersistenceCreator + public Concert() {} + public Concert(Venue venue, Singer singer, String name) { this.venueId = venue.getId(); this.singerId = singer.getId(); diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java index 255459a890a8..4b68f139232a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.sample.entities; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.relational.core.mapping.Table; @@ -31,6 +32,7 @@ public class Singer extends AbstractEntity { private Boolean active; + @PersistenceCreator public Singer() {} public Singer(String firstName, String lastName) { diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java index 268b6e2b51fa..c255a08bc85c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.sample.entities; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Table; @@ -44,6 +45,9 @@ public class Track extends AbstractEntity { private Double sampleRate; + @PersistenceCreator + public Track() {} + public Track(Album album, int trackNumber, String title) { setAlbumId(album.getId()); this.trackNumber = trackNumber; diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java index e7855cd01a36..82dc5973d894 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.sample.entities; +import org.springframework.data.annotation.PersistenceCreator; import org.springframework.data.relational.core.mapping.Table; @Table("venues") @@ -24,6 +25,9 @@ public class Venue extends AbstractEntity { private String description; + @PersistenceCreator + public Venue() {} + public Venue(String name) { this.name = name; } diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 2d3ee2078eb2..5ec71fa2f5fb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.0.5 + 2023.1.2 import pom From 8e06ef58ed32ca185d7d2e4245ad834a0c1a7318 Mon Sep 17 00:00:00 2001 From: Alice <65933803+alicejli@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:16:07 -0500 Subject: [PATCH 1152/1979] chore: remove obsolete release job configs (#1469) * chore: remove obsolete release job configs * remove inadvertent logs file --- .../.kokoro/release/bump_snapshot.cfg | 53 -- .../.kokoro/release/bump_snapshot.sh | 30 -- java-spanner-jdbc/.kokoro/release/common.cfg | 49 -- java-spanner-jdbc/.kokoro/release/common.sh | 50 -- java-spanner-jdbc/.kokoro/release/drop.cfg | 6 - java-spanner-jdbc/.kokoro/release/drop.sh | 32 -- java-spanner-jdbc/.kokoro/release/promote.cfg | 6 - java-spanner-jdbc/.kokoro/release/promote.sh | 34 -- .../.kokoro/release/publish_javadoc.cfg | 23 - .../.kokoro/release/publish_javadoc.sh | 53 -- .../.kokoro/release/publish_javadoc11.cfg | 30 -- .../.kokoro/release/publish_javadoc11.sh | 63 --- .../.kokoro/release/snapshot.cfg | 6 - java-spanner-jdbc/.kokoro/release/snapshot.sh | 33 -- java-spanner-jdbc/.kokoro/release/stage.cfg | 19 - java-spanner-jdbc/.kokoro/release/stage.sh | 47 -- java-spanner-jdbc/.kokoro/requirements.in | 6 - java-spanner-jdbc/.kokoro/requirements.txt | 491 ------------------ java-spanner-jdbc/owlbot.py | 4 +- 19 files changed, 3 insertions(+), 1032 deletions(-) delete mode 100644 java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/bump_snapshot.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/common.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/common.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/drop.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/drop.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/promote.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/promote.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/publish_javadoc.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/snapshot.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/snapshot.sh delete mode 100644 java-spanner-jdbc/.kokoro/release/stage.cfg delete mode 100755 java-spanner-jdbc/.kokoro/release/stage.sh delete mode 100644 java-spanner-jdbc/.kokoro/requirements.in delete mode 100644 java-spanner-jdbc/.kokoro/requirements.txt diff --git a/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg b/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg deleted file mode 100644 index 3dc06f216777..000000000000 --- a/java-spanner-jdbc/.kokoro/release/bump_snapshot.cfg +++ /dev/null @@ -1,53 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh" -} - -# tokens used by release-please to keep an up-to-date release PR. -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-key-release-please" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-token-release-please" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "github-magic-proxy-url-release-please" - } - } -} diff --git a/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh b/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh deleted file mode 100755 index 4d76d4393c67..000000000000 --- a/java-spanner-jdbc/.kokoro/release/bump_snapshot.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# Copyright 2019 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 -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -eo pipefail - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -if [ -f ${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please ]; then - # Groom the snapshot release PR immediately after publishing a release - npx release-please release-pr --token=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-token-release-please \ - --repo-url=googleapis/java-spanner-jdbc \ - --package-name="spanner-jdbc" \ - --api-url=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please \ - --proxy-key=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-key-release-please \ - --snapshot \ - --release-type=java-auth-yoshi -fi diff --git a/java-spanner-jdbc/.kokoro/release/common.cfg b/java-spanner-jdbc/.kokoro/release/common.cfg deleted file mode 100644 index 2ace079c9a1e..000000000000 --- a/java-spanner-jdbc/.kokoro/release/common.cfg +++ /dev/null @@ -1,49 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "java-spanner-jdbc/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 70247 - keyname: "maven-gpg-keyring" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 70247 - keyname: "maven-gpg-passphrase" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 70247 - keyname: "maven-gpg-pubkeyring" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 70247 - keyname: "sonatype-credentials" - } - } -} diff --git a/java-spanner-jdbc/.kokoro/release/common.sh b/java-spanner-jdbc/.kokoro/release/common.sh deleted file mode 100755 index 7f78ee414faf..000000000000 --- a/java-spanner-jdbc/.kokoro/release/common.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -set -eo pipefail - -# Get secrets from keystore and set and environment variables -setup_environment_secrets() { - export GPG_PASSPHRASE=$(cat ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-passphrase) - export GPG_TTY=$(tty) - export GPG_HOMEDIR=/gpg - mkdir $GPG_HOMEDIR - mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-pubkeyring $GPG_HOMEDIR/pubring.gpg - mv ${KOKORO_KEYSTORE_DIR}/70247_maven-gpg-keyring $GPG_HOMEDIR/secring.gpg - export SONATYPE_USERNAME=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f1 -d'|') - export SONATYPE_PASSWORD=$(cat ${KOKORO_KEYSTORE_DIR}/70247_sonatype-credentials | cut -f2 -d'|') -} - -create_settings_xml_file() { - echo " - - - ossrh - ${SONATYPE_USERNAME} - ${SONATYPE_PASSWORD} - - - sonatype-nexus-staging - ${SONATYPE_USERNAME} - ${SONATYPE_PASSWORD} - - - sonatype-nexus-snapshots - ${SONATYPE_USERNAME} - ${SONATYPE_PASSWORD} - - -" > $1 -} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/drop.cfg b/java-spanner-jdbc/.kokoro/release/drop.cfg deleted file mode 100644 index 245e96b4c4ee..000000000000 --- a/java-spanner-jdbc/.kokoro/release/drop.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/drop.sh" -} diff --git a/java-spanner-jdbc/.kokoro/release/drop.sh b/java-spanner-jdbc/.kokoro/release/drop.sh deleted file mode 100755 index 742ec1a88600..000000000000 --- a/java-spanner-jdbc/.kokoro/release/drop.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -set -eo pipefail - -# STAGING_REPOSITORY_ID must be set -if [ -z "${STAGING_REPOSITORY_ID}" ]; then - echo "Missing STAGING_REPOSITORY_ID environment variable" - exit 1 -fi - -source $(dirname "$0")/common.sh -pushd $(dirname "$0")/../../ - -setup_environment_secrets -create_settings_xml_file "settings.xml" - -mvn nexus-staging:drop -B \ - --settings=settings.xml \ - -DstagingRepositoryId=${STAGING_REPOSITORY_ID} diff --git a/java-spanner-jdbc/.kokoro/release/promote.cfg b/java-spanner-jdbc/.kokoro/release/promote.cfg deleted file mode 100644 index 1ee66ee99932..000000000000 --- a/java-spanner-jdbc/.kokoro/release/promote.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/promote.sh" -} diff --git a/java-spanner-jdbc/.kokoro/release/promote.sh b/java-spanner-jdbc/.kokoro/release/promote.sh deleted file mode 100755 index 3cac3d8a97d7..000000000000 --- a/java-spanner-jdbc/.kokoro/release/promote.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -set -eo pipefail - -# STAGING_REPOSITORY_ID must be set -if [ -z "${STAGING_REPOSITORY_ID}" ]; then - echo "Missing STAGING_REPOSITORY_ID environment variable" - exit 1 -fi - -source $(dirname "$0")/common.sh - -pushd $(dirname "$0")/../../ - -setup_environment_secrets -create_settings_xml_file "settings.xml" - -mvn nexus-staging:release -B \ - -DperformRelease=true \ - --settings=settings.xml \ - -DstagingRepositoryId=${STAGING_REPOSITORY_ID} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg deleted file mode 100644 index 8e17cf25b0e5..000000000000 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.cfg +++ /dev/null @@ -1,23 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/doc-templates/" - -env_vars: { - key: "STAGING_BUCKET" - value: "docs-staging" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh" -} - - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "docuploader_service_account" - } - } -} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh deleted file mode 100755 index 54c727bad2e1..000000000000 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# Copyright 2019 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. - -set -eo pipefail - -if [[ -z "${CREDENTIALS}" ]]; then - CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account -fi - -if [[ -z "${STAGING_BUCKET}" ]]; then - echo "Need to set STAGING_BUCKET environment variable" - exit 1 -fi - -# work from the git root directory -pushd $(dirname "$0")/../../ - -# install docuploader package -python3 -m pip install --require-hashes -r .kokoro/requirements.txt - -# compile all packages -mvn clean install -B -q -DskipTests=true - -export NAME=google-cloud-spanner-jdbc -export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) - -# build the docs -mvn site -B -q - -pushd target/site/apidocs - -# create metadata -python3 -m docuploader create-metadata \ - --name ${NAME} \ - --version ${VERSION} \ - --language java - -# upload docs -python3 -m docuploader upload . \ - --credentials ${CREDENTIALS} \ - --staging-bucket ${STAGING_BUCKET} diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg deleted file mode 100644 index 15fdc9840226..000000000000 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.cfg +++ /dev/null @@ -1,30 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# cloud-rad production -env_vars: { - key: "STAGING_BUCKET_V2" - value: "docs-staging-v2" -} - -# Configure the docker image for kokoro-trampoline -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java11" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh" -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "docuploader_service_account" - } - } -} - -# Downloads docfx doclet resource. This will be in ${KOKORO_GFILE_DIR}/ -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/docfx" diff --git a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh b/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh deleted file mode 100755 index 03eff888c7dd..000000000000 --- a/java-spanner-jdbc/.kokoro/release/publish_javadoc11.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# Copyright 2021 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. - -set -eo pipefail - -if [[ -z "${CREDENTIALS}" ]]; then - CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account -fi - -if [[ -z "${STAGING_BUCKET_V2}" ]]; then - echo "Need to set STAGING_BUCKET_V2 environment variable" - exit 1 -fi - -# work from the git root directory -pushd $(dirname "$0")/../../ - -# install docuploader package -python3 -m pip install --require-hashes -r .kokoro/requirements.txt - -# compile all packages -mvn clean install -B -q -DskipTests=true - -export NAME=google-cloud-spanner-jdbc -export VERSION=$(grep ${NAME}: versions.txt | cut -d: -f3) - -# cloud RAD generation -mvn clean javadoc:aggregate -B -q -P docFX -# include CHANGELOG -cp CHANGELOG.md target/docfx-yml/history.md - -pushd target/docfx-yml - -# create metadata -python3 -m docuploader create-metadata \ - --name ${NAME} \ - --version ${VERSION} \ - --xrefs devsite://java/gax \ - --xrefs devsite://java/google-cloud-core \ - --xrefs devsite://java/api-common \ - --xrefs devsite://java/proto-google-common-protos \ - --xrefs devsite://java/google-api-client \ - --xrefs devsite://java/google-http-client \ - --xrefs devsite://java/protobuf \ - --language java - -# upload yml to production bucket -python3 -m docuploader upload . \ - --credentials ${CREDENTIALS} \ - --staging-bucket ${STAGING_BUCKET_V2} \ - --destination-prefix docfx diff --git a/java-spanner-jdbc/.kokoro/release/snapshot.cfg b/java-spanner-jdbc/.kokoro/release/snapshot.cfg deleted file mode 100644 index aa772391f1fa..000000000000 --- a/java-spanner-jdbc/.kokoro/release/snapshot.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/snapshot.sh" -} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/release/snapshot.sh b/java-spanner-jdbc/.kokoro/release/snapshot.sh deleted file mode 100755 index 1f55b77024d8..000000000000 --- a/java-spanner-jdbc/.kokoro/release/snapshot.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# Copyright 2019 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. - -set -eo pipefail - -source $(dirname "$0")/common.sh -MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml -pushd $(dirname "$0")/../../ - -# ensure we're trying to push a snapshot (no-result returns non-zero exit code) -grep SNAPSHOT versions.txt - -setup_environment_secrets -create_settings_xml_file "settings.xml" - -mvn clean deploy -B \ - --settings ${MAVEN_SETTINGS_FILE} \ - -DperformRelease=true \ - -Dgpg.executable=gpg \ - -Dgpg.passphrase=${GPG_PASSPHRASE} \ - -Dgpg.homedir=${GPG_HOMEDIR} diff --git a/java-spanner-jdbc/.kokoro/release/stage.cfg b/java-spanner-jdbc/.kokoro/release/stage.cfg deleted file mode 100644 index edca2bef01e1..000000000000 --- a/java-spanner-jdbc/.kokoro/release/stage.cfg +++ /dev/null @@ -1,19 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-spanner-jdbc/.kokoro/release/stage.sh" -} - -# Need to save the properties file -action { - define_artifacts { - regex: "github/java-spanner-jdbc/target/nexus-staging/staging/*.properties" - strip_prefix: "github/java-spanner-jdbc" - } -} - -env_vars: { - key: "SECRET_MANAGER_KEYS" - value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" -} diff --git a/java-spanner-jdbc/.kokoro/release/stage.sh b/java-spanner-jdbc/.kokoro/release/stage.sh deleted file mode 100755 index 61e714d6ba56..000000000000 --- a/java-spanner-jdbc/.kokoro/release/stage.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -set -eo pipefail - -# Start the releasetool reporter -requirementsFile=$(realpath $(dirname "${BASH_SOURCE[0]}")/../requirements.txt) -python3 -m pip install --require-hashes -r $requirementsFile -python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script - -source $(dirname "$0")/common.sh -source $(dirname "$0")/../common.sh -MAVEN_SETTINGS_FILE=$(realpath $(dirname "$0")/../../)/settings.xml -pushd $(dirname "$0")/../../ - -setup_environment_secrets -create_settings_xml_file "settings.xml" - -# attempt to stage 3 times with exponential backoff (starting with 10 seconds) -retry_with_backoff 3 10 \ - mvn clean deploy -B \ - --settings ${MAVEN_SETTINGS_FILE} \ - -DskipTests=true \ - -Dclirr.skip=true \ - -DperformRelease=true \ - -Dgpg.executable=gpg \ - -Dgpg.passphrase=${GPG_PASSPHRASE} \ - -Dgpg.homedir=${GPG_HOMEDIR} - -if [[ -n "${AUTORELEASE_PR}" ]] -then - mvn nexus-staging:release -B \ - -DperformRelease=true \ - --settings=settings.xml -fi diff --git a/java-spanner-jdbc/.kokoro/requirements.in b/java-spanner-jdbc/.kokoro/requirements.in deleted file mode 100644 index 2092cc741d9c..000000000000 --- a/java-spanner-jdbc/.kokoro/requirements.in +++ /dev/null @@ -1,6 +0,0 @@ -gcp-docuploader -gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x -wheel -setuptools -typing-extensions -click<8.1.0 \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/requirements.txt b/java-spanner-jdbc/.kokoro/requirements.txt deleted file mode 100644 index 445c5c1f0929..000000000000 --- a/java-spanner-jdbc/.kokoro/requirements.txt +++ /dev/null @@ -1,491 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile requirements.in --generate-hashes --upgrade -# -attrs==23.1.0 \ - --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ - --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 - # via gcp-releasetool -cachetools==5.3.1 \ - --hash=sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 \ - --hash=sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b - # via google-auth -certifi==2023.7.22 \ - --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ - --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 - # via requests -cffi==1.15.1 \ - --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ - --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ - --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ - --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ - --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ - --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ - --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ - --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ - --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ - --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ - --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ - --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ - --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ - --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ - --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ - --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ - --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ - --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ - --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ - --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ - --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ - --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ - --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ - --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ - --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ - --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ - --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ - --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ - --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ - --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ - --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ - --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ - --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ - --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ - --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ - --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ - --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ - --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ - --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ - --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ - --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ - --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ - --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ - --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ - --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ - --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ - --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ - --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ - --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ - --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ - --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ - --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ - --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ - --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ - --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ - --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ - --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ - --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ - --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ - --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ - --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ - --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ - --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ - --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 - # via cryptography -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 \ - --hash=sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb - # via - # -r requirements.in - # gcp-docuploader - # gcp-releasetool -colorlog==6.7.0 \ - --hash=sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662 \ - --hash=sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5 - # via gcp-docuploader -cryptography==41.0.6 \ - --hash=sha256:068bc551698c234742c40049e46840843f3d98ad7ce265fd2bd4ec0d11306596 \ - --hash=sha256:0f27acb55a4e77b9be8d550d762b0513ef3fc658cd3eb15110ebbcbd626db12c \ - --hash=sha256:2132d5865eea673fe6712c2ed5fb4fa49dba10768bb4cc798345748380ee3660 \ - --hash=sha256:3288acccef021e3c3c10d58933f44e8602cf04dba96d9796d70d537bb2f4bbc4 \ - --hash=sha256:35f3f288e83c3f6f10752467c48919a7a94b7d88cc00b0668372a0d2ad4f8ead \ - --hash=sha256:398ae1fc711b5eb78e977daa3cbf47cec20f2c08c5da129b7a296055fbb22aed \ - --hash=sha256:422e3e31d63743855e43e5a6fcc8b4acab860f560f9321b0ee6269cc7ed70cc3 \ - --hash=sha256:48783b7e2bef51224020efb61b42704207dde583d7e371ef8fc2a5fb6c0aabc7 \ - --hash=sha256:4d03186af98b1c01a4eda396b137f29e4e3fb0173e30f885e27acec8823c1b09 \ - --hash=sha256:5daeb18e7886a358064a68dbcaf441c036cbdb7da52ae744e7b9207b04d3908c \ - --hash=sha256:60e746b11b937911dc70d164060d28d273e31853bb359e2b2033c9e93e6f3c43 \ - --hash=sha256:742ae5e9a2310e9dade7932f9576606836ed174da3c7d26bc3d3ab4bd49b9f65 \ - --hash=sha256:7e00fb556bda398b99b0da289ce7053639d33b572847181d6483ad89835115f6 \ - --hash=sha256:85abd057699b98fce40b41737afb234fef05c67e116f6f3650782c10862c43da \ - --hash=sha256:8efb2af8d4ba9dbc9c9dd8f04d19a7abb5b49eab1f3694e7b5a16a5fc2856f5c \ - --hash=sha256:ae236bb8760c1e55b7a39b6d4d32d2279bc6c7c8500b7d5a13b6fb9fc97be35b \ - --hash=sha256:afda76d84b053923c27ede5edc1ed7d53e3c9f475ebaf63c68e69f1403c405a8 \ - --hash=sha256:b27a7fd4229abef715e064269d98a7e2909ebf92eb6912a9603c7e14c181928c \ - --hash=sha256:b648fe2a45e426aaee684ddca2632f62ec4613ef362f4d681a9a6283d10e079d \ - --hash=sha256:c5a550dc7a3b50b116323e3d376241829fd326ac47bc195e04eb33a8170902a9 \ - --hash=sha256:da46e2b5df770070412c46f87bac0849b8d685c5f2679771de277a422c7d0b86 \ - --hash=sha256:f39812f70fc5c71a15aa3c97b2bbe213c3f2a460b79bd21c40d033bb34a9bf36 \ - --hash=sha256:ff369dd19e8fe0528b02e8df9f2aeb2479f89b1270d90f96a63500afe9af5cae - # via - # gcp-releasetool - # secretstorage -gcp-docuploader==0.6.5 \ - --hash=sha256:30221d4ac3e5a2b9c69aa52fdbef68cc3f27d0e6d0d90e220fc024584b8d2318 \ - --hash=sha256:b7458ef93f605b9d46a4bf3a8dc1755dad1f31d030c8679edf304e343b347eea - # via -r requirements.in -gcp-releasetool==1.16.0 \ - --hash=sha256:27bf19d2e87aaa884096ff941aa3c592c482be3d6a2bfe6f06afafa6af2353e3 \ - --hash=sha256:a316b197a543fd036209d0caba7a8eb4d236d8e65381c80cbc6d7efaa7606d63 - # via -r requirements.in -google-api-core==2.11.1 \ - --hash=sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a \ - --hash=sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a - # via - # google-cloud-core - # google-cloud-storage -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.3 \ - --hash=sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb \ - --hash=sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863 - # via google-cloud-storage -google-cloud-storage==2.10.0 \ - --hash=sha256:934b31ead5f3994e5360f9ff5750982c5b6b11604dc072bc452c25965e076dc7 \ - --hash=sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7 - # via gcp-docuploader -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.5.0 \ - --hash=sha256:218931e8e2b2a73a58eb354a288e03a0fd5fb1c4583261ac6e4c078666468c93 \ - --hash=sha256:da1bd943e2e114a56d85d6848497ebf9be6a14d3db23e9fc57581e7c3e8170ec - # via google-cloud-storage -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==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 \ - --hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755 - # via - # keyring - # secretstorage -jinja2==3.1.2 \ - --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ - --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 - # via gcp-releasetool -keyring==24.2.0 \ - --hash=sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6 \ - --hash=sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509 - # via gcp-releasetool -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 -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.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 - # googleapis-common-protos -pyasn1==0.5.0 \ - --hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \ - --hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde - # via - # pyasn1-modules - # rsa -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.7.0 \ - --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \ - --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074 - # via gcp-releasetool -pyperclip==1.8.2 \ - --hash=sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57 - # via gcp-releasetool -python-dateutil==2.8.2 \ - --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ - --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 - # via gcp-releasetool -requests==2.31.0 \ - --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ - --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 - # via - # gcp-releasetool - # google-api-core - # google-cloud-storage -rsa==4.9 \ - --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ - --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 - # via google-auth -secretstorage==3.3.3 \ - --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ - --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 - # via keyring -six==1.16.0 \ - --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ - --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 - # via - # gcp-docuploader - # google-auth - # python-dateutil -typing-extensions==4.7.1 \ - --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ - --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 - # via -r requirements.in -urllib3==1.26.18 \ - --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \ - --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0 - # via - # google-auth - # requests -wheel==0.40.0 \ - --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \ - --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247 - # via -r requirements.in -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 diff --git a/java-spanner-jdbc/owlbot.py b/java-spanner-jdbc/owlbot.py index 05f32bb6d596..0403a6558936 100644 --- a/java-spanner-jdbc/owlbot.py +++ b/java-spanner-jdbc/owlbot.py @@ -22,5 +22,7 @@ '.github/sync-repo-settings.yaml', '.github/blunderbuss.yml', '.kokoro/nightly/integration.cfg', - '.kokoro/build.sh' + '.kokoro/build.sh', + '.kokoro/requirements.in', + '.kokoro/requirements.txt' ]) From a505c4cf3f0374f2025e1a745e949f00fe4d7c91 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Jan 2024 09:21:27 +0100 Subject: [PATCH 1153/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.2 (#1424) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 65d9df89f8f6..d7ee99c10326 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.1.5 + 3.2.2 From c7c79aae857fb95145b4561cb5971f8b75e54da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 29 Jan 2024 17:29:26 +0100 Subject: [PATCH 1154/1979] deps: bump Spanner client to 6.57.0 (#1474) Updates the Spanner client to 6.57.0 and modifies some test cases to work with the newest version of the Spanner client. The manual changes other than the dependency update are: 1. The Spanner client now supports PROTO and PROTO ENUM columns. This is also reflected in the RandomResultSetGenerator, which means that the number of columns is increased from 18 to 22. 2. The above addition of PROTO and PROTO ENUM means that the error message changes when you try to get a blob with a wrong column. 3. The newly introduced statement cache must be disabled, as there is a small bug that prevents the first query to include any default query options (e.g. optimizer version). --- java-spanner-jdbc/pom.xml | 2 +- .../main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java | 2 ++ .../cloud/spanner/jdbc/PartitionedQueryMockServerTest.java | 6 +++--- .../google/cloud/spanner/jdbc/PgNumericResultSetTest.java | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6b3a2f399796..02be88331521 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.56.0 + 6.57.0 pom import diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 5df6cf63844d..2042feebbc16 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -191,6 +191,8 @@ public Connection connect(String url, Properties info) throws SQLException { if (matcher.matches()) { // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic // Connection API + // TODO: Remove when statement cache should be enabled by default. + System.setProperty("spanner.statement_cache_size_mb", "0"); String connectionUri = appendPropertiesToUrl(url.substring(5), info); ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build(); JdbcConnection connection = new JdbcConnection(url, options); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index 7e4e74953d48..7144bfa2a8b3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -158,7 +158,7 @@ public void testPartitionedQueryUsingSql() throws SQLException { partitionStatement.setBoolean(1, true); try (ResultSet results = partitionStatement.executeQuery()) { assertNotNull(results.getMetaData()); - assertEquals(18, results.getMetaData().getColumnCount()); + assertEquals(22, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -376,7 +376,7 @@ public void testAutoPartitionMode() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(18, results.getMetaData().getColumnCount()); + assertEquals(22, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -482,7 +482,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(18, results.getMetaData().getColumnCount()); + assertEquals(22, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java index 119897af9c0b..db245402c475 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PgNumericResultSetTest.java @@ -491,7 +491,8 @@ public void testGetBytes() throws Exception { resultSetMatcherFrom(resultSet, ResultSet::getBytes, ResultSet::getBytes); matcher.nextAndAssertError( - IllegalStateException.class, "expected BYTES but was NUMERIC"); + IllegalStateException.class, + "expected one of [[PROTO, BYTES]] but was NUMERIC"); matcher.nextAndAssertEquals(null); } } @@ -600,7 +601,8 @@ public void testGetBlob() throws Exception { resultSetMatcherFrom(resultSet, ResultSet::getBlob, ResultSet::getBlob); matcher.nextAndAssertError( - IllegalStateException.class, "expected BYTES but was NUMERIC"); + IllegalStateException.class, + "expected one of [[PROTO, BYTES]] but was NUMERIC"); matcher.nextAndAssertEquals(null); } } From 54cc267a19a93d7228d513f244b3cccc9486fa5c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:36:33 +0100 Subject: [PATCH 1155/1979] chore(main): release 2.15.2 (#1464) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1a2b89a29989..a0b53563c9ee 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.15.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.1...v2.15.2) (2024-01-29) + + +### Dependencies + +* Bump Spanner client to 6.57.0 ([#1474](https://github.com/googleapis/java-spanner-jdbc/issues/1474)) ([ce5180a](https://github.com/googleapis/java-spanner-jdbc/commit/ce5180a900a6b55bba2d32f401d957f6924f8ea8)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.22.0 ([#1463](https://github.com/googleapis/java-spanner-jdbc/issues/1463)) ([d505321](https://github.com/googleapis/java-spanner-jdbc/commit/d505321ab58f3d597550d9891c11eb7a7f17c536)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.23.0 ([#1470](https://github.com/googleapis/java-spanner-jdbc/issues/1470)) ([58cf2ba](https://github.com/googleapis/java-spanner-jdbc/commit/58cf2baa1a8cecc4f84d60001d288c535e82b66d)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.22 ([#1460](https://github.com/googleapis/java-spanner-jdbc/issues/1460)) ([bbbff2f](https://github.com/googleapis/java-spanner-jdbc/commit/bbbff2ff98a0bc15ea3b5640b767e872f753452c)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.22.1 ([#1467](https://github.com/googleapis/java-spanner-jdbc/issues/1467)) ([449bae5](https://github.com/googleapis/java-spanner-jdbc/commit/449bae5079ce122be711490f8f1009f272082d13)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.2 ([#1424](https://github.com/googleapis/java-spanner-jdbc/issues/1424)) ([e14af90](https://github.com/googleapis/java-spanner-jdbc/commit/e14af9025a64a94cf431cc2d03bcace7eb753b32)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.2 ([#1425](https://github.com/googleapis/java-spanner-jdbc/issues/1425)) ([9ccb04a](https://github.com/googleapis/java-spanner-jdbc/commit/9ccb04afaaf355734e955f82716c94d229b958d3)) +* Update dependency org.springframework.data:spring-data-bom to v2023.1.2 ([#1421](https://github.com/googleapis/java-spanner-jdbc/issues/1421)) ([dc53309](https://github.com/googleapis/java-spanner-jdbc/commit/dc53309d7846e97ffb1ee2e5cdc0e6c13b648049)) + ## [2.15.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.0...v2.15.1) (2024-01-09) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 02be88331521..d231a4c43fec 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.2-SNAPSHOT + 2.15.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0c744d90ef26..82186b7260a5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.2-SNAPSHOT + 2.15.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1378e8c75de3..678a514bc088 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.1:2.15.2-SNAPSHOT +google-cloud-spanner-jdbc:2.15.2:2.15.2 From ce169053dfcd18387ae3348c0a8b6fbde1866cef Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:48:15 +0000 Subject: [PATCH 1156/1979] chore(main): release 2.15.3-SNAPSHOT (#1476) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d231a4c43fec..ca14cf04c6fd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.2 + 2.15.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 82186b7260a5..7bf6b59a122f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.2 + 2.15.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 678a514bc088..8974286afa66 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.2:2.15.2 +google-cloud-spanner-jdbc:2.15.2:2.15.3-SNAPSHOT From 56bce1a5da22cba6dc4b6ba10461b02216741c7b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 Jan 2024 17:32:44 +0100 Subject: [PATCH 1157/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.31.0 (#1478) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 95879e083779..14d53299f2db 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.30.0 + 26.31.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d7ee99c10326..ea05b791bdb2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.30.0 + 26.31.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 5ec71fa2f5fb..a86e50da4d39 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.30.0 + 26.31.0 import pom From d3c98a30462897f2b6f44823a5efe617398e5e36 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 Jan 2024 17:33:12 +0100 Subject: [PATCH 1158/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.2 (#1477) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 902f2d9eabea..b592bc8e6e90 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.1 + 2.15.2 From 971dc41a2be9e347bd4567e78ccfcad058816d08 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Feb 2024 17:26:18 +0100 Subject: [PATCH 1159/1979] test(deps): update dependency com.google.truth:truth to v1.4.0 (#1483) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b592bc8e6e90..ae742ca9faa5 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.3.0 + 1.4.0 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 7bf6b59a122f..054e7d94008c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.3.0 + 1.4.0 test From c3eb6e09a1210cdd1a35d5d5e3dc546f7508c6d0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Feb 2024 17:26:34 +0100 Subject: [PATCH 1160/1979] test(deps): update dependency com.google.truth:truth to v1.4.0 (#1482) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ca14cf04c6fd..b7549f93f8b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.3.0 + 1.4.0 4.11.0 2.2 0.31.1 From 7cb60c198d96f90239059fcd6d712c016d1ab09f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Feb 2024 17:26:53 +0100 Subject: [PATCH 1161/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.24.0 (#1481) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b7549f93f8b5..8fd009c521ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.23.0 + 3.24.0 pom import From d2bc558894df5f1c91bfdbbea091d984c4d496f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 5 Feb 2024 17:27:49 +0100 Subject: [PATCH 1162/1979] chore: only reset dialect result when it has changed (#1471) Only change the dialect result that is returned by the mock server when the dialect has actually changed. This makes the test a bit quicker, as we also don't have to close the SpannerPool after each test. --- .../cloud/spanner/jdbc/SavepointMockServerTest.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java index 2c5d5185def6..f74cff82ff51 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java @@ -43,6 +43,7 @@ import java.sql.SQLException; import java.sql.Savepoint; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; @@ -54,6 +55,8 @@ @RunWith(Parameterized.class) public class SavepointMockServerTest extends AbstractMockServerTest { + private static Dialect currentDialect; + @Parameter public Dialect dialect; @Parameters(name = "dialect = {0}") @@ -63,13 +66,18 @@ public static Object[] data() { @Before public void setupDialect() { - mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + // Only reset the dialect result when it has actually changed. This prevents the SpannerPool + // from being closed after each test, which again makes the test slower. + if (!Objects.equals(this.dialect, currentDialect)) { + currentDialect = this.dialect; + mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + SpannerPool.closeSpannerPool(); + } } @After public void clearRequests() { mockSpanner.clearRequests(); - SpannerPool.closeSpannerPool(); } private String createUrl() { From 701dc62c95f353d78b54412e679e69107e2882b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 5 Feb 2024 17:28:00 +0100 Subject: [PATCH 1163/1979] test: add tests to verify behavior of empty transactions (#1472) --- .../jdbc/TransactionMockServerTest.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java new file mode 100644 index 000000000000..a514995491af --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.spanner.v1.CommitRequest; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class TransactionMockServerTest extends AbstractMockServerTest { + + @AfterClass + public static void closeSpannerPool() { + SpannerPool.closeSpannerPool(); + } + + @After + public void clearRequests() { + mockSpanner.clearRequests(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=false", + getPort(), "proj", "inst", "db"); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testCommittingEmptyTransactionIsNoOp() throws SQLException { + try (Connection connection = createConnection()) { + connection.commit(); + } + + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testCommittingEmptyExplicitTransactionIsNoOp() throws SQLException { + try (Connection connection = createConnection()) { + connection.setAutoCommit(true); + try (Statement statement = connection.createStatement()) { + statement.execute("begin transaction"); + statement.execute("commit"); + } + } + + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testRollingBackEmptyTransactionIsNoOp() throws SQLException { + try (Connection connection = createConnection()) { + connection.rollback(); + } + + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testRollingBackEmptyExplicitTransactionIsNoOp() throws SQLException { + try (Connection connection = createConnection()) { + connection.setAutoCommit(true); + try (Statement statement = connection.createStatement()) { + statement.execute("begin transaction"); + statement.execute("rollback"); + } + } + + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } +} From 28abc5843e227766870e4063ff767e9b478f11e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 6 Feb 2024 14:24:17 +0100 Subject: [PATCH 1164/1979] test: add tag tests (#1445) --- .../spanner/jdbc/SavepointMockServerTest.java | 3 +- .../cloud/spanner/jdbc/TagMockServerTest.java | 209 ++++++++++++++++++ 2 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java index f74cff82ff51..d8b438abb8b5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java @@ -28,7 +28,6 @@ import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.RandomResultSetGenerator; import com.google.cloud.spanner.connection.SavepointSupport; -import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcAbortedDueToConcurrentModificationException; import com.google.common.base.Strings; import com.google.protobuf.AbstractMessage; @@ -83,7 +82,7 @@ public void clearRequests() { private String createUrl() { return String.format( "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=false", - getPort(), "proj", "inst", "db"); + getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); } private Connection createConnection() throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java new file mode 100644 index 000000000000..5c626c0f95e7 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java @@ -0,0 +1,209 @@ +/* + * 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.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +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 TagMockServerTest 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(); + } + + private String getVariablePrefix() { + return dialect == Dialect.POSTGRESQL ? "spanner." : ""; + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=false", + getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testStatementTagForQuery() throws SQLException { + try (Connection connection = createConnection()) { + connection + .createStatement() + .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getRequestTag()); + + // Verify that the tag is cleared after having been used. + mockSpanner.clearRequests(); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("", request.getRequestOptions().getRequestTag()); + } + } + + @Test + public void testTransactionTagForQuery() throws SQLException { + try (Connection connection = createConnection()) { + connection + .createStatement() + .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getTransactionTag()); + + // Verify that the tag is used for the entire transaction. + mockSpanner.clearRequests(); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getTransactionTag()); + + // Verify that committing the transaction will remove the transaction tag. + connection.commit(); + + mockSpanner.clearRequests(); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("", request.getRequestOptions().getTransactionTag()); + } + } + + @Test + public void testStatementTagForBatchDml() throws SQLException { + try (Connection connection = createConnection()) { + connection + .createStatement() + .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); + + try (Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + ExecuteBatchDmlRequest request = + mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getRequestTag()); + + // Verify that the tag is cleared after having been used. + mockSpanner.clearRequests(); + try (Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals("", request.getRequestOptions().getRequestTag()); + } + } + + @Test + public void testTransactionTagForBatchDml() throws SQLException { + try (Connection connection = createConnection()) { + connection + .createStatement() + .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); + + try (Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + ExecuteBatchDmlRequest request = + mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getTransactionTag()); + + // Verify that the tag is used for the entire transaction. + mockSpanner.clearRequests(); + try (Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals("my-tag", request.getRequestOptions().getTransactionTag()); + + // Verify that committing the transaction will remove the transaction tag. + connection.commit(); + mockSpanner.clearRequests(); + try (Statement statement = connection.createStatement()) { + statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_STATEMENT.getSql()); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + request = mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals("", request.getRequestOptions().getTransactionTag()); + } + } +} From e5deb4c8445a6145a8a00886ee01e6ae41257047 Mon Sep 17 00:00:00 2001 From: Joe Wang <106995533+JoeWang1127@users.noreply.github.com> Date: Fri, 9 Feb 2024 07:52:16 +0000 Subject: [PATCH 1165/1979] chore: add an unmanaged dependency check (#1462) --- .../workflows/unmanaged-dependency-check.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml diff --git a/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml new file mode 100644 index 000000000000..4ca518aea539 --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml @@ -0,0 +1,19 @@ +on: + pull_request: +name: Unmanaged dependency check +jobs: + unmanaged_dependency_check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 11 + - name: Install modules + shell: bash + run: .kokoro/build.sh + - name: Unmanaged dependency check + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@unmanaged-dependencies-check-latest + with: + bom-path: pom.xml From 550e135071f66dbb98b075a0d384acd466268172 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Fri, 9 Feb 2024 07:52:32 +0000 Subject: [PATCH 1166/1979] chore: use sdk-platform-java-config to consolidate build configs (#1486) --- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/owlbot.py | 4 +++- java-spanner-jdbc/pom.xml | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index fb5bb678ffcc..90d9a20a085a 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.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.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.24.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 59efee340c53..948177be87f9 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.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.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.24.0" } env_vars: { diff --git a/java-spanner-jdbc/owlbot.py b/java-spanner-jdbc/owlbot.py index 0403a6558936..d470606bff98 100644 --- a/java-spanner-jdbc/owlbot.py +++ b/java-spanner-jdbc/owlbot.py @@ -24,5 +24,7 @@ '.kokoro/nightly/integration.cfg', '.kokoro/build.sh', '.kokoro/requirements.in', - '.kokoro/requirements.txt' + '.kokoro/requirements.txt', + '.kokoro/presubmit/graalvm-native.cfg', + '.kokoro/presubmit/graalvm-native-17.cfg' ]) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8fd009c521ab..b77ffa6db07e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -13,8 +13,8 @@ com.google.cloud - google-cloud-shared-config - 1.7.1 + sdk-platform-java-config + 3.24.0 @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.24.0 + ${google-cloud-shared-dependencies.version} pom import From 1b6b107607e59a0ccc8fc0d037d686b43ecd4c64 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 14:35:14 +0100 Subject: [PATCH 1167/1979] chore(main): release 2.15.3 (#1484) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 8 ++++---- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a0b53563c9ee..1aaad1696740 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.15.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.2...v2.15.3) (2024-02-09) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.24.0 ([#1481](https://github.com/googleapis/java-spanner-jdbc/issues/1481)) ([e3f58d1](https://github.com/googleapis/java-spanner-jdbc/commit/e3f58d1cad8806e120dda99e16536c7bbf837fe4)) + ## [2.15.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.1...v2.15.2) (2024-01-29) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b77ffa6db07e..8b6399c2551c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.3-SNAPSHOT + 2.15.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc @@ -13,8 +13,8 @@ com.google.cloud - sdk-platform-java-config - 3.24.0 + google-cloud-shared-config + 1.7.1 @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - ${google-cloud-shared-dependencies.version} + 3.24.0 pom import diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 054e7d94008c..8e94432ddc91 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.3-SNAPSHOT + 2.15.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8974286afa66..2d6cd468d91e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.2:2.15.3-SNAPSHOT +google-cloud-spanner-jdbc:2.15.3:2.15.3 From 1a3a3cf132de764bbde566201a1deda6c76c85a6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 14:46:43 +0000 Subject: [PATCH 1168/1979] chore(main): release 2.15.4-SNAPSHOT (#1488) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8b6399c2551c..ecaa6a986da9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.3 + 2.15.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8e94432ddc91..b651b6b7c668 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.3 + 2.15.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2d6cd468d91e..2a90830e5f4f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.3:2.15.3 +google-cloud-spanner-jdbc:2.15.3:2.15.4-SNAPSHOT From 8bb70042e8d56f044f3359184911546d89ac9528 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:03:46 -0500 Subject: [PATCH 1169/1979] chore: adjust renovate bot configs to update the sdk-platform-java-config artifact (#1921) (#1480) chore: update renovate bot configs to update the sdk-platform-java-config artifact Source-Link: https://github.com/googleapis/synthtool/commit/d7828c02a5b1aeb8dcf3aa6c55f8fdf407a0156f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:0d1bb26a1a99ae0456176bf891b8490e9aab424a5cb4e4d301d9703c4dc43b58 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/renovate.json | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index dc05a72762fe..bf48c82da143 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:a6aa751984f1e905c3ae5a3aac78fc7b68210626ce91487dc7ff4f0a06f010cc -# created: 2024-01-22T14:14:20.913785597Z + digest: sha256:0d1bb26a1a99ae0456176bf891b8490e9aab424a5cb4e4d301d9703c4dc43b58 +# created: 2024-01-30T19:46:55.029238294Z diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index efe64307fcf3..fe0d0ccdb3f1 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -14,6 +14,17 @@ ".kokoro/requirements.txt", ".github/workflows/**" ], + "customManagers": [ + { + "customType": "regex", + "fileMatch": [ + "^.kokoro/presubmit/graalvm-native.*.cfg$" + ], + "matchStrings": ["value: \"gcr.io/cloud-devrel-public-resources/graalvm.*:(?.*?)\""], + "depNameTemplate": "com.google.cloud:sdk-platform-java-config", + "datasourceTemplate": "maven" + } + ], "packageRules": [ { "packagePatterns": [ From e22529cbf4305ab1c7ad64dbf64cc7350df6f579 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 10 Feb 2024 21:13:25 +0100 Subject: [PATCH 1170/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.58.0 (#1487) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ecaa6a986da9..124b6d4acc44 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.57.0 + 6.58.0 pom import From de6bc9f50440f5472d403d8803b598a83f26b3eb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 10 Feb 2024 21:13:50 +0100 Subject: [PATCH 1171/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.3 (#1489) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ae742ca9faa5..01abf80c9fa9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.2 + 2.15.3 From bded80b066cdacae0e3a303bdc61e62ddd759aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 12 Feb 2024 17:28:20 +0100 Subject: [PATCH 1172/1979] test: verify execution of client side statements (#1473) Verifies that client-side statements can now also be executed using the executeQuery and executeUpdate methods. Replaces #1152 --- .../cloud/spanner/jdbc/JdbcStatement.java | 5 + .../spanner/jdbc/ExecuteMockServerTest.java | 389 ++++++++++++------ 2 files changed, 264 insertions(+), 130 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 60cc3e5cf6df..1db0c4070746 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -153,6 +153,11 @@ private long extractUpdateCountAndClose(com.google.cloud.spanner.ResultSet resul "Result does not contain an update count", Code.FAILED_PRECONDITION); } return updateCount; + } catch (UnsupportedOperationException unsupportedOperationException) { + throw JdbcSqlExceptionFactory.of( + unsupportedOperationException.getMessage(), + Code.FAILED_PRECONDITION, + unsupportedOperationException); } finally { resultSet.close(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index 65a54a89a5a6..d85c4f8a5b03 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -48,6 +48,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Objects; import org.junit.Before; import org.junit.Test; import org.junit.function.ThrowingRunnable; @@ -63,6 +64,7 @@ */ @RunWith(Parameterized.class) public class ExecuteMockServerTest extends AbstractMockServerTest { + private static Dialect currentDialect; @Parameters(name = "dialect = {0}") public static Object[] parameters() { @@ -78,112 +80,123 @@ public static Object[] parameters() { private String dml; private String largeDml; private String dmlReturning; + private String clientSideQuery; + private String clientSideUpdate; @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( - 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(); - 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(largeDml), LARGE_UPDATE_COUNT)); - mockSpanner.putStatementResult( - StatementResult.query( - com.google.cloud.spanner.Statement.of(dmlReturning), - 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()); + // Only register new results if the dialect has changed. + if (!Objects.equals(currentDialect, dialect)) { + 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 *"; + clientSideQuery = + dialect == Dialect.POSTGRESQL ? "show spanner.readonly" : "show variable readonly"; + clientSideUpdate = + dialect == Dialect.POSTGRESQL ? "set spanner.readonly=false" : "set readonly=false"; + + // 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( + 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(); + 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(largeDml), LARGE_UPDATE_COUNT)); + mockSpanner.putStatementResult( + StatementResult.query( + com.google.cloud.spanner.Statement.of(dmlReturning), + 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() { @@ -206,9 +219,13 @@ public void testStatementExecuteQuery() throws SQLException { try (ResultSet resultSet = statement.executeQuery(dmlReturning)) { verifyResultSet(resultSet); } + try (ResultSet resultSet = statement.executeQuery(clientSideQuery)) { + verifyClientSideResultSet(resultSet); + } verifyException(() -> statement.executeQuery(dml)); verifyException(() -> statement.executeQuery(largeDml)); verifyException(() -> statement.executeQuery(DDL)); + verifyException(() -> statement.executeQuery(clientSideUpdate)); } } @@ -218,9 +235,15 @@ public void testStatementExecuteUpdate() throws SQLException { Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml)); assertEquals(0, statement.executeUpdate(DDL)); + + connection.setAutoCommit(false); + assertEquals(0, statement.executeUpdate(clientSideUpdate)); + connection.setAutoCommit(true); + verifyOverflow(() -> statement.executeUpdate(largeDml)); verifyException(() -> statement.executeUpdate(query)); verifyException(() -> statement.executeUpdate(dmlReturning)); + verifyException(() -> statement.executeUpdate(clientSideQuery)); } } @@ -231,9 +254,12 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException // 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)); + assertEquals(0, statement.executeUpdate(clientSideUpdate, 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)); + verifyException(() -> statement.executeUpdate(clientSideQuery, Statement.NO_GENERATED_KEYS)); } } @@ -243,10 +269,15 @@ public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"})); + assertEquals(0, statement.executeUpdate(clientSideUpdate, new String[] {"id"})); + verifyOverflow(() -> statement.executeUpdate(largeDml, new String[] {"id"})); verifyException( () -> statement.executeUpdate(query, new String[] {"id"}), Code.FAILED_PRECONDITION); assertEquals(1, statement.executeUpdate(dmlReturning, new String[] {"id"})); + verifyException( + () -> statement.executeUpdate(clientSideQuery, new String[] {"id"}), + Code.FAILED_PRECONDITION); } } @@ -256,9 +287,11 @@ public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeUpdate(DDL, new int[] {1})); + assertEquals(0, statement.executeUpdate(clientSideUpdate, new int[] {1})); verifyOverflow(() -> statement.executeUpdate(largeDml, new int[] {1})); verifyException(() -> statement.executeUpdate(query, new int[] {1})); verifyException(() -> statement.executeUpdate(dmlReturning, new int[] {1})); + verifyException(() -> statement.executeUpdate(clientSideQuery, new int[] {1})); } } @@ -268,9 +301,11 @@ public void testStatementLargeExecuteUpdate() throws SQLException { Statement statement = connection.createStatement()) { assertEquals(1L, statement.executeLargeUpdate(dml)); assertEquals(0L, statement.executeLargeUpdate(DDL)); + assertEquals(0L, statement.executeLargeUpdate(clientSideUpdate)); assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml)); verifyException(() -> statement.executeLargeUpdate(query)); verifyException(() -> statement.executeLargeUpdate(dmlReturning)); + verifyException(() -> statement.executeLargeUpdate(clientSideQuery)); } } @@ -281,11 +316,14 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep // 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(0, statement.executeLargeUpdate(clientSideUpdate, Statement.NO_GENERATED_KEYS)); assertEquals( LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml, Statement.NO_GENERATED_KEYS)); verifyException(() -> statement.executeLargeUpdate(query, Statement.NO_GENERATED_KEYS)); verifyException( () -> statement.executeLargeUpdate(dmlReturning, Statement.NO_GENERATED_KEYS)); + verifyException( + () -> statement.executeLargeUpdate(clientSideQuery, Statement.NO_GENERATED_KEYS)); } } @@ -295,10 +333,14 @@ public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLExcepti Statement statement = connection.createStatement()) { assertEquals(1, statement.executeLargeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeLargeUpdate(DDL, new String[] {"id"})); + assertEquals(0, statement.executeLargeUpdate(clientSideUpdate, 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(dmlReturning, new String[] {"id"})); + verifyException( + () -> statement.executeLargeUpdate(clientSideQuery, new String[] {"id"}), + Code.FAILED_PRECONDITION); } } @@ -308,9 +350,11 @@ public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLExcep Statement statement = connection.createStatement()) { assertEquals(1, statement.executeLargeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeLargeUpdate(DDL, new int[] {1})); + assertEquals(0, statement.executeLargeUpdate(clientSideUpdate, 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})); + verifyException(() -> statement.executeLargeUpdate(clientSideQuery, new int[] {1})); } } @@ -321,8 +365,11 @@ public void testStatementExecute() throws SQLException { verifyUpdateCount(statement, () -> statement.execute(dml), 1L); verifyUpdateCount(statement, () -> statement.execute(largeDml), LARGE_UPDATE_COUNT); verifyUpdateCount(statement, () -> statement.execute(DDL), Statement.SUCCESS_NO_INFO); + verifyUpdateCount( + statement, () -> statement.execute(clientSideUpdate), Statement.SUCCESS_NO_INFO); verifyResultSet(statement, () -> statement.execute(query)); verifyResultSet(statement, () -> statement.execute(dmlReturning)); + verifyResultSet(statement, () -> statement.execute(clientSideQuery)); } } @@ -340,9 +387,15 @@ public void testStatementExecuteReturnGeneratedKeys() throws SQLException { statement, () -> statement.execute(DDL, Statement.NO_GENERATED_KEYS), Statement.SUCCESS_NO_INFO); + verifyUpdateCount( + statement, + () -> statement.execute(clientSideUpdate, Statement.NO_GENERATED_KEYS), + Statement.SUCCESS_NO_INFO); verifyResultSet(statement, () -> statement.execute(query, Statement.NO_GENERATED_KEYS)); verifyResultSet( statement, () -> statement.execute(dmlReturning, Statement.NO_GENERATED_KEYS)); + verifyResultSet( + statement, () -> statement.execute(clientSideQuery, Statement.NO_GENERATED_KEYS)); } } @@ -355,8 +408,13 @@ public void testStatementExecuteReturnColumnNames() throws SQLException { statement, () -> statement.execute(largeDml, new String[] {"id"}), LARGE_UPDATE_COUNT); verifyUpdateCount( statement, () -> statement.execute(DDL, new String[] {"id"}), Statement.SUCCESS_NO_INFO); + verifyUpdateCount( + statement, + () -> statement.execute(clientSideUpdate, new String[] {"id"}), + Statement.SUCCESS_NO_INFO); verifyResultSet(statement, () -> statement.execute(query, new String[] {"id"})); verifyResultSet(statement, () -> statement.execute(dmlReturning, new String[] {"id"})); + verifyResultSet(statement, () -> statement.execute(clientSideQuery, new String[] {"id"})); } } @@ -369,8 +427,13 @@ public void testStatementExecuteReturnColumnIndexes() throws SQLException { statement, () -> statement.execute(largeDml, new int[] {1}), LARGE_UPDATE_COUNT); verifyUpdateCount( statement, () -> statement.execute(DDL, new int[] {1}), Statement.SUCCESS_NO_INFO); + verifyUpdateCount( + statement, + () -> statement.execute(clientSideUpdate, new int[] {1}), + Statement.SUCCESS_NO_INFO); verifyResultSet(statement, () -> statement.execute(query, new int[] {1})); verifyResultSet(statement, () -> statement.execute(dmlReturning, new int[] {1})); + verifyResultSet(statement, () -> statement.execute(clientSideQuery, new int[] {1})); } } @@ -383,9 +446,13 @@ public void testPreparedStatementExecuteQuery() throws SQLException { try (ResultSet resultSet = connection.prepareStatement(dmlReturning).executeQuery()) { verifyResultSet(resultSet); } + try (ResultSet resultSet = connection.prepareStatement(clientSideQuery).executeQuery()) { + verifyClientSideResultSet(resultSet); + } verifyException(() -> connection.prepareStatement(dml).executeQuery()); verifyException(() -> connection.prepareStatement(largeDml).executeQuery()); verifyException(() -> connection.prepareStatement(DDL).executeQuery()); + verifyException(() -> connection.prepareStatement(clientSideUpdate).executeQuery()); } } @@ -393,13 +460,13 @@ public void testPreparedStatementExecuteQuery() throws SQLException { 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()); + assertEquals(0, connection.prepareStatement(DDL).executeUpdate()); + assertEquals(0, connection.prepareStatement(clientSideUpdate).executeUpdate()); verifyOverflow(() -> connection.prepareStatement(largeDml).executeUpdate()); verifyException(() -> connection.prepareStatement(query).executeUpdate()); verifyException( () -> connection.prepareStatement(dmlReturning).executeUpdate(), Code.INVALID_ARGUMENT); + verifyException(() -> connection.prepareStatement(clientSideQuery).executeUpdate()); } } @@ -409,10 +476,13 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx // 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()); + assertEquals( + 0, connection.prepareStatement(DDL, Statement.NO_GENERATED_KEYS).executeUpdate()); + assertEquals( + 0, + connection + .prepareStatement(clientSideUpdate, Statement.NO_GENERATED_KEYS) + .executeUpdate()); verifyOverflow( () -> connection.prepareStatement(largeDml, Statement.NO_GENERATED_KEYS).executeUpdate()); verifyException( @@ -423,6 +493,11 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx .prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS) .executeUpdate(), Code.INVALID_ARGUMENT); + verifyException( + () -> + connection + .prepareStatement(clientSideQuery, Statement.NO_GENERATED_KEYS) + .executeUpdate()); } } @@ -430,9 +505,9 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx 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()); + assertEquals(0, connection.prepareStatement(DDL, new String[] {"id"}).executeUpdate()); + assertEquals( + 0, connection.prepareStatement(clientSideUpdate, new String[] {"id"}).executeUpdate()); verifyOverflow( () -> connection.prepareStatement(largeDml, new String[] {"id"}).executeUpdate()); verifyException( @@ -440,6 +515,9 @@ public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLExce Code.FAILED_PRECONDITION); assertEquals( 1, connection.prepareStatement(dmlReturning, new String[] {"id"}).executeUpdate()); + verifyException( + () -> connection.prepareStatement(clientSideQuery, new String[] {"id"}).executeUpdate(), + Code.FAILED_PRECONDITION); } } @@ -447,14 +525,15 @@ public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLExce 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()); + assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeUpdate()); + assertEquals(0, connection.prepareStatement(clientSideUpdate, new int[] {1}).executeUpdate()); verifyOverflow(() -> connection.prepareStatement(largeDml, new int[] {1}).executeUpdate()); verifyException(() -> connection.prepareStatement(query, new int[] {1}).executeUpdate()); verifyException( () -> connection.prepareStatement(dmlReturning, new int[] {1}).executeUpdate(), Code.INVALID_ARGUMENT); + verifyException( + () -> connection.prepareStatement(clientSideQuery, new int[] {1}).executeUpdate()); } } @@ -462,14 +541,14 @@ public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLEx 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(0L, connection.prepareStatement(DDL).executeLargeUpdate()); + assertEquals(0L, connection.prepareStatement(clientSideUpdate).executeLargeUpdate()); assertEquals(LARGE_UPDATE_COUNT, connection.prepareStatement(largeDml).executeLargeUpdate()); verifyException(() -> connection.prepareStatement(query).executeLargeUpdate()); verifyException( () -> connection.prepareStatement(dmlReturning).executeLargeUpdate(), Code.INVALID_ARGUMENT); + verifyException(() -> connection.prepareStatement(clientSideQuery).executeLargeUpdate()); } } @@ -479,10 +558,13 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws // 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( + 0, connection.prepareStatement(DDL, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); + assertEquals( + 0, + connection + .prepareStatement(clientSideUpdate, Statement.NO_GENERATED_KEYS) + .executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, connection.prepareStatement(largeDml, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); @@ -495,6 +577,11 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws .prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS) .executeLargeUpdate(), Code.INVALID_ARGUMENT); + verifyException( + () -> + connection + .prepareStatement(clientSideQuery, Statement.NO_GENERATED_KEYS) + .executeLargeUpdate()); } } @@ -502,10 +589,10 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws 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(0, connection.prepareStatement(DDL, new String[] {"id"}).executeLargeUpdate()); + assertEquals( + 0, + connection.prepareStatement(clientSideUpdate, new String[] {"id"}).executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, connection.prepareStatement(largeDml, new String[] {"id"}).executeLargeUpdate()); @@ -514,6 +601,12 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQ Code.FAILED_PRECONDITION); assertEquals( 1L, connection.prepareStatement(dmlReturning, new String[] {"id"}).executeLargeUpdate()); + verifyException( + () -> + connection + .prepareStatement(clientSideQuery, new String[] {"id"}) + .executeLargeUpdate(), + Code.FAILED_PRECONDITION); } } @@ -521,9 +614,9 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQ 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(0, connection.prepareStatement(DDL, new int[] {1}).executeLargeUpdate()); + assertEquals( + 0, connection.prepareStatement(clientSideUpdate, new int[] {1}).executeLargeUpdate()); assertEquals( LARGE_UPDATE_COUNT, connection.prepareStatement(largeDml, new int[] {1}).executeLargeUpdate()); @@ -531,6 +624,8 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws verifyException( () -> connection.prepareStatement(dmlReturning, new int[] {1}).executeLargeUpdate(), Code.INVALID_ARGUMENT); + verifyException( + () -> connection.prepareStatement(clientSideQuery, new int[] {1}).executeLargeUpdate()); } } @@ -542,9 +637,15 @@ public void testPreparedStatementExecute() throws SQLException { connection.prepareStatement(largeDml), PreparedStatement::execute, LARGE_UPDATE_COUNT); verifyPreparedUpdateCount( connection.prepareStatement(DDL), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); + verifyPreparedUpdateCount( + connection.prepareStatement(clientSideUpdate), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); verifyPreparedResultSet(connection.prepareStatement(query), PreparedStatement::execute); verifyPreparedResultSet( connection.prepareStatement(dmlReturning), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(clientSideQuery), PreparedStatement::execute); } } @@ -564,12 +665,19 @@ public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLExceptio connection.prepareStatement(DDL, Statement.NO_GENERATED_KEYS), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); + verifyPreparedUpdateCount( + connection.prepareStatement(clientSideUpdate, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( connection.prepareStatement(query, Statement.NO_GENERATED_KEYS), PreparedStatement::execute); verifyPreparedResultSet( connection.prepareStatement(dmlReturning, Statement.NO_GENERATED_KEYS), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(clientSideQuery, Statement.NO_GENERATED_KEYS), + PreparedStatement::execute); } } @@ -586,11 +694,18 @@ public void testPreparedStatementExecuteReturnColumnNames() throws SQLException connection.prepareStatement(DDL, new String[] {"id"}), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); + verifyPreparedUpdateCount( + connection.prepareStatement(clientSideUpdate, new String[] {"id"}), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( connection.prepareStatement(query, new String[] {"id"}), PreparedStatement::execute); verifyPreparedResultSet( connection.prepareStatement(dmlReturning, new String[] {"id"}), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(clientSideQuery, new String[] {"id"}), + PreparedStatement::execute); } } @@ -607,13 +722,27 @@ public void testPreparedStatementExecuteReturnColumnIndexes() throws SQLExceptio connection.prepareStatement(DDL, new int[] {1}), PreparedStatement::execute, Statement.SUCCESS_NO_INFO); + verifyPreparedUpdateCount( + connection.prepareStatement(clientSideUpdate, new int[] {1}), + PreparedStatement::execute, + Statement.SUCCESS_NO_INFO); verifyPreparedResultSet( connection.prepareStatement(query, new int[] {1}), PreparedStatement::execute); verifyPreparedResultSet( connection.prepareStatement(dmlReturning, new int[] {1}), PreparedStatement::execute); + verifyPreparedResultSet( + connection.prepareStatement(clientSideQuery, new int[] {1}), PreparedStatement::execute); } } + private void verifyClientSideResultSet(ResultSet resultSet) throws SQLException { + assertNotNull(resultSet.getMetaData()); + assertEquals(1, resultSet.getMetaData().getColumnCount()); + assertTrue(resultSet.next()); + assertFalse(resultSet.getBoolean(1)); + assertFalse(resultSet.next()); + } + private void verifyResultSet(ResultSet resultSet) throws SQLException { assertNotNull(resultSet.getMetaData()); assertEquals(2, resultSet.getMetaData().getColumnCount()); From 95ac00b69cbabfcc513e5a3b51be6acc3619c746 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Feb 2024 09:39:12 +0100 Subject: [PATCH 1173/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.32.0 (#1491) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 14d53299f2db..70a8532c602f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.31.0 + 26.32.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ea05b791bdb2..89d2425de7e5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.31.0 + 26.32.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index a86e50da4d39..647713222b85 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.31.0 + 26.32.0 import pom From 04b3ffb566a4d3a5390f0de32f8cb4f8ab9eae56 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Feb 2024 09:39:53 +0100 Subject: [PATCH 1174/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.25.0 (#1492) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 124b6d4acc44..451772f5b899 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.24.0 + 3.25.0 pom import From 834cc654394ed3940978f1e7c5c7b372405b6493 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Feb 2024 09:40:21 +0100 Subject: [PATCH 1175/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.25.0 (#1493) --- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 90d9a20a085a..5e86d37f0769 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.24.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.25.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 948177be87f9..8e8cded782d0 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.24.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.25.0" } env_vars: { From 3df31cc9d73cedefae9d0dbf6f77739d85c55961 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 15 Feb 2024 20:52:16 +0100 Subject: [PATCH 1176/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.59.0 (#1495) 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.58.0` -> `6.59.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.59.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.59.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.58.0/6.59.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.58.0/6.59.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.59.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6590-2024-02-15) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.58.0...v6.59.0) ##### Features - Support public methods to use autogenerated admin clients. ([#​2878](https://togithub.com/googleapis/java-spanner/issues/2878)) ([53bcb3e](https://togithub.com/googleapis/java-spanner/commit/53bcb3eca2e814472c3def24e8e03d47652a8e42)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.25.0 ([#​2888](https://togithub.com/googleapis/java-spanner/issues/2888)) ([8e2da51](https://togithub.com/googleapis/java-spanner/commit/8e2da5126263c7acd134fb7fcfeb590ca190ce8e)) ##### Documentation - README for OpenTelemetry metrics and traces ([#​2880](https://togithub.com/googleapis/java-spanner/issues/2880)) ([c8632f5](https://togithub.com/googleapis/java-spanner/commit/c8632f5b2f462420a8c2a1f4308a68a18a414472)) - Samples and tests for database Admin APIs. ([#​2775](https://togithub.com/googleapis/java-spanner/issues/2775)) ([14ae01c](https://togithub.com/googleapis/java-spanner/commit/14ae01cd82e455a0dc22d7e3bb8c362e541ede12))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 451772f5b899..5020ee4ae13a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.58.0 + 6.59.0 pom import From 33035a3652ad2d362b9bf66b376dd2ba96952b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 15 Feb 2024 21:36:20 +0100 Subject: [PATCH 1177/1979] chore: enable client-side statement cache (#1496) --- .../src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 2042feebbc16..5df6cf63844d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -191,8 +191,6 @@ public Connection connect(String url, Properties info) throws SQLException { if (matcher.matches()) { // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic // Connection API - // TODO: Remove when statement cache should be enabled by default. - System.setProperty("spanner.statement_cache_size_mb", "0"); String connectionUri = appendPropertiesToUrl(url.substring(5), info); ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build(); JdbcConnection connection = new JdbcConnection(url, options); From bc054b187393f90684d04b21b36e624fd7af9d6e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:00:49 +0000 Subject: [PATCH 1178/1979] chore(main): release 2.15.4 (#1490) :robot: I have created a release *beep* *boop* --- ## [2.15.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.15.3...v2.15.4) (2024-02-15) ### Dependencies * Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.25.0 ([#1492](https://togithub.com/googleapis/java-spanner-jdbc/issues/1492)) ([04b3ffb](https://togithub.com/googleapis/java-spanner-jdbc/commit/04b3ffb566a4d3a5390f0de32f8cb4f8ab9eae56)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.58.0 ([#1487](https://togithub.com/googleapis/java-spanner-jdbc/issues/1487)) ([e22529c](https://togithub.com/googleapis/java-spanner-jdbc/commit/e22529cbf4305ab1c7ad64dbf64cc7350df6f579)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.59.0 ([#1495](https://togithub.com/googleapis/java-spanner-jdbc/issues/1495)) ([3df31cc](https://togithub.com/googleapis/java-spanner-jdbc/commit/3df31cc9d73cedefae9d0dbf6f77739d85c55961)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.25.0 ([#1493](https://togithub.com/googleapis/java-spanner-jdbc/issues/1493)) ([834cc65](https://togithub.com/googleapis/java-spanner-jdbc/commit/834cc654394ed3940978f1e7c5c7b372405b6493)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1aaad1696740..bfb7c3d5129a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.15.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.3...v2.15.4) (2024-02-15) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.25.0 ([#1492](https://github.com/googleapis/java-spanner-jdbc/issues/1492)) ([21988ab](https://github.com/googleapis/java-spanner-jdbc/commit/21988ab03ddff378caf536eccf94289bb745434c)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.58.0 ([#1487](https://github.com/googleapis/java-spanner-jdbc/issues/1487)) ([c4889fa](https://github.com/googleapis/java-spanner-jdbc/commit/c4889fa9ba8d9527cd2a54488a06cde7ef94266e)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.59.0 ([#1495](https://github.com/googleapis/java-spanner-jdbc/issues/1495)) ([091170b](https://github.com/googleapis/java-spanner-jdbc/commit/091170b80a4cd95f36eaa8ae7a9d2f6c33f9b862)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.25.0 ([#1493](https://github.com/googleapis/java-spanner-jdbc/issues/1493)) ([0e1694f](https://github.com/googleapis/java-spanner-jdbc/commit/0e1694f573268b6c1c67be2d683afcbbd7cd6c61)) + ## [2.15.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.2...v2.15.3) (2024-02-09) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5020ee4ae13a..a032fe244be5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.4-SNAPSHOT + 2.15.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b651b6b7c668..e2ce188c60a3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.4-SNAPSHOT + 2.15.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2a90830e5f4f..84784f6effc6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.3:2.15.4-SNAPSHOT +google-cloud-spanner-jdbc:2.15.4:2.15.4 From 8410d82b8972f399b63870a1a6f74beba06ab5c9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 22:08:15 +0000 Subject: [PATCH 1179/1979] chore(main): release 2.15.5-SNAPSHOT (#1497) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a032fe244be5..6706a8eb5fd7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.4 + 2.15.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e2ce188c60a3..dd146d2222c7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.4 + 2.15.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 84784f6effc6..1748fda38f9e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.4:2.15.4 +google-cloud-spanner-jdbc:2.15.4:2.15.5-SNAPSHOT From 5adb8fb29355870ffd1ff77909ab8dc967df0089 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Feb 2024 08:45:49 +0100 Subject: [PATCH 1180/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.4 (#1498) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 01abf80c9fa9..93485cd107dd 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.3 + 2.15.4 From c0a67e7337d15669349c8b31228627f79c509ca7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Feb 2024 18:55:30 +0100 Subject: [PATCH 1181/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.1.3 (#1499) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 89d2425de7e5..e88247852431 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.1.2 + 2023.1.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 647713222b85..1de4730c1d2f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.1.2 + 2023.1.3 import pom From 729c7c0cb00207d0fd9706801b12693ec950841c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 17 Feb 2024 14:35:30 +0100 Subject: [PATCH 1182/1979] test(deps): update dependency com.google.truth:truth to v1.4.1 (#1501) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6706a8eb5fd7..7bcb180b6bff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.0 + 1.4.1 4.11.0 2.2 0.31.1 From 1e21913ebfe0179e7e2f1e49e0c7df91719b2e45 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 17 Feb 2024 14:35:49 +0100 Subject: [PATCH 1183/1979] test(deps): update dependency com.google.truth:truth to v1.4.1 (#1502) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 93485cd107dd..5024bca92213 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.0 + 1.4.1 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index dd146d2222c7..14305c33663c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.4.0 + 1.4.1 test From 4c623450c265fd760524815aa33469eb2668092c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 21 Feb 2024 16:06:52 +0100 Subject: [PATCH 1184/1979] deps: update dependency org.postgresql:postgresql to v42.7.2 [security] (#1507) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e88247852431..38351461743b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -52,7 +52,7 @@ org.postgresql postgresql - 42.7.1 + 42.7.2 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 1de4730c1d2f..120b79fa7471 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.7.1 + 42.7.2 From 773aed250b131533b722850dd80f26c890a65489 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 21 Feb 2024 16:08:16 +0100 Subject: [PATCH 1185/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.2 (#1504) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7bcb180b6bff..b42e7b568c7b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -256,7 +256,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.1 + 3.5.2 From f67f7d82b4523623622e31dbe4cc5c74ca37a552 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 21 Feb 2024 16:25:32 +0100 Subject: [PATCH 1186/1979] deps: update dependency org.postgresql:postgresql to v42.7.2 (#1503) From f71e3790e1febdd73ee46f6ad76eaec63987d54e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 21 Feb 2024 17:56:16 +0100 Subject: [PATCH 1187/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.0 (#1508) 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.59.0` -> `6.60.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.60.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.60.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.59.0/6.60.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.59.0/6.60.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.60.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6600-2024-02-21) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.59.0...v6.60.0) ##### Features - Add an API method for reordering firewall policies ([62319f0](https://togithub.com/googleapis/java-spanner/commit/62319f032163c4ad3e8771dd5f92e7b8a086b5ee)) - **spanner:** Add field for multiplexed session in spanner.proto ([62319f0](https://togithub.com/googleapis/java-spanner/commit/62319f032163c4ad3e8771dd5f92e7b8a086b5ee)) - Update TransactionOptions to include new option exclude_txn_from_change_streams ([#​2853](https://togithub.com/googleapis/java-spanner/issues/2853)) ([62319f0](https://togithub.com/googleapis/java-spanner/commit/62319f032163c4ad3e8771dd5f92e7b8a086b5ee)) ##### Bug Fixes - Add ensureDecoded to proto type ([#​2897](https://togithub.com/googleapis/java-spanner/issues/2897)) ([e99b78c](https://togithub.com/googleapis/java-spanner/commit/e99b78c5d810195d368112eed2b185d2d99e62a9)) - **spanner:** Fix write replace used by dataflow template and import export ([#​2901](https://togithub.com/googleapis/java-spanner/issues/2901)) ([64b9042](https://togithub.com/googleapis/java-spanner/commit/64b90429d4fe53f8509a3923e046406b4bc5876a)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-trace to v2.36.0 ([#​2749](https://togithub.com/googleapis/java-spanner/issues/2749)) ([51a348a](https://togithub.com/googleapis/java-spanner/commit/51a348a0c2b84106ea763721bed3420a0d07f30a)) ##### Documentation - Update comments ([62319f0](https://togithub.com/googleapis/java-spanner/commit/62319f032163c4ad3e8771dd5f92e7b8a086b5ee)) - Update the comment regarding eligible SQL shapes for PartitionQuery ([62319f0](https://togithub.com/googleapis/java-spanner/commit/62319f032163c4ad3e8771dd5f92e7b8a086b5ee))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b42e7b568c7b..794b061555f1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.59.0 + 6.60.0 pom import From 655f6f312d45f2539ce974a3b0318ee64cfdeccb Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:06:15 +0000 Subject: [PATCH 1188/1979] chore(main): release 2.15.5 (#1500) :robot: I have created a release *beep* *boop* --- ## [2.15.5](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.15.4...v2.15.5) (2024-02-21) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.0 ([#1508](https://togithub.com/googleapis/java-spanner-jdbc/issues/1508)) ([f71e379](https://togithub.com/googleapis/java-spanner-jdbc/commit/f71e3790e1febdd73ee46f6ad76eaec63987d54e)) * Update dependency org.postgresql:postgresql to v42.7.2 ([#1503](https://togithub.com/googleapis/java-spanner-jdbc/issues/1503)) ([f67f7d8](https://togithub.com/googleapis/java-spanner-jdbc/commit/f67f7d82b4523623622e31dbe4cc5c74ca37a552)) * Update dependency org.postgresql:postgresql to v42.7.2 [security] ([#1507](https://togithub.com/googleapis/java-spanner-jdbc/issues/1507)) ([4c62345](https://togithub.com/googleapis/java-spanner-jdbc/commit/4c623450c265fd760524815aa33469eb2668092c)) * Update dependency org.springframework.data:spring-data-bom to v2023.1.3 ([#1499](https://togithub.com/googleapis/java-spanner-jdbc/issues/1499)) ([c0a67e7](https://togithub.com/googleapis/java-spanner-jdbc/commit/c0a67e7337d15669349c8b31228627f79c509ca7)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index bfb7c3d5129a..d4d5f25814c7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.15.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.4...v2.15.5) (2024-02-21) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.0 ([#1508](https://github.com/googleapis/java-spanner-jdbc/issues/1508)) ([0f7e59c](https://github.com/googleapis/java-spanner-jdbc/commit/0f7e59c7aabdb9fe69fde23f35c5451d19332076)) +* Update dependency org.postgresql:postgresql to v42.7.2 ([#1503](https://github.com/googleapis/java-spanner-jdbc/issues/1503)) ([dd5142f](https://github.com/googleapis/java-spanner-jdbc/commit/dd5142faab667817b9fe6bff7f0388c5e43e7dee)) +* Update dependency org.postgresql:postgresql to v42.7.2 [security] ([#1507](https://github.com/googleapis/java-spanner-jdbc/issues/1507)) ([caacd05](https://github.com/googleapis/java-spanner-jdbc/commit/caacd056f245f1cf57119653627b0c5097730f41)) +* Update dependency org.springframework.data:spring-data-bom to v2023.1.3 ([#1499](https://github.com/googleapis/java-spanner-jdbc/issues/1499)) ([34151b6](https://github.com/googleapis/java-spanner-jdbc/commit/34151b6cae097c97fc49839e2594f5adbd6393c3)) + ## [2.15.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.3...v2.15.4) (2024-02-15) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 794b061555f1..5a43ed346468 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.5-SNAPSHOT + 2.15.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 14305c33663c..9a07ca1f59a4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.5-SNAPSHOT + 2.15.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1748fda38f9e..2c09e8c87bd4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.4:2.15.5-SNAPSHOT +google-cloud-spanner-jdbc:2.15.5:2.15.5 From 5ad61b23a0474495922b2c1732f29c9cacf34c86 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:16:15 +0000 Subject: [PATCH 1189/1979] chore(main): release 2.15.6-SNAPSHOT (#1509) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a43ed346468..1353d760b459 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.5 + 2.15.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9a07ca1f59a4..fe95f8152804 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.5 + 2.15.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2c09e8c87bd4..a6e48e1b81c6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.5:2.15.5 +google-cloud-spanner-jdbc:2.15.5:2.15.6-SNAPSHOT From ad5f94122fdf68212f5ef883fe7eced5199c388d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 22 Feb 2024 08:40:59 +0100 Subject: [PATCH 1190/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.33.0 (#1511) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 70a8532c602f..57231a4c770d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.32.0 + 26.33.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 38351461743b..900b0b2356eb 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.32.0 + 26.33.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 120b79fa7471..ba23fdb7405d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.32.0 + 26.33.0 import pom From 03ebfa3358aa5e00064dd99a486501289c0687a3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 22 Feb 2024 08:42:37 +0100 Subject: [PATCH 1191/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.15.5 (#1510) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5024bca92213..93270ee3bd4c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.4 + 2.15.5 From bd58057bf7a83e95a984de48f99242ca3a9d615c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Feb 2024 12:09:47 +0100 Subject: [PATCH 1192/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.1 (#1514) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1353d760b459..c3941278e007 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.60.0 + 6.60.1 pom import From b76ec9bef2a9aee58e04a2185b4a1fb5c0466bae Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Feb 2024 12:10:06 +0100 Subject: [PATCH 1193/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.3 (#1512) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 900b0b2356eb..6bcfd491db38 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.2.2 + 3.2.3 From 4a63604018be303ef2566489f84549c8d5e12c4d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Feb 2024 12:10:38 +0100 Subject: [PATCH 1194/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.3 (#1513) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index ba23fdb7405d..a32e7a800de4 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.2 + 3.2.3 From 0531d953740db7954e2695a3128bed83f5d133f9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 Feb 2024 20:25:29 +0100 Subject: [PATCH 1195/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.7.2 (#1516) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c3941278e007..5ff725fc1c3e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.7.1 + 1.7.2 From 0fe36aef8b79356e4231090dc6d0b4dc7ca73bd1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 29 Feb 2024 14:42:38 +0100 Subject: [PATCH 1196/1979] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.7.4 (#1517) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5ff725fc1c3e..6d4cef261dc2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.7.2 + 1.7.4 From c4b8005e96eb8812840a399173d5288968161f04 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Mar 2024 07:37:39 +0100 Subject: [PATCH 1197/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.27.0 (#1522) --- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 5e86d37f0769..56db68092d21 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.25.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.27.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 8e8cded782d0..6283184778e7 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.25.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.27.0" } env_vars: { From f40768ed0e1823409d70f124caca4d485fed6567 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Mar 2024 07:37:57 +0100 Subject: [PATCH 1198/1979] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.27.0 (#1521) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6d4cef261dc2..8085d0fd741a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.25.0 + 3.27.0 pom import From a6561153d66a6019f3876f68e2b782cf6ccb02ca Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Mar 2024 19:47:35 +0100 Subject: [PATCH 1199/1979] test(deps): update dependency com.google.truth:truth to v1.4.2 (#1519) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8085d0fd741a..f2e14a6897f6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.1 + 1.4.2 4.11.0 2.2 0.31.1 From 005e412e06ef69c28156289399961d456735757e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Mar 2024 19:47:54 +0100 Subject: [PATCH 1200/1979] test(deps): update dependency com.google.truth:truth to v1.4.2 (#1520) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 93270ee3bd4c..0fabc41fb449 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.1 + 1.4.2 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fe95f8152804..832a1bf1f3f6 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.4.1 + 1.4.2 test From 707186da8f63ca17d121a6a5ec39a8a0ce12ecd7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 5 Mar 2024 11:38:17 +0100 Subject: [PATCH 1201/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.61.0 (#1523) 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.60.1` -> `6.61.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.61.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.61.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.60.1/6.61.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.60.1/6.61.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.61.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6610-2024-03-04) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.60.1...v6.61.0) ##### Features - Support float32 type ([#​2894](https://togithub.com/googleapis/java-spanner/issues/2894)) ([19b7976](https://togithub.com/googleapis/java-spanner/commit/19b79764294e938ad85d02b7c0662db6ec3afeda)) ##### Bug Fixes - Flaky test issue due to AbortedException. ([#​2925](https://togithub.com/googleapis/java-spanner/issues/2925)) ([cd34c1d](https://togithub.com/googleapis/java-spanner/commit/cd34c1d3ae9a5a36f4d5516dcf7c3667a9cf015a)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.27.0 ([#​2935](https://togithub.com/googleapis/java-spanner/issues/2935)) ([f8f835a](https://togithub.com/googleapis/java-spanner/commit/f8f835a9da705605c492e232a58276c39d1d7e6c)) - Update dependency org.json:json to v20240303 ([#​2936](https://togithub.com/googleapis/java-spanner/issues/2936)) ([1d7044e](https://togithub.com/googleapis/java-spanner/commit/1d7044e97d16f5296b7de020cd24b11cbe2a7df0)) ##### Documentation - Samples and tests for backup Admin APIs and overall spanner Admin APIs. ([#​2882](https://togithub.com/googleapis/java-spanner/issues/2882)) ([de13636](https://togithub.com/googleapis/java-spanner/commit/de1363645e03f46deed5be41f90ddfed72766751)) - Update all public documents to use auto-generated admin clients. ([#​2928](https://togithub.com/googleapis/java-spanner/issues/2928)) ([ccb110a](https://togithub.com/googleapis/java-spanner/commit/ccb110ad6835557870933c95cfd76580fd317a16))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- .../cloud/spanner/jdbc/PartitionedQueryMockServerTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f2e14a6897f6..9b9a6fb8a3d1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.60.1 + 6.61.0 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index 7144bfa2a8b3..be5087fe432e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -158,7 +158,7 @@ public void testPartitionedQueryUsingSql() throws SQLException { partitionStatement.setBoolean(1, true); try (ResultSet results = partitionStatement.executeQuery()) { assertNotNull(results.getMetaData()); - assertEquals(22, results.getMetaData().getColumnCount()); + assertEquals(24, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -376,7 +376,7 @@ public void testAutoPartitionMode() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(22, results.getMetaData().getColumnCount()); + assertEquals(24, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -482,7 +482,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(22, results.getMetaData().getColumnCount()); + assertEquals(24, results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; From 1aacb24106bcf615d5aba6511b1f85c6ca132f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 6 Mar 2024 12:09:16 +0100 Subject: [PATCH 1202/1979] chore: remove custom type name implementation (#1525) Remove the custom type name implementation in the JDBC driver and rely on the implementation in the Java client library. --- .../spanner/jdbc/AbstractJdbcWrapper.java | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index b56aed037dfb..86281af0daab 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -71,65 +71,7 @@ static int extractColumnType(Type type) { } static String getSpannerTypeName(Type type, Dialect dialect) { - // TODO: Use com.google.cloud.spanner.Type#getSpannerTypeName() when available. - Preconditions.checkNotNull(type); - switch (type.getCode()) { - case BOOL: - return dialect == Dialect.POSTGRESQL ? "boolean" : "BOOL"; - case BYTES: - return dialect == Dialect.POSTGRESQL ? "bytea" : "BYTES"; - case DATE: - return dialect == Dialect.POSTGRESQL ? "date" : "DATE"; - case FLOAT64: - return dialect == Dialect.POSTGRESQL ? "double precision" : "FLOAT64"; - case INT64: - return dialect == Dialect.POSTGRESQL ? "bigint" : "INT64"; - case NUMERIC: - return "NUMERIC"; - case PG_NUMERIC: - return "numeric"; - case STRING: - return dialect == Dialect.POSTGRESQL ? "character varying" : "STRING"; - case JSON: - return "JSON"; - case PG_JSONB: - return "jsonb"; - case TIMESTAMP: - return dialect == Dialect.POSTGRESQL ? "timestamp with time zone" : "TIMESTAMP"; - case STRUCT: - return "STRUCT"; - case ARRAY: - switch (type.getArrayElementType().getCode()) { - case BOOL: - return dialect == Dialect.POSTGRESQL ? "boolean[]" : "ARRAY"; - case BYTES: - return dialect == Dialect.POSTGRESQL ? "bytea[]" : "ARRAY"; - case DATE: - return dialect == Dialect.POSTGRESQL ? "date[]" : "ARRAY"; - case FLOAT64: - return dialect == Dialect.POSTGRESQL ? "double precision[]" : "ARRAY"; - case INT64: - return dialect == Dialect.POSTGRESQL ? "bigint[]" : "ARRAY"; - case NUMERIC: - return "ARRAY"; - case PG_NUMERIC: - return "numeric[]"; - case STRING: - return dialect == Dialect.POSTGRESQL ? "character varying[]" : "ARRAY"; - case JSON: - return "ARRAY"; - case PG_JSONB: - return "jsonb[]"; - case TIMESTAMP: - return dialect == Dialect.POSTGRESQL - ? "timestamp with time zone[]" - : "ARRAY"; - case STRUCT: - return "ARRAY"; - } - default: - return null; - } + return Preconditions.checkNotNull(type).getSpannerTypeName(dialect); } /** From 65fbc087aff7f4d417ae12cbdf768ea99f3b07c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 6 Mar 2024 18:10:16 +0100 Subject: [PATCH 1203/1979] test: enable integration tests for PG on emulator (#1526) The emulator now supports PostgreSQL, so we can enable the integration tests for PostgreSQL when running on the emulator. This change also changes some of the tests that had workarounds for features that were initially missing in PostgreSQL, such as support for DATE and TIMESTAMPTZ. --- .../spanner/jdbc/it/ITAbstractJdbcTest.java | 7 +- .../spanner/jdbc/it/ITJdbcConnectTest.java | 3 +- .../cloud/spanner/jdbc/it/ITJdbcDdlTest.java | 6 - .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 11 +- .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 16 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 233 ++++++------------ .../jdbc/it/ITJdbcQueryOptionsTest.java | 3 - .../spanner/jdbc/it/ITJdbcReadOnlyTest.java | 5 - .../it/ITJdbcReadWriteAutocommitTest.java | 5 - .../spanner/jdbc/it/ITJdbcScriptTest.java | 18 +- .../jdbc/it/ITJdbcSimpleStatementsTest.java | 4 - .../jdbc/it/ITJdbcSqlMusicScriptTest.java | 6 - .../ITReadWriteAutocommitSpannerTest.sql | 2 +- .../ITScriptTest_TestGetReadTimestamp.sql | 8 +- ...ITSqlScriptTest_TestGetCommitTimestamp.sql | 138 +++++++++++ .../spanner/jdbc/it/CreateMusicTables_PG.sql | 9 +- 16 files changed, 241 insertions(+), 233 deletions(-) create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java index b6fb245c7c66..b2f949e2d208 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; + import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.GceTestEnvConfig; @@ -23,7 +25,6 @@ import com.google.cloud.spanner.connection.ITAbstractSpannerTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import java.nio.file.Files; @@ -116,7 +117,7 @@ static Collection getMusicTablesDdl(Dialect dialect) { default: scriptFile = "CreateMusicTables.sql"; } - if (EmulatorSpannerHelper.isUsingEmulator()) { + if (dialect != Dialect.POSTGRESQL && isUsingEmulator()) { scriptFile = "CreateMusicTables_Emulator.sql"; } return AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, ITAbstractJdbcTest.class) @@ -130,7 +131,7 @@ public Dialect getDialect() { } public String getDefaultCatalog(Database database) { - if (getDialect() == Dialect.POSTGRESQL) { + if (getDialect() == Dialect.POSTGRESQL && !isUsingEmulator()) { return database.getId().getDatabase(); } return ""; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index bf6d2892cacd..17bd657854a0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -73,8 +73,7 @@ private String createBaseUrl() { if (EmulatorSpannerHelper.isUsingEmulator()) { url.append("//").append(System.getenv("SPANNER_EMULATOR_HOST")); } - // Extract "//x.y.googleapis.com" from "https://x.y.googleapis.com" and append it to - // url. + // Extract "//x.y.googleapis.com" from "https://x.y.googleapis.com" and append it to url. if (options.getHost() != null) { url.append(options.getHost().substring(options.getHost().indexOf(':') + 1)); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java index 5273cb4d3bf5..88cffc0bea99 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDdlTest.java @@ -16,13 +16,10 @@ package com.google.cloud.spanner.jdbc.it; -import static org.junit.Assume.assumeFalse; - import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.Collections; @@ -64,9 +61,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index 56d75db1a92d..1b96e9569d5b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -21,12 +21,10 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -35,7 +33,6 @@ import java.util.Arrays; import java.util.List; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; @@ -57,13 +54,6 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; private static final String TABLE_WITH_REF = "TableWithRef"; - @BeforeClass - public static void skipOnEmulator() { - assumeFalse( - "PostgreSQL dialect is not yet supported on the emulator", - EmulatorSpannerHelper.isUsingEmulator()); - } - private Database database; @Before @@ -71,6 +61,7 @@ public void setup() { database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); } + @Override public Dialect getDialect() { return Dialect.POSTGRESQL; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index 57b3e89820a9..5527c8b952c6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -16,10 +16,10 @@ package com.google.cloud.spanner.jdbc.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseAdminClient; @@ -30,7 +30,6 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.cloud.spanner.testing.RemoteSpannerHelper; import java.math.BigDecimal; import java.sql.Connection; @@ -64,8 +63,6 @@ public class ITJdbcPgNumericTest { @BeforeClass public static void setup() throws Exception { - assumeFalse( - "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); testHelper = env.getTestHelper(); final String projectId = testHelper.getInstanceId().getProject(); final String instanceId = testHelper.getInstanceId().getInstance(); @@ -83,6 +80,9 @@ public static void setup() throws Exception { .createDatabase(databaseToCreate, Collections.emptyList()) .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); url = "jdbc:cloudspanner://" + host + "/" + database.getId() + "?dialect=postgresql"; + if (isUsingEmulator()) { + url += ";usePlainText=true"; + } } @AfterClass @@ -95,8 +95,6 @@ public static void teardown() { @Test public void testResultSet() throws SQLException { - assumeFalse( - "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); final String table = testHelper.getUniqueDatabaseId(); final String positiveBigNumeric = String.join("", Collections.nCopies(131072, "1")) @@ -124,7 +122,7 @@ public void testResultSet() throws SQLException { try (Connection connection = DriverManager.getConnection(url); Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table)) { + ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) { resultSet.next(); assertEquals("1.23", resultSet.getString("col1")); @@ -190,8 +188,6 @@ public void testResultSet() throws SQLException { @Test public void testPreparedStatement() throws Exception { - assumeFalse( - "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); final String table = testHelper.getUniqueDatabaseId(); try (Connection connection = DriverManager.getConnection(url); Statement statement = connection.createStatement(); ) { @@ -253,7 +249,7 @@ public void testPreparedStatement() throws Exception { try (Connection connection = DriverManager.getConnection(url); Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table)) { + ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) { resultSet.next(); assertNull(resultSet.getObject("col1")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 8f014937a151..2fb170a98da4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -16,7 +16,6 @@ package com.google.cloud.spanner.jdbc.it; -import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -32,7 +31,6 @@ import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.JsonType; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; @@ -91,9 +89,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); } @@ -137,11 +132,7 @@ private void setPreparedStatement(PreparedStatement ps, Dialect dialect) throws ps.setString(2, this.firstName); ps.setString(3, this.lastName); ps.setBytes(4, this.singerInfo); - if (dialect == Dialect.POSTGRESQL) { - ps.setString(5, this.birthDate.toString()); - } else { - ps.setDate(5, this.birthDate); - } + ps.setDate(5, this.birthDate); } } @@ -253,34 +244,22 @@ private void setPreparedStatement(Connection connection, PreparedStatement ps, D throws SQLException { ps.setLong(1, this.venueId); ps.setLong(2, this.singerId); - if (dialect == Dialect.POSTGRESQL) { - ps.setString(3, this.concertDate.toString()); - ps.setString(4, this.beginTime.toString()); - ps.setString(5, this.endTime.toString()); - } else { - ps.setDate(3, this.concertDate); - ps.setTimestamp(4, this.beginTime); - ps.setTimestamp(5, this.endTime); - ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices)); - } + ps.setDate(3, this.concertDate); + ps.setTimestamp(4, this.beginTime); + ps.setTimestamp(5, this.endTime); + ps.setArray(6, connection.createArrayOf("INT64", this.ticketPrices)); } private void assertEqualsFields(Connection connection, ResultSet rs, Dialect dialect) throws SQLException { assertEquals(rs.getLong(1), this.venueId); assertEquals(rs.getLong(2), this.singerId); - if (dialect == Dialect.POSTGRESQL) { - assertEquals(rs.getString(3), this.concertDate.toString()); - assertEquals(rs.getString(4), this.beginTime.toString()); - assertEquals(rs.getString(5), this.endTime.toString()); - } else { - assertEquals(rs.getDate(3), this.concertDate); - assertEquals(rs.getTimestamp(4), this.beginTime); - assertEquals(rs.getTimestamp(5), this.endTime); - assertArrayEquals( - (Object[]) rs.getArray(6).getArray(), - (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray()); - } + assertEquals(rs.getDate(3), this.concertDate); + assertEquals(rs.getTimestamp(4), this.beginTime); + assertEquals(rs.getTimestamp(5), this.endTime); + assertArrayEquals( + (Object[]) rs.getArray(6).getArray(), + (Object[]) connection.createArrayOf("INT64", this.ticketPrices).getArray()); } } @@ -346,15 +325,12 @@ private List createConcerts() { } private String getConcertsInsertQuery(Dialect dialect) { - if (dialect == Dialect.POSTGRESQL) { - return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?);"; - } return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?);"; } private String getConcertsInsertReturningQuery(Dialect dialect) { if (dialect == Dialect.POSTGRESQL) { - return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime) VALUES (?,?,?,?,?) RETURNING *;"; + return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) RETURNING *;"; } return "INSERT INTO Concerts (VenueId, SingerId, ConcertDate, BeginTime, EndTime, TicketPrices) VALUES (?,?,?,?,?,?) THEN RETURN *;"; } @@ -380,13 +356,6 @@ private String getSongsInsertReturningQuery(Dialect dialect) { return "INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre) VALUES (?,?,?,?,?,?) THEN RETURN *;"; } - private int getConcertExpectedParamCount(Dialect dialect) { - if (dialect == Dialect.POSTGRESQL) { - return 5; - } - return 6; - } - @Test public void test01_InsertTestData() throws SQLException { try (Connection connection = createConnection(env, database)) { @@ -396,24 +365,13 @@ public void test01_InsertTestData() throws SQLException { "INSERT INTO Singers (SingerId, FirstName, LastName, SingerInfo, BirthDate) values (?,?,?,?,?)")) { assertParameterMetaData( ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), dialect.dialect == Dialect.POSTGRESQL ? ImmutableList.of( - Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR) - : ImmutableList.of( - Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - "bigint", - "character varying", - "character varying", - "bytea", - "character varying") + "bigint", "character varying", "character varying", "bytea", "date") : ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - Long.class, String.class, String.class, byte[].class, String.class) - : ImmutableList.of( - Long.class, String.class, String.class, byte[].class, Date.class)); + ImmutableList.of(Long.class, String.class, String.class, byte[].class, Date.class)); for (Singer singer : createSingers()) { singer.setPreparedStatement(ps, getDialect()); assertInsertSingerParameterMetadata(ps.getParameterMetaData()); @@ -487,39 +445,35 @@ public void test01_InsertTestData() throws SQLException { connection.prepareStatement(getConcertsInsertQuery(dialect.dialect))) { assertParameterMetaData( ps.getParameterMetaData(), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR) - : ImmutableList.of( - Types.BIGINT, - Types.BIGINT, - Types.DATE, - Types.TIMESTAMP, - Types.TIMESTAMP, - Types.ARRAY), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), dialect.dialect == Dialect.POSTGRESQL ? ImmutableList.of( "bigint", "bigint", - "character varying", - "character varying", - "character varying") + "date", + "timestamp with time zone", + "timestamp with time zone", + "bigint[]") : ImmutableList.of( "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class) - : ImmutableList.of( - Long.class, - Long.class, - Date.class, - Timestamp.class, - Timestamp.class, - Long[].class)); + ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); for (Concert concert : createConcerts()) { concert.setPreparedStatement(connection, ps, getDialect()); assertInsertConcertParameterMetadata(ps.getParameterMetaData()); assertEquals(1, ps.executeUpdate()); - // check that calling executeUpdate will not reset the meta data + // check that calling executeUpdate will not reset the metadata. assertInsertConcertParameterMetadata(ps.getParameterMetaData()); } } @@ -564,17 +518,10 @@ public void test02_VerifyTestData() throws SQLException { assertTrue(rs.next()); assertEquals(1L, rs.getLong(1)); assertEquals(1L, rs.getLong(2)); - if (dialect.dialect == Dialect.POSTGRESQL) { - assertEquals("2003-06-19", rs.getString(3)); - assertEquals("2003-06-19 12:30:05.0", rs.getString(4)); - assertEquals("2003-06-19 18:57:15.0", rs.getString(5)); - } else { - assertEquals(Date.valueOf("2003-06-19"), rs.getDate(3)); - assertEquals(Timestamp.valueOf("2003-06-19 12:30:05"), rs.getTimestamp(4)); - assertEquals(Timestamp.valueOf("2003-06-19 18:57:15"), rs.getTimestamp(5)); - assertArrayEquals( - new Long[] {11L, 93L, 140L, 923L}, (Long[]) rs.getArray(6).getArray()); - } + assertEquals(Date.valueOf("2003-06-19"), rs.getDate(3)); + assertEquals(Timestamp.valueOf("2003-06-19 12:30:05"), rs.getTimestamp(4)); + assertEquals(Timestamp.valueOf("2003-06-19 18:57:15"), rs.getTimestamp(5)); + assertArrayEquals(new Long[] {11L, 93L, 140L, 923L}, (Long[]) rs.getArray(6).getArray()); } } } @@ -583,8 +530,6 @@ public void test02_VerifyTestData() throws SQLException { @SuppressWarnings("deprecation") @Test public void test03_Dates() throws SQLException { - assumeFalse( - "Date type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); List expectedValues = new ArrayList<>(); expectedValues.add("2008-01-01"); expectedValues.add("2000-01-01"); @@ -645,8 +590,16 @@ public void test03_Dates() throws SQLException { Types.TIMESTAMP, Types.TIMESTAMP, Types.ARRAY), - ImmutableList.of( - "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "date", + "timestamp with time zone", + "timestamp with time zone", + "bigint[]") + : ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), ImmutableList.of( Long.class, Long.class, @@ -1140,7 +1093,6 @@ public void test09_MetaData_FromQuery() throws SQLException { assumeFalse( "TableWithAllColumnTypes type is not supported on POSTGRESQL dialect", dialect.dialect == Dialect.POSTGRESQL); - assumeFalse("The emulator does not support PLAN mode", isUsingEmulator()); try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { @@ -1341,9 +1293,6 @@ private void assertParameterMetaData( @Test public void test12_InsertReturningTestData() throws SQLException { - assumeFalse( - "Emulator does not support DML with returning clause", - EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection(env, database)) { connection.setAutoCommit(false); // Delete existing rows from tables populated by other tests, @@ -1358,24 +1307,13 @@ public void test12_InsertReturningTestData() throws SQLException { connection.prepareStatement(getSingersInsertReturningQuery(dialect.dialect))) { assertParameterMetaData( ps.getParameterMetaData(), + ImmutableList.of( + Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), dialect.dialect == Dialect.POSTGRESQL ? ImmutableList.of( - Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.NVARCHAR) - : ImmutableList.of( - Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.BINARY, Types.DATE), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - "bigint", - "character varying", - "character varying", - "bytea", - "character varying") + "bigint", "character varying", "character varying", "bytea", "date") : ImmutableList.of("INT64", "STRING", "STRING", "BYTES", "DATE"), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - Long.class, String.class, String.class, byte[].class, String.class) - : ImmutableList.of( - Long.class, String.class, String.class, byte[].class, Date.class)); + ImmutableList.of(Long.class, String.class, String.class, byte[].class, Date.class)); for (Singer singer : createSingers()) { singer.setPreparedStatement(ps, getDialect()); assertInsertSingerParameterMetadata(ps.getParameterMetaData()); @@ -1465,34 +1403,30 @@ public void test12_InsertReturningTestData() throws SQLException { connection.prepareStatement(getConcertsInsertReturningQuery(dialect.dialect))) { assertParameterMetaData( ps.getParameterMetaData(), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of( - Types.BIGINT, Types.BIGINT, Types.NVARCHAR, Types.NVARCHAR, Types.NVARCHAR) - : ImmutableList.of( - Types.BIGINT, - Types.BIGINT, - Types.DATE, - Types.TIMESTAMP, - Types.TIMESTAMP, - Types.ARRAY), + ImmutableList.of( + Types.BIGINT, + Types.BIGINT, + Types.DATE, + Types.TIMESTAMP, + Types.TIMESTAMP, + Types.ARRAY), dialect.dialect == Dialect.POSTGRESQL ? ImmutableList.of( "bigint", "bigint", - "character varying", - "character varying", - "character varying") + "date", + "timestamp with time zone", + "timestamp with time zone", + "bigint[]") : ImmutableList.of( "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), - dialect.dialect == Dialect.POSTGRESQL - ? ImmutableList.of(Long.class, Long.class, String.class, String.class, String.class) - : ImmutableList.of( - Long.class, - Long.class, - Date.class, - Timestamp.class, - Timestamp.class, - Long[].class)); + ImmutableList.of( + Long.class, + Long.class, + Date.class, + Timestamp.class, + Timestamp.class, + Long[].class)); for (Concert concert : createConcerts()) { concert.setPreparedStatement(connection, ps, getDialect()); assertInsertConcertParameterMetadata(ps.getParameterMetaData()); @@ -1500,7 +1434,7 @@ public void test12_InsertReturningTestData() throws SQLException { rs.next(); concert.assertEqualsFields(connection, rs, dialect.dialect); } - // check that calling executeQuery will not reset the meta data + // check that calling executeQuery will not reset the metadata. assertInsertConcertParameterMetadata(ps.getParameterMetaData()); } } @@ -1569,11 +1503,7 @@ private void assertInsertSingerParameterMetadata(ParameterMetaData pmd) throws S assertStringParam(pmd, 2); assertStringParam(pmd, 3); assertBytesParam(pmd, 4); - if (dialect.dialect == Dialect.POSTGRESQL) { - assertStringParam(pmd, 5); - } else { - assertDateParam(pmd, 5); - } + assertDateParam(pmd, 5); } private void assertInsertAlbumParameterMetadata(ParameterMetaData pmd) throws SQLException { @@ -1595,20 +1525,13 @@ private void assertInsertSongParameterMetadata(ParameterMetaData pmd) throws SQL } private void assertInsertConcertParameterMetadata(ParameterMetaData pmd) throws SQLException { - int expectedParamCount = getConcertExpectedParamCount(getDialect()); - assertEquals(expectedParamCount, pmd.getParameterCount()); + assertEquals(6, pmd.getParameterCount()); assertLongParam(pmd, 1); assertLongParam(pmd, 2); - if (dialect.dialect == Dialect.POSTGRESQL) { - assertStringParam(pmd, 3); - assertStringParam(pmd, 4); - assertStringParam(pmd, 5); - } else { - assertDateParam(pmd, 3); - assertTimestampParam(pmd, 4); - assertTimestampParam(pmd, 5); - assertLongArrayParam(pmd, 6); - } + assertDateParam(pmd, 3); + assertTimestampParam(pmd, 4); + assertTimestampParam(pmd, 5); + assertLongArrayParam(pmd, 6); } private void assertLongParam(ParameterMetaData pmd, int param) throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java index 46251ac9e28d..737a76880ff6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcQueryOptionsTest.java @@ -99,9 +99,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java index 7e13532c9d6e..f70e025bc32c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadOnlyTest.java @@ -17,7 +17,6 @@ package com.google.cloud.spanner.jdbc.it; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; @@ -26,7 +25,6 @@ import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.math.BigInteger; import java.sql.Connection; @@ -85,9 +83,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 7076563b3f14..525ccbbe13ba 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -19,7 +19,6 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; @@ -27,7 +26,6 @@ import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.List; @@ -69,9 +67,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), getTestTableDdl(getDialect())); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java index a6e44358e4a7..8d8c0ffa0120 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java @@ -90,6 +90,8 @@ public class ITJdbcScriptTest extends ITAbstractJdbcTest { "PostgreSQL/ITScriptTest_InsertTestData.sql"; private static final String TEST_GET_READ_TIMESTAMP_PG = "PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql"; + private static final String TEST_GET_COMMIT_TIMESTAMP_PG = + "PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql"; private static final String TEST_TEMPORARY_TRANSACTIONS_PG = "PostgreSQL/ITScriptTest_TestTemporaryTransactions.sql"; private static final String TEST_TRANSACTION_MODE_PG = @@ -138,6 +140,7 @@ public static List data() { postgresScripts.put("CREATE_TABLES_FILE", CREATE_TABLES_FILE_PG); postgresScripts.put("INSERT_AND_VERIFY_TEST_DATA", INSERT_AND_VERIFY_TEST_DATA_PG); postgresScripts.put("TEST_GET_READ_TIMESTAMP", TEST_GET_READ_TIMESTAMP_PG); + postgresScripts.put("TEST_GET_COMMIT_TIMESTAMP", TEST_GET_COMMIT_TIMESTAMP_PG); postgresScripts.put("TEST_TEMPORARY_TRANSACTIONS", TEST_TEMPORARY_TRANSACTIONS_PG); postgresScripts.put("TEST_TRANSACTION_MODE", TEST_TRANSACTION_MODE_PG); postgresScripts.put("TEST_TRANSACTION_MODE_READ_ONLY", TEST_TRANSACTION_MODE_READ_ONLY_PG); @@ -163,9 +166,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } @@ -217,24 +217,12 @@ public void test03_TestGetReadTimestamp() throws Exception { @Test public void test04_TestGetCommitTimestamp() throws Exception { - // Skipping test as Commit Timestamp not supported in POSTGRES - assumeFalse(dialect.dialect == Dialect.POSTGRESQL); try (CloudSpannerJdbcConnection connection = createConnection(env, database)) { verifier.verifyStatementsInFile( JdbcGenericConnection.of(connection), dialect.executeQueriesFiles.get("TEST_GET_COMMIT_TIMESTAMP"), JdbcSqlScriptVerifier.class, false); - } catch (SQLException e) { - if (env.getTestHelper().isEmulator() - && e.getErrorCode() == ErrorCode.INVALID_ARGUMENT.getGrpcStatusCode().value()) { - // Ignore as errors during read/write transactions are sticky on the emulator. - } - } catch (SpannerException e) { - if (env.getTestHelper().isEmulator() && e.getErrorCode() == ErrorCode.ALREADY_EXISTS) { - // Ignore, this is expected as errors during a read/write transaction are sticky on the - // emulator. - } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index b7fbc6956c5a..f6948a9c2942 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -29,7 +29,6 @@ import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Array; import java.sql.Connection; import java.sql.PreparedStatement; @@ -69,9 +68,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java index 7c8c7aeb53f9..5a2240182658 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSqlMusicScriptTest.java @@ -16,15 +16,12 @@ package com.google.cloud.spanner.jdbc.it; -import static org.junit.Assume.assumeFalse; - import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.Collections; @@ -63,9 +60,6 @@ public static List data() { @Before public void setup() { - assumeFalse( - "Emulator does not support PostgreSQL", - dialect.dialect == Dialect.POSTGRESQL && EmulatorSpannerHelper.isUsingEmulator()); database = env.getOrCreateDatabase(getDialect(), Collections.emptyList()); } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql index ae7ee898cfad..b1df42f1a221 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITReadWriteAutocommitSpannerTest.sql @@ -206,7 +206,7 @@ START BATCH DML; @EXPECT UPDATE_COUNT -1 DELETE FROM TEST WHERE ID IN (10,11,12); @EXPECT UPDATE_COUNT -1 -DELETE FROM TEST_NOT_FOUND WHERE ID IN (10,11,12); +DELETE FROM TEST WERE ID IN (10,11,12); -- Returns an error because of the second statement. @EXPECT EXCEPTION INVALID_ARGUMENT RUN BATCH; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql index 00fa78c3f7b0..adff02e059c4 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITScriptTest_TestGetReadTimestamp.sql @@ -94,8 +94,8 @@ SET SPANNER.READONLY = TRUE; @EXPECT EXCEPTION INVALID_ARGUMENT SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" -FROM NonExistentTable -WHERE SingerId=1; +FROM Singers +WERE SingerId=1; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; @@ -105,8 +105,8 @@ SET SPANNER.READONLY = FALSE; @EXPECT EXCEPTION INVALID_ARGUMENT SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" -FROM NonExistentTable -WHERE SingerId=1; +FROM Singers +WERE SingerId=1; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql new file mode 100644 index 000000000000..a727461c7cd2 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ITSqlScriptTest_TestGetCommitTimestamp.sql @@ -0,0 +1,138 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Test SHOW VARIABLE COMMIT_TIMESTAMP in different modes + */ + +-- Select query in autocommit and read-only mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = TRUE; +@EXPECT NO_RESULT +SET SPANNER.READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Select query in autocommit and read-write mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET SPANNER.READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WHERE SingerId=1; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Select query in transactional and read-only mode should not yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; +@EXPECT NO_RESULT +SET SPANNER.READONLY = TRUE; + +@EXPECT RESULT_SET +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Select query in transactional and read-write mode should yield a commit timestamp +@EXPECT NO_RESULT +SET SPANNER.READONLY = FALSE; + +@EXPECT RESULT_SET +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Update statement in transactional and read-write mode should yield a commit timestamp +@EXPECT NO_RESULT +SET AUTOCOMMIT = FALSE; + +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='New Last 1' +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Reset the value to its original value +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='Last 1' +WHERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +-- Select query in transactional and read-write mode that rollbacks should not yield a commit timestamp +@EXPECT RESULT_SET +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WHERE SingerId=1; + +@EXPECT NO_RESULT +ROLLBACK; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Update statement in transactional and read-write mode that rollbacks should not yield a commit timestamp +@EXPECT UPDATE_COUNT 1 +UPDATE Singers SET LastName='New Last 1' +WHERE SingerId=1; + +@EXPECT NO_RESULT +ROLLBACK; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; + +-- Invalid select query in transactional and read-write mode should yield a commit timestamp +-- The (invalid) query is sent to the server, initiating a transaction, that is committed afterwards +SET AUTOCOMMIT = FALSE; +SET SPANNER.READONLY = FALSE; + +@EXPECT EXCEPTION INVALID_ARGUMENT +SELECT LastName AS "ACTUAL", 'Last 1' AS "EXPECTED" +FROM Singers +WERE SingerId=1; + +@EXPECT NO_RESULT +COMMIT; + +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index c77968b45236..abecd9fad368 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -21,7 +21,7 @@ CREATE TABLE Singers ( FirstName VARCHAR(1024), LastName VARCHAR(1024), SingerInfo BYTEA, - BirthDate VARCHAR + BirthDate DATE ); CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); @@ -55,9 +55,10 @@ CREATE INDEX SongsBySongName ON Songs(SongName); CREATE TABLE Concerts ( VenueId BIGINT NOT NULL, SingerId BIGINT NOT NULL, - ConcertDate VARCHAR NOT NULL, - BeginTime VARCHAR, - EndTime VARCHAR, + ConcertDate DATE NOT NULL, + BeginTime TIMESTAMPTZ, + EndTime TIMESTAMPTZ, + TicketPrices BIGINT[], PRIMARY KEY(VenueId, SingerId, ConcertDate), FOREIGN KEY(SingerId) REFERENCES Singers(SingerId) ); From 1f77f7fa282296e121ebf5f695a87c56c33f3985 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 7 Mar 2024 14:41:18 +0100 Subject: [PATCH 1204/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.23 (#1527) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 6bcfd491db38..79af944277d6 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -87,7 +87,7 @@ com.spotify.fmt fmt-maven-plugin - 2.22.1 + 2.23 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index a32e7a800de4..ef02f014a019 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -97,7 +97,7 @@ com.spotify.fmt fmt-maven-plugin - 2.22.1 + 2.23 From 7f3caf8caafb5515fe8f09d24f6e9a28ca7154ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 7 Mar 2024 16:24:47 +0100 Subject: [PATCH 1205/1979] feat: support float32 (#1518) * feat: support float32 Adds support for the FLOAT32 / real data type. * test: update tests to use new RandomResultSetGenerator * test: add more tests * deps: bump to Spanner 6.61.0 * test: enable pg_numeric test on emulator * test: skip setFloat(..) until float32 is supported * chore: address review comments --- .../jdbc/AbstractJdbcPreparedStatement.java | 2 +- .../spanner/jdbc/AbstractJdbcWrapper.java | 13 + .../google/cloud/spanner/jdbc/JdbcArray.java | 3 + .../cloud/spanner/jdbc/JdbcDataType.java | 56 +++ .../spanner/jdbc/JdbcDatabaseMetaData.java | 38 ++ .../spanner/jdbc/JdbcParameterMetaData.java | 3 +- .../spanner/jdbc/JdbcParameterStore.java | 30 +- .../cloud/spanner/jdbc/JdbcResultSet.java | 34 ++ .../spanner/jdbc/JdbcResultSetMetaData.java | 9 + .../cloud/spanner/jdbc/JdbcTypeConverter.java | 17 +- .../spanner/jdbc/AllTypesMockServerTest.java | 372 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcArrayTest.java | 18 + .../jdbc/JdbcDatabaseMetaDataTest.java | 2 + .../spanner/jdbc/JdbcParameterStoreTest.java | 40 +- .../jdbc/JdbcResultSetMetaDataTest.java | 42 +- .../jdbc/PartitionedQueryMockServerTest.java | 30 +- ...reparedStatementParameterMetadataTest.java | 63 ++- .../spanner/jdbc/RandomResultSetTest.java | 164 ++++++++ .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 8 +- 19 files changed, 883 insertions(+), 61 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index cd1c50a733d7..2a9ba067df4b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -118,7 +118,7 @@ public void setLong(int parameterIndex, long value) throws SQLException { @Override public void setFloat(int parameterIndex, float value) throws SQLException { checkClosed(); - parameters.setParameter(parameterIndex, value, Types.FLOAT); + parameters.setParameter(parameterIndex, value, Types.REAL); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 86281af0daab..b06e5999e4a5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -49,6 +49,8 @@ static int extractColumnType(Type type) { return Types.BINARY; case DATE: return Types.DATE; + case FLOAT32: + return Types.REAL; case FLOAT64: return Types.DOUBLE; case INT64: @@ -81,9 +83,13 @@ static String getSpannerTypeName(Type type, Dialect dialect) { */ @Deprecated static String getSpannerTypeName(int sqlType) { + // TODO: Re-write to be dialect-aware (or remove all-together). if (sqlType == Types.BOOLEAN) return Type.bool().getCode().name(); if (sqlType == Types.BINARY) return Type.bytes().getCode().name(); if (sqlType == Types.DATE) return Type.date().getCode().name(); + if (sqlType == Types.REAL) { + return Type.float32().getCode().name(); + } if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Type.float64().getCode().name(); if (sqlType == Types.BIGINT || sqlType == Types.INTEGER @@ -109,6 +115,9 @@ static String getClassName(int sqlType) { if (sqlType == Types.BOOLEAN) return Boolean.class.getName(); if (sqlType == Types.BINARY) return Byte[].class.getName(); if (sqlType == Types.DATE) return Date.class.getName(); + if (sqlType == Types.REAL) { + return Float.class.getName(); + } if (sqlType == Types.DOUBLE || sqlType == Types.FLOAT) return Double.class.getName(); if (sqlType == Types.BIGINT || sqlType == Types.INTEGER @@ -137,6 +146,8 @@ static String getClassName(Type type) { return byte[].class.getName(); case DATE: return Date.class.getName(); + case FLOAT32: + return Float.class.getName(); case FLOAT64: return Double.class.getName(); case INT64: @@ -158,6 +169,8 @@ static String getClassName(Type type) { return byte[][].class.getName(); case DATE: return Date[].class.getName(); + case FLOAT32: + return Float[].class.getName(); case FLOAT64: return Double[].class.getName(); case INT64: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 650c1eb78f0e..4ef2ac21538c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -188,6 +188,9 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { case DATE: builder = binder.to(JdbcTypeConverter.toGoogleDate((Date) value)); break; + case FLOAT32: + builder = binder.to((Float) value); + break; case FLOAT64: builder = binder.to((Double) value); break; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 5dd082ef8439..b920d3d55ecd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -110,6 +110,47 @@ public Type getSpannerType() { return Type.date(); } }, + FLOAT32 { + @Override + public int getSqlType() { + return Types.REAL; + } + + @Override + public int getScale() { + return 7; + } + + @Override + public int getPrecision() { + return 7; + } + + @Override + public int getDefaultColumnDisplaySize() { + return 7; + } + + @Override + public Class getJavaClass() { + return Float.class; + } + + @Override + public Code getCode() { + return Code.FLOAT32; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getFloatList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.float32(); + } + }, FLOAT64 { private final Set> classes = new HashSet<>(Arrays.asList(Float.class, Double.class)); @@ -371,6 +412,21 @@ public Type getSpannerType() { public abstract Type getSpannerType(); + // TODO: Implement and use this method for all types. + public int getPrecision() { + throw new UnsupportedOperationException(); + } + + // TODO: Implement and use this method for all types. + public int getScale() { + throw new UnsupportedOperationException(); + } + + // TODO: Implement and use this method for all types. + public int getDefaultColumnDisplaySize() { + throw new UnsupportedOperationException(); + } + /** * @param rs the result set to look up the elements * @param columnIndex zero based column index diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 446339587fd4..025b26570ac6 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -1056,6 +1056,44 @@ public ResultSet getTypeInfo() { .set("NUM_PREC_RADIX") .to((Long) null) .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("FLOAT32") + .set("DATA_TYPE") + .to(Types.REAL) // 8 + .set("PRECISION") + .to(7L) + .set("LITERAL_PREFIX") + .to((String) null) + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typePredBasic) + .set("UNSIGNED_ATTRIBUTE") + .to(false) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("FLOAT32") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to(2) + .build(), Struct.newBuilder() .set("TYPE_NAME") .to("FLOAT64") diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java index 82a4b9133c62..784a2678fd29 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterMetaData.java @@ -76,6 +76,7 @@ public boolean isSigned(int param) throws SQLException { int type = getParameterType(param); return type == Types.DOUBLE || type == Types.FLOAT + || type == Types.REAL || type == Types.BIGINT || type == Types.INTEGER || type == Types.SMALLINT @@ -139,7 +140,7 @@ private int getParameterTypeFromValue(int param) { } else if (Long.class.isAssignableFrom(value.getClass())) { return Types.BIGINT; } else if (Float.class.isAssignableFrom(value.getClass())) { - return Types.FLOAT; + return Types.REAL; } else if (Double.class.isAssignableFrom(value.getClass())) { return Types.DOUBLE; } else if (BigDecimal.class.isAssignableFrom(value.getClass())) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 5fb4177fc8ad..dabc9bfa0518 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -452,8 +452,12 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, return binder.to(((Number) value).longValue()); } throw JdbcSqlExceptionFactory.of(value + " is not a valid long", Code.INVALID_ARGUMENT); - case Types.FLOAT: case Types.REAL: + if (value instanceof Number) { + return binder.to(((Number) value).floatValue()); + } + throw JdbcSqlExceptionFactory.of(value + " is not a valid float", Code.INVALID_ARGUMENT); + case Types.FLOAT: case Types.DOUBLE: if (value instanceof Number) { return binder.to(((Number) value).doubleValue()); @@ -744,8 +748,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.INTEGER: case Types.BIGINT: return binder.toInt64Array((long[]) null); - case Types.FLOAT: case Types.REAL: + return binder.toFloat32Array((float[]) null); + case Types.FLOAT: case Types.DOUBLE: return binder.toFloat64Array((double[]) null); case Types.NUMERIC: @@ -814,13 +819,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (Long[].class.isAssignableFrom(value.getClass())) { return binder.toInt64Array(toLongList((Long[]) value)); } else if (float[].class.isAssignableFrom(value.getClass())) { - double[] l = new double[((float[]) value).length]; - for (int i = 0; i < l.length; i++) { - l[i] = ((float[]) value)[i]; - } - return binder.toFloat64Array(l); + return binder.toFloat32Array((float[]) value); } else if (Float[].class.isAssignableFrom(value.getClass())) { - return binder.toFloat64Array(toDoubleList((Float[]) value)); + return binder.toFloat32Array(toFloatList((Float[]) value)); } else if (double[].class.isAssignableFrom(value.getClass())) { return binder.toFloat64Array((double[]) value); } else if (Double[].class.isAssignableFrom(value.getClass())) { @@ -860,6 +861,14 @@ private List toLongList(Number[] input) { return res; } + private List toFloatList(Number[] input) { + List res = new ArrayList<>(input.length); + for (Number number : input) { + res.add(number == null ? null : number.floatValue()); + } + return res; + } + private List toDoubleList(Number[] input) { List res = new ArrayList<>(input.length); for (Number number : input) { @@ -901,9 +910,8 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { } else { return binder.to((BigDecimal) null); } - case Types.DOUBLE: - return binder.to((Double) null); case Types.FLOAT: + case Types.DOUBLE: return binder.to((Double) null); case Types.INTEGER: return binder.to((Long) null); @@ -920,7 +928,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { case Types.NVARCHAR: return binder.to((String) null); case Types.REAL: - return binder.to((Double) null); + return binder.to((Float) null); case Types.SMALLINT: return binder.to((Long) null); case Types.SQLXML: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 4152fa58b8c5..91ec976b8534 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -203,6 +203,8 @@ public String getString(int columnIndex) throws SQLException { return isNull ? null : spanner.getBytes(spannerIndex).toBase64(); case DATE: return isNull ? null : spanner.getDate(spannerIndex).toString(); + case FLOAT32: + return isNull ? null : Float.toString(spanner.getFloat(spannerIndex)); case FLOAT64: return isNull ? null : Double.toString(spanner.getDouble(spannerIndex)); case INT64: @@ -235,6 +237,8 @@ public boolean getBoolean(int columnIndex) throws SQLException { switch (type) { case BOOL: return !isNull && spanner.getBoolean(spannerIndex); + case FLOAT32: + return !isNull && spanner.getFloat(spannerIndex) != 0f; case FLOAT64: return !isNull && spanner.getDouble(spannerIndex) != 0D; case INT64: @@ -266,6 +270,10 @@ public byte getByte(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? (byte) 0 : (spanner.getBoolean(spannerIndex) ? (byte) 1 : 0); + case FLOAT32: + return isNull + ? (byte) 0 + : checkedCastToByte(Float.valueOf(spanner.getFloat(spannerIndex)).longValue()); case FLOAT64: return isNull ? (byte) 0 @@ -301,6 +309,10 @@ public short getShort(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (short) 1 : 0); + case FLOAT32: + return isNull + ? 0 + : checkedCastToShort(Float.valueOf(spanner.getFloat(spannerIndex)).longValue()); case FLOAT64: return isNull ? 0 @@ -336,6 +348,10 @@ public int getInt(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? 1 : 0); + case FLOAT32: + return isNull + ? 0 + : checkedCastToInt(Float.valueOf(spanner.getFloat(spannerIndex)).longValue()); case FLOAT64: return isNull ? 0 @@ -371,6 +387,8 @@ public long getLong(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? 0L : (spanner.getBoolean(spannerIndex) ? 1L : 0L); + case FLOAT32: + return isNull ? 0L : Float.valueOf(spanner.getFloat(spannerIndex)).longValue(); case FLOAT64: return isNull ? 0L : Double.valueOf(spanner.getDouble(spannerIndex)).longValue(); case INT64: @@ -404,6 +422,8 @@ public float getFloat(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (float) 1 : 0); + case FLOAT32: + return isNull ? 0 : spanner.getFloat(spannerIndex); case FLOAT64: return isNull ? 0 : checkedCastToFloat(spanner.getDouble(spannerIndex)); case INT64: @@ -435,6 +455,8 @@ public double getDouble(int columnIndex) throws SQLException { switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (double) 1 : 0); + case FLOAT32: + return isNull ? 0 : spanner.getFloat(spannerIndex); case FLOAT64: return isNull ? 0 : spanner.getDouble(spannerIndex); case INT64: @@ -481,6 +503,7 @@ public Date getDate(int columnIndex) throws SQLException { ? null : new Date(spanner.getTimestamp(spannerIndex).toSqlTimestamp().getTime()); case BOOL: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: @@ -508,6 +531,7 @@ public Time getTime(int columnIndex) throws SQLException { return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex)); case BOOL: case DATE: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: @@ -536,6 +560,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case TIMESTAMP: return isNull ? null : JdbcTypeConverter.toSqlTimestamp(spanner.getTimestamp(spannerIndex)); case BOOL: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: @@ -694,6 +719,9 @@ private Object getObject(Type type, int columnIndex) throws SQLException { if (type == Type.bool()) return getBoolean(columnIndex); if (type == Type.bytes()) return getBytes(columnIndex); if (type == Type.date()) return getDate(columnIndex); + if (type == Type.float32()) { + return getFloat(columnIndex); + } if (type == Type.float64()) return getDouble(columnIndex); if (type == Type.int64()) return getLong(columnIndex); if (type == Type.numeric()) return getBigDecimal(columnIndex); @@ -774,6 +802,9 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) ? null : (spanner.getBoolean(columnIndex - 1) ? BigDecimal.ONE : BigDecimal.ZERO); break; + case FLOAT32: + res = isNull ? null : BigDecimal.valueOf(spanner.getFloat(spannerIndex)); + break; case FLOAT64: res = isNull ? null : BigDecimal.valueOf(spanner.getDouble(spannerIndex)); break; @@ -886,6 +917,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { return new Date( JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal).getTime()); case BOOL: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: @@ -917,6 +949,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { return isNull ? null : JdbcTypeConverter.toSqlTime(spanner.getTimestamp(spannerIndex), cal); case BOOL: case DATE: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: @@ -951,6 +984,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException case TIMESTAMP: return JdbcTypeConverter.getAsSqlTimestamp(spanner.getTimestamp(spannerIndex), cal); case BOOL: + case FLOAT32: case FLOAT64: case INT64: case NUMERIC: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index 26226bc66314..ff1ec2e2e488 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -95,6 +95,9 @@ public int getColumnDisplaySize(int column) { return binaryLength == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : binaryLength; case Types.DATE: return 10; + case Types.REAL: + return JdbcDataType.FLOAT32.getDefaultColumnDisplaySize(); + case Types.FLOAT: case Types.DOUBLE: return 14; case Types.BIGINT: @@ -134,6 +137,9 @@ public int getPrecision(int column) { return 1; case Types.DATE: return 10; + case Types.REAL: + return JdbcDataType.FLOAT32.getPrecision(); + case Types.FLOAT: case Types.DOUBLE: return 14; case Types.BIGINT: @@ -155,6 +161,9 @@ public int getPrecision(int column) { @Override public int getScale(int column) { int colType = getColumnType(column); + if (colType == Types.REAL) { + return JdbcDataType.FLOAT32.getScale(); + } if (colType == Types.DOUBLE || colType == Types.NUMERIC) { return 15; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index a506998ea6c3..c6be0a824975 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -91,6 +91,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; if (type.getCode() == Code.INT64) return (Long) value != 0; + if (type.getCode() == Code.FLOAT32) { + return (Float) value != 0f; + } if (type.getCode() == Code.FLOAT64) return (Double) value != 0d; if (type.getCode() == Code.NUMERIC) return !value.equals(BigDecimal.ZERO); } @@ -134,6 +137,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (targetType.equals(Float.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Float.valueOf(1f) : Float.valueOf(0f); + if (type.getCode() == Code.FLOAT32) { + return value; + } if (type.getCode() == Code.FLOAT64) return AbstractJdbcWrapper.checkedCastToFloat((Double) value); if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).floatValue(); @@ -141,7 +147,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (targetType.equals(Double.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? Double.valueOf(1d) : Double.valueOf(0d); - if (type.getCode() == Code.FLOAT64) return value; + if (type.getCode() == Code.FLOAT64 || type.getCode() == Code.FLOAT32) { + return value; + } if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).doubleValue(); } if (targetType.equals(java.sql.Date.class)) { @@ -190,6 +198,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx case DATE: return Value.dateArray( toGoogleDates((java.sql.Date[]) ((java.sql.Array) value).getArray())); + case FLOAT32: + return Value.float32Array(Arrays.asList((Float[]) ((java.sql.Array) value).getArray())); case FLOAT64: return Value.float64Array( Arrays.asList((Double[]) ((java.sql.Array) value).getArray())); @@ -222,6 +232,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.bytes(ByteArray.copyFrom((byte[]) value)); case DATE: return Value.date(toGoogleDate((java.sql.Date) value)); + case FLOAT32: + return Value.float32((Float) value); case FLOAT64: return Value.float64((Double) value); case INT64: @@ -260,6 +272,9 @@ private static void checkValidTypeAndValueForConvert(Type type, Object value) JdbcPreconditions.checkArgument( type.getCode() != Code.DATE || value.getClass().equals(java.sql.Date.class), "input type is date, but input value is not an instance of java.sql.Date"); + JdbcPreconditions.checkArgument( + type.getCode() != Code.FLOAT32 || value.getClass().equals(Float.class), + "input type is float32, but input value is not an instance of Float"); JdbcPreconditions.checkArgument( type.getCode() != Code.FLOAT64 || value.getClass().equals(Double.class), "input type is float64, but input value is not an instance of Double"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java new file mode 100644 index 000000000000..4a1eb6a6f335 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java @@ -0,0 +1,372 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.common.collect.ImmutableList; +import com.google.protobuf.Value; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.Type; +import com.google.spanner.v1.TypeCode; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.Date; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Base64; +import java.util.Map; +import java.util.stream.Collectors; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class AllTypesMockServerTest + extends com.google.cloud.spanner.connection.AllTypesMockServerTest { + + @Override + @Test + public void testSelectAllTypes() { + try (Connection connection = createJdbcConnection()) { + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_STATEMENT.getSql())) { + assertTrue(resultSet.next()); + + int col = 0; + assertEquals(BOOL_VALUE, resultSet.getBoolean(++col)); + assertEquals(INT64_VALUE, resultSet.getLong(++col)); + assertEquals(FLOAT32_VALUE, resultSet.getFloat(++col), 0.0f); + assertEquals(FLOAT64_VALUE, resultSet.getDouble(++col), 0.0d); + if (dialect == Dialect.POSTGRESQL) { + assertEquals(PG_NUMERIC_VALUE, resultSet.getString(++col)); + } else { + assertEquals(NUMERIC_VALUE, resultSet.getBigDecimal(++col)); + } + assertEquals(STRING_VALUE, resultSet.getString(++col)); + assertEquals(JSON_VALUE, resultSet.getString(++col)); + assertArrayEquals(BYTES_VALUE, resultSet.getBytes(++col)); + assertEquals( + new java.sql.Date( + DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), + resultSet.getDate(++col)); + assertEquals(TIMESTAMP_VALUE.toSqlTimestamp(), resultSet.getTimestamp(++col)); + + assertEquals( + BOOL_ARRAY_VALUE, Arrays.asList((Boolean[]) resultSet.getArray(++col).getArray())); + assertEquals( + INT64_ARRAY_VALUE, Arrays.asList((Long[]) resultSet.getArray(++col).getArray())); + assertEquals( + FLOAT32_ARRAY_VALUE, Arrays.asList((Float[]) resultSet.getArray(++col).getArray())); + assertEquals( + FLOAT64_ARRAY_VALUE, Arrays.asList((Double[]) resultSet.getArray(++col).getArray())); + if (dialect == Dialect.POSTGRESQL) { + // TODO: Fix getting an ARRAY. This currently tries to cast it to a + // BigDecimal[], which is not supported for NaN values. + // assertEquals(PG_NUMERIC_ARRAY_VALUE, Arrays.asList((String[]) + // resultSet.getArray(++col).getArray())); + ++col; + } else { + assertEquals( + NUMERIC_ARRAY_VALUE, + Arrays.asList((BigDecimal[]) resultSet.getArray(++col).getArray())); + } + assertEquals( + STRING_ARRAY_VALUE, Arrays.asList((String[]) resultSet.getArray(++col).getArray())); + assertEquals( + JSON_ARRAY_VALUE, Arrays.asList((String[]) resultSet.getArray(++col).getArray())); + // Convert bytes to base64 strings, as the equals(..) method for byte[] uses ==. + assertEquals( + BYTES_ARRAY_VALUE.stream() + .map(bytes -> bytes == null ? null : bytes.toBase64()) + .collect(Collectors.toList()), + Arrays.stream((byte[][]) resultSet.getArray(++col).getArray()) + .map(bytes -> bytes == null ? null : Base64.getEncoder().encodeToString(bytes)) + .collect(Collectors.toList())); + assertEquals( + DATE_ARRAY_VALUE.stream() + .map( + date -> + date == null + ? null + : new Date( + date.getYear() - 1900, date.getMonth() - 1, date.getDayOfMonth())) + .collect(Collectors.toList()), + Arrays.asList((Date[]) resultSet.getArray(++col).getArray())); + assertEquals( + TIMESTAMP_ARRAY_VALUE.stream() + .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp()) + .collect(Collectors.toList()), + Arrays.asList((Timestamp[]) resultSet.getArray(++col).getArray())); + + assertFalse(resultSet.next()); + } + } catch (SQLException sqlException) { + throw new RuntimeException(sqlException); + } + } + + @Override + @Test + public void testInsertAllTypes() { + // TODO: Remove when PG_NUMERIC NaN is supported. + if (dialect == Dialect.POSTGRESQL) { + Statement insertStatement = createInsertStatement(dialect); + insertStatement = + insertStatement + .toBuilder() + .replace(insertStatement.getSql().replaceAll("@p", "\\$")) + .bind("p15") + .to( + com.google.cloud.spanner.Value.pgNumericArray( + NUMERIC_ARRAY_VALUE.stream() + .map( + bigDecimal -> + bigDecimal == null ? null : bigDecimal.toEngineeringString()) + .collect(Collectors.toList()))) + .build(); + mockSpanner.putStatementResult(StatementResult.update(insertStatement, 1L)); + } + try (Connection connection = createJdbcConnection()) { + try (PreparedStatement statement = + connection.prepareStatement( + createInsertStatement(dialect).getSql().replaceAll("@p\\d+", "?"))) { + int param = 0; + statement.setBoolean(++param, BOOL_VALUE); + statement.setLong(++param, INT64_VALUE); + statement.setFloat(++param, FLOAT32_VALUE); + statement.setDouble(++param, FLOAT64_VALUE); + if (dialect == Dialect.POSTGRESQL) { + statement.setBigDecimal(++param, new BigDecimal(PG_NUMERIC_VALUE)); + } else { + statement.setBigDecimal(++param, NUMERIC_VALUE); + } + statement.setString(++param, STRING_VALUE); + if (dialect == Dialect.POSTGRESQL) { + statement.setObject(++param, JSON_VALUE, JdbcDataType.PG_JSONB.getSqlType()); + } else { + statement.setObject(++param, JSON_VALUE, JdbcDataType.JSON.getSqlType()); + } + statement.setBytes(++param, BYTES_VALUE); + statement.setDate( + ++param, + new Date( + DATE_VALUE.getYear() - 1900, + DATE_VALUE.getMonth() - 1, + DATE_VALUE.getDayOfMonth())); + statement.setTimestamp(++param, TIMESTAMP_VALUE.toSqlTimestamp()); + + // TODO: Support PostgreSQL type names for creating arrays. + statement.setArray( + ++param, connection.createArrayOf("BOOL", BOOL_ARRAY_VALUE.toArray(new Boolean[0]))); + statement.setArray( + ++param, connection.createArrayOf("INT64", INT64_ARRAY_VALUE.toArray(new Long[0]))); + statement.setArray( + ++param, + connection.createArrayOf("FLOAT32", FLOAT32_ARRAY_VALUE.toArray(new Float[0]))); + statement.setArray( + ++param, + connection.createArrayOf("FLOAT64", FLOAT64_ARRAY_VALUE.toArray(new Double[0]))); + + // TODO: Make dialect-specific when NaN in arrays for PG_NUMERIC is supported. + // statement.setArray( + // ++param, + // connection.createArrayOf( + // "NUMERIC", + // dialect == Dialect.POSTGRESQL + // ? PG_NUMERIC_ARRAY_VALUE.toArray(new String[0]) + // : NUMERIC_ARRAY_VALUE.toArray(new BigDecimal[0]))); + statement.setArray( + ++param, + connection.createArrayOf( + dialect == Dialect.POSTGRESQL ? "PG_NUMERIC" : "NUMERIC", + NUMERIC_ARRAY_VALUE.toArray(new BigDecimal[0]))); + + statement.setArray( + ++param, connection.createArrayOf("STRING", STRING_ARRAY_VALUE.toArray(new String[0]))); + statement.setArray( + ++param, + connection.createArrayOf( + dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON", + JSON_ARRAY_VALUE.toArray(new String[0]))); + statement.setArray( + ++param, + connection.createArrayOf( + "BYTES", + BYTES_ARRAY_VALUE.stream() + .map(bytes -> bytes == null ? null : bytes.toByteArray()) + .toArray(byte[][]::new))); + statement.setArray( + ++param, + connection.createArrayOf( + "DATE", + DATE_ARRAY_VALUE.stream() + .map( + date -> + date == null + ? null + : new Date( + date.getYear() - 1900, + date.getMonth() - 1, + date.getDayOfMonth())) + .toArray(Date[]::new))); + statement.setArray( + ++param, + connection.createArrayOf( + "TIMESTAMP", + TIMESTAMP_ARRAY_VALUE.stream() + .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp()) + .toArray(Timestamp[]::new))); + + assertEquals(1, statement.executeUpdate()); + } + + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + Map paramTypes = request.getParamTypesMap(); + Map params = request.getParams().getFieldsMap(); + assertEquals(20, paramTypes.size()); + assertEquals(20, params.size()); + + // Verify param types. + ImmutableList expectedTypes = + ImmutableList.of( + TypeCode.BOOL, + TypeCode.INT64, + TypeCode.FLOAT32, + TypeCode.FLOAT64, + TypeCode.NUMERIC, + TypeCode.STRING, + TypeCode.JSON, + TypeCode.BYTES, + TypeCode.DATE, + TypeCode.TIMESTAMP); + for (int col = 0; col < expectedTypes.size(); col++) { + assertEquals(expectedTypes.get(col), paramTypes.get("p" + (col + 1)).getCode()); + int arrayCol = col + expectedTypes.size(); + assertEquals(TypeCode.ARRAY, paramTypes.get("p" + (arrayCol + 1)).getCode()); + assertEquals( + expectedTypes.get(col), + paramTypes.get("p" + (arrayCol + 1)).getArrayElementType().getCode()); + } + + // Verify param values. + int col = 0; + assertEquals(BOOL_VALUE, params.get("p" + ++col).getBoolValue()); + assertEquals(String.valueOf(INT64_VALUE), params.get("p" + ++col).getStringValue()); + assertEquals(FLOAT32_VALUE, params.get("p" + ++col).getNumberValue(), 0.0d); + assertEquals(FLOAT64_VALUE, params.get("p" + ++col).getNumberValue(), 0.0d); + assertEquals( + dialect == Dialect.POSTGRESQL ? PG_NUMERIC_VALUE : NUMERIC_VALUE.toEngineeringString(), + params.get("p" + ++col).getStringValue()); + assertEquals(STRING_VALUE, params.get("p" + ++col).getStringValue()); + assertEquals(JSON_VALUE, params.get("p" + ++col).getStringValue()); + assertEquals( + Base64.getEncoder().encodeToString(BYTES_VALUE), + params.get("p" + ++col).getStringValue()); + assertEquals(DATE_VALUE.toString(), params.get("p" + ++col).getStringValue()); + assertEquals(TIMESTAMP_VALUE.toString(), params.get("p" + ++col).getStringValue()); + + assertEquals( + BOOL_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : value.getBoolValue()) + .collect(Collectors.toList())); + assertEquals( + INT64_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : Long.valueOf(value.getStringValue())) + .collect(Collectors.toList())); + assertEquals( + FLOAT32_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : (float) value.getNumberValue()) + .collect(Collectors.toList())); + assertEquals( + FLOAT64_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : value.getNumberValue()) + .collect(Collectors.toList())); + if (dialect == Dialect.POSTGRESQL) { + // TODO: Replace with PG specific value when NaN is supported. + // assertEquals( + // PG_NUMERIC_ARRAY_VALUE, + // params.get("p" + ++col).getListValue().getValuesList().stream() + // .map(value -> value.hasNullValue() ? null : value.getStringValue()) + // .collect(Collectors.toList())); + assertEquals( + NUMERIC_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : new BigDecimal(value.getStringValue())) + .collect(Collectors.toList())); + } else { + assertEquals( + NUMERIC_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : new BigDecimal(value.getStringValue())) + .collect(Collectors.toList())); + } + assertEquals( + STRING_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : value.getStringValue()) + .collect(Collectors.toList())); + assertEquals( + JSON_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : value.getStringValue()) + .collect(Collectors.toList())); + assertEquals( + BYTES_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map( + value -> + value.hasNullValue() ? null : ByteArray.fromBase64(value.getStringValue())) + .collect(Collectors.toList())); + assertEquals( + DATE_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map( + value -> + value.hasNullValue() + ? null + : com.google.cloud.Date.parseDate(value.getStringValue())) + .collect(Collectors.toList())); + assertEquals( + TIMESTAMP_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map( + value -> + value.hasNullValue() + ? null + : com.google.cloud.Timestamp.parseTimestamp(value.getStringValue())) + .collect(Collectors.toList())); + } catch (SQLException sqlException) { + throw new RuntimeException(sqlException); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index 16e16ad06c35..e39e28a74136 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -95,6 +95,24 @@ public void testCreateArrayTypeName() throws SQLException { assertThat(rs.next()).isFalse(); } + array = + JdbcArray.createArray( + "FLOAT32", new Float[] {1.1f, 2.2f, Double.valueOf(Math.PI).floatValue()}); + assertEquals(Types.REAL, array.getBaseType()); + assertThat(((Float[]) array.getArray(1, 3))[2]).isEqualTo(Double.valueOf(Math.PI).floatValue()); + assertEquals(Double.valueOf(Math.PI).floatValue(), ((Float[]) array.getArray(1, 3))[2], 0.0f); + try (ResultSet resultSet = array.getResultSet()) { + assertTrue(resultSet.next()); + // Column index 2 of a JDBC array is the value. + // Column index 1 of a JDBC array is the index. + assertEquals(1.1f, resultSet.getFloat(2), 0.0f); + assertTrue(resultSet.next()); + assertEquals(2.2f, resultSet.getFloat(2), 0.0f); + assertTrue(resultSet.next()); + assertEquals(Double.valueOf(Math.PI).floatValue(), resultSet.getFloat(2), 0.0f); + assertFalse(resultSet.next()); + } + array = JdbcArray.createArray("FLOAT64", new Double[] {1.1D, 2.2D, Math.PI}); assertThat(array.getBaseType()).isEqualTo(Types.DOUBLE); assertThat(((Double[]) array.getArray(1, 3))[2]).isEqualTo(Math.PI); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 9782e964a4cb..1dc95655f130 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -487,6 +487,8 @@ public void testGetTypeInfo() throws SQLException { assertTrue(rs.next()); assertEquals("BYTES", rs.getString("TYPE_NAME")); assertTrue(rs.next()); + assertEquals("FLOAT32", rs.getString("TYPE_NAME")); + assertTrue(rs.next()); assertEquals("FLOAT64", rs.getString("TYPE_NAME")); assertTrue(rs.next()); assertEquals("BOOL", rs.getString("TYPE_NAME")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index 869655bb39c6..ba674b2552e5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -147,9 +147,9 @@ public void testSetParameterWithType() throws SQLException, IOException { params.setParameter(1, 1L, Types.BIGINT); assertEquals(1, ((Long) params.getParameter(1)).longValue()); verifyParameter(params, Value.int64(1)); - params.setParameter(1, (float) 1, Types.FLOAT); + params.setParameter(1, (float) 1, Types.REAL); assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); - verifyParameter(params, Value.float64(1)); + verifyParameter(params, Value.float32(1)); params.setParameter(1, (double) 1, Types.DOUBLE); assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); verifyParameter(params, Value.float64(1)); @@ -266,8 +266,33 @@ public void testSetParameterWithType() throws SQLException, IOException { verifyParameter(params, Value.int64(1)); } + // types that should lead to float32 + for (int type : new int[] {Types.REAL}) { + params.setParameter(1, (byte) 1, type); + assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, (short) 1, type); + assertEquals(1, ((Short) params.getParameter(1)).shortValue()); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, 1, type); + assertEquals(1, ((Integer) params.getParameter(1)).intValue()); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, 1L, type); + assertEquals(1, ((Long) params.getParameter(1)).longValue()); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, (float) 1, type); + assertEquals(1.0f, (Float) params.getParameter(1), 0.0f); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, (double) 1, type); + assertEquals(1.0d, (Double) params.getParameter(1), 0.0d); + verifyParameter(params, Value.float32(1)); + params.setParameter(1, BigDecimal.ONE, type); + assertEquals(BigDecimal.ONE, params.getParameter(1)); + verifyParameter(params, Value.float32(1)); + } + // types that should lead to float64 - for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) { + for (int type : new int[] {Types.FLOAT, Types.DOUBLE}) { params.setParameter(1, (byte) 1, type); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.float64(1)); @@ -438,8 +463,15 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { assertInvalidParameter(params, Boolean.TRUE, type); } + // types that should not be valid float32 parameters. + for (int type : new int[] {Types.REAL}) { + assertInvalidParameter(params, "1", type); + assertInvalidParameter(params, new Object(), type); + assertInvalidParameter(params, Boolean.TRUE, type); + } + // types that should lead to float64 - for (int type : new int[] {Types.FLOAT, Types.REAL, Types.DOUBLE}) { + for (int type : new int[] {Types.FLOAT, Types.DOUBLE}) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java index a46a1c324030..53b58dcc170f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -73,6 +73,8 @@ private static int getDefaultSize(Type type) { return 1; case DATE: return 10; + case FLOAT32: + return 7; case FLOAT64: return 14; case INT64: @@ -189,6 +191,7 @@ private static List getAllTypes() { types.add(Type.bool()); types.add(Type.bytes()); types.add(Type.date()); + types.add(Type.float32()); types.add(Type.float64()); types.add(Type.int64()); types.add(Type.string()); @@ -237,6 +240,8 @@ private Value getDefaultValue(Type type, int row) { return Value.numeric(new BigDecimal("3.14")); case PG_NUMERIC: return Value.pgNumeric("3.14"); + case FLOAT32: + return Value.float32(6.626f); case FLOAT64: return Value.float64(123.45D); case STRING: @@ -261,6 +266,8 @@ private Value getDefaultValue(Type type, int row) { return Value.numericArray(Arrays.asList(BigDecimal.ONE, BigDecimal.TEN)); case PG_NUMERIC: return Value.pgNumericArray(Arrays.asList("3.14", null, "NaN", "6.626")); + case FLOAT32: + return Value.float32Array(Arrays.asList(-3498.31490f, 82.353f)); case FLOAT64: return Value.float64Array(Arrays.asList(123.45D, 543.21D)); case STRING: @@ -371,6 +378,8 @@ private int getDefaultDisplaySize(Type type, int column) { return 5; case INT64: return 10; + case FLOAT32: + return 7; case NUMERIC: case PG_NUMERIC: return 14; @@ -432,6 +441,8 @@ private int getPrecision(TestColumn col) { return 1; case DATE: return 10; + case FLOAT32: + return 7; case FLOAT64: return 14; case INT64: @@ -460,6 +471,9 @@ public void testGetScale() { } private int getScale(TestColumn col) { + if (col.type == Type.float32()) { + return 7; + } if (col.type == Type.float64() || col.type == Type.numeric() || col.type == Type.pgNumeric()) { return 15; } @@ -495,6 +509,8 @@ private int getSqlType(Type type) { case NUMERIC: case PG_NUMERIC: return Types.NUMERIC; + case FLOAT32: + return Types.REAL; case FLOAT64: return Types.DOUBLE; case STRING: @@ -562,6 +578,8 @@ private String getTypeClassName(Type type) { case NUMERIC: case PG_NUMERIC: return BigDecimal.class.getName(); + case FLOAT32: + return Float.class.getName(); case FLOAT64: return Double.class.getName(); case STRING: @@ -583,6 +601,8 @@ private String getTypeClassName(Type type) { case NUMERIC: case PG_NUMERIC: return BigDecimal[].class.getName(); + case FLOAT32: + return Float[].class.getName(); case FLOAT64: return Double[].class.getName(); case STRING: @@ -610,15 +630,15 @@ private String getTypeClassName(Type type) { "Col 1: COL1 BOOL\n" + "Col 2: COL2 BYTES\n" + "Col 3: COL3 DATE\n" - + "Col 4: COL4 FLOAT64\n" - + "Col 5: COL5 INT64\n" - + "Col 6: COL6 STRING\n" - + "Col 7: COL7 JSON\n" - + "Col 8: COL8 PG_JSONB\n" - + "Col 9: COL9 TIMESTAMP\n" - + "Col 10: COL10 NUMERIC\n" - + "Col 11: COL11 PG_NUMERIC\n" - + "Col 12: COL12 ARRAY\n" + + "Col 4: COL4 FLOAT32\n" + + "Col 5: COL5 FLOAT64\n" + + "Col 6: COL6 INT64\n" + + "Col 7: COL7 STRING\n" + + "Col 8: COL8 JSON\n" + + "Col 9: COL9 PG_JSONB\n" + + "Col 10: COL10 TIMESTAMP\n" + + "Col 11: COL11 NUMERIC\n" + + "Col 12: COL12 PG_NUMERIC\n" + "Col 13: COL13 ARRAY\n" + "Col 14: COL14 ARRAY\n" + "Col 15: COL15 ARRAY\n" @@ -629,7 +649,9 @@ private String getTypeClassName(Type type) { + "Col 20: COL20 ARRAY\n" + "Col 21: COL21 ARRAY\n" + "Col 22: COL22 ARRAY\n" - + "Col 23: CALCULATED INT64\n"; + + "Col 23: COL23 ARRAY\n" + + "Col 24: COL24 ARRAY\n" + + "Col 25: CALCULATED INT64\n"; @Test public void testToString() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index be5087fe432e..31842409bd40 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -50,6 +50,8 @@ public class PartitionedQueryMockServerTest extends AbstractMockServerTest { @Parameter public Dialect dialect; + private Dialect currentDialect; + @Parameters(name = "dialect = {0}") public static Object[] data() { return Dialect.values(); @@ -57,13 +59,21 @@ public static Object[] data() { @Before public void setupDialect() { - mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + if (currentDialect != dialect) { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + currentDialect = dialect; + SpannerPool.closeSpannerPool(); + } } @After public void clearRequests() { mockSpanner.clearRequests(); - SpannerPool.closeSpannerPool(); + } + + private int getExpectedColumnCount(Dialect dialect) { + // GoogleSQL also adds 4 PROTO columns. + return dialect == Dialect.GOOGLE_STANDARD_SQL ? 24 : 20; } private String createUrl() { @@ -80,7 +90,7 @@ private Connection createConnection() throws SQLException { public void testPartitionedQueryUsingSql() throws SQLException { int numRows = 5; int maxPartitions = 4; - RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect); Statement statement = Statement.newBuilder( String.format( @@ -158,7 +168,7 @@ public void testPartitionedQueryUsingSql() throws SQLException { partitionStatement.setBoolean(1, true); try (ResultSet results = partitionStatement.executeQuery()) { assertNotNull(results.getMetaData()); - assertEquals(24, results.getMetaData().getColumnCount()); + assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -184,7 +194,7 @@ public void testPartitionedQueryUsingSql() throws SQLException { public void testPartitionedQueryStatement() throws SQLException { int numRows = 5; int maxPartitions = 4; - RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect); Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); @@ -266,7 +276,7 @@ public void testPartitionedQueryStatement() throws SQLException { public void testPartitionedQueryPreparedStatement() throws SQLException { int numRows = 5; int maxPartitions = 4; - RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect); Statement statement = Statement.newBuilder( String.format( @@ -357,7 +367,7 @@ public void testPartitionedQueryPreparedStatement() throws SQLException { public void testAutoPartitionMode() throws SQLException { int numRows = 5; int maxPartitions = 4; - RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect); Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); @@ -376,7 +386,7 @@ public void testAutoPartitionMode() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(24, results.getMetaData().getColumnCount()); + assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; @@ -463,7 +473,7 @@ public void testAutoPartitionMode() throws SQLException { public void testAutoPartitionModeEmptyResult() throws SQLException { int numRows = 0; int maxPartitions = 1; - RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); + RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows, dialect); Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); @@ -482,7 +492,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException { try (ResultSet results = connection.createStatement().executeQuery("select * from my_table where active=true")) { assertNotNull(results.getMetaData()); - assertEquals(24, results.getMetaData().getColumnCount()); + assertEquals(getExpectedColumnCount(dialect), results.getMetaData().getColumnCount()); int rowCount = 0; while (results.next()) { rowCount++; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java index 8b7130ed6496..a6d7c35420ba 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java @@ -60,18 +60,18 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); String baseSql = - "insert into all_types (col_bool, col_bytes, col_date, col_float64, col_int64, " + "insert into all_types (col_bool, col_bytes, col_date, col_float32, col_float64, col_int64, " + "col_json, col_numeric, col_string, col_timestamp, col_bool_array, col_bytes_array, " - + "col_date_array, col_float64_array, col_int64_array, col_json_array, col_numeric_array, " - + "col_string_array, col_timestamp_array) values (%s)"; + + "col_date_array, col_float32_array, col_float64_array, col_int64_array, col_json_array," + + "col_numeric_array, col_string_array, col_timestamp_array) values (%s)"; String jdbcSql = String.format( baseSql, - IntStream.range(0, 18).mapToObj(ignored -> "?").collect(Collectors.joining(", "))); + IntStream.range(0, 20).mapToObj(ignored -> "?").collect(Collectors.joining(", "))); String googleSql = String.format( baseSql, - IntStream.range(1, 19) + IntStream.range(1, 21) .mapToObj(index -> "@p" + index) .collect(Collectors.joining(", "))); mockSpanner.putStatementResult( @@ -89,7 +89,7 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { try (Connection connection = createJdbcConnection()) { try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) { ParameterMetaData metadata = statement.getParameterMetaData(); - assertEquals(18, metadata.getParameterCount()); + assertEquals(20, metadata.getParameterCount()); int index = 0; assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); assertEquals("BOOL", metadata.getParameterTypeName(index)); @@ -97,6 +97,8 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { assertEquals("BYTES", metadata.getParameterTypeName(index)); assertEquals(Types.DATE, metadata.getParameterType(++index)); assertEquals("DATE", metadata.getParameterTypeName(index)); + assertEquals(Types.REAL, metadata.getParameterType(++index)); + assertEquals("FLOAT32", metadata.getParameterTypeName(index)); assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); assertEquals("FLOAT64", metadata.getParameterTypeName(index)); assertEquals(Types.BIGINT, metadata.getParameterType(++index)); @@ -117,6 +119,8 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("ARRAY", metadata.getParameterTypeName(index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("ARRAY", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("ARRAY", metadata.getParameterTypeName(index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("ARRAY", metadata.getParameterTypeName(index)); @@ -166,7 +170,7 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException { try (Connection connection = createJdbcConnection()) { try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) { ParameterMetaData metadata = statement.getParameterMetaData(); - assertEquals(18, metadata.getParameterCount()); + assertEquals(20, metadata.getParameterCount()); int index = 0; assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); assertEquals("boolean", metadata.getParameterTypeName(index)); @@ -174,6 +178,8 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException { assertEquals("bytea", metadata.getParameterTypeName(index)); assertEquals(Types.DATE, metadata.getParameterType(++index)); assertEquals("date", metadata.getParameterTypeName(index)); + assertEquals(Types.REAL, metadata.getParameterType(++index)); + assertEquals("real", metadata.getParameterTypeName(index)); assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); assertEquals("double precision", metadata.getParameterTypeName(index)); assertEquals(Types.BIGINT, metadata.getParameterType(++index)); @@ -194,6 +200,8 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException { assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("date[]", metadata.getParameterTypeName(index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals("real[]", metadata.getParameterTypeName(index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("double precision[]", metadata.getParameterTypeName(index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("bigint[]", metadata.getParameterTypeName(index)); @@ -229,16 +237,21 @@ static StructType createAllTypesParameters(Dialect dialect) { .addFields( Field.newBuilder() .setName("p4") - .setType(Type.newBuilder().setCode(TypeCode.FLOAT64).build()) + .setType(Type.newBuilder().setCode(TypeCode.FLOAT32).build()) .build()) .addFields( Field.newBuilder() .setName("p5") - .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .setType(Type.newBuilder().setCode(TypeCode.FLOAT64).build()) .build()) .addFields( Field.newBuilder() .setName("p6") + .setType(Type.newBuilder().setCode(TypeCode.INT64).build()) + .build()) + .addFields( + Field.newBuilder() + .setName("p7") .setType( Type.newBuilder() .setCode(TypeCode.JSON) @@ -250,7 +263,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p7") + .setName("p8") .setType( Type.newBuilder() .setCode(TypeCode.NUMERIC) @@ -262,17 +275,17 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p8") + .setName("p9") .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) .build()) .addFields( Field.newBuilder() - .setName("p9") + .setName("p10") .setType(Type.newBuilder().setCode(TypeCode.TIMESTAMP).build()) .build()) .addFields( Field.newBuilder() - .setName("p10") + .setName("p11") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -280,7 +293,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p11") + .setName("p12") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -288,7 +301,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p12") + .setName("p13") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -296,7 +309,15 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p13") + .setName("p14") + .setType( + Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType(Type.newBuilder().setCode(TypeCode.FLOAT32).build())) + .build()) + .addFields( + Field.newBuilder() + .setName("p15") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -304,7 +325,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p14") + .setName("p16") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -312,7 +333,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p15") + .setName("p17") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -327,7 +348,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p16") + .setName("p18") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -342,7 +363,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p17") + .setName("p19") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) @@ -350,7 +371,7 @@ static StructType createAllTypesParameters(Dialect dialect) { .build()) .addFields( Field.newBuilder() - .setName("p18") + .setName("p20") .setType( Type.newBuilder() .setCode(TypeCode.ARRAY) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java new file mode 100644 index 000000000000..4d24068dc01e --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java @@ -0,0 +1,164 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.RandomResultSetGenerator; +import com.google.cloud.spanner.connection.SpannerPool; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +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 RandomResultSetTest 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(dialect)); + RandomResultSetGenerator generator = + new RandomResultSetGenerator(RANDOM_RESULT_SET_ROW_COUNT, dialect); + mockSpanner.putStatementResult( + StatementResult.query(SELECT_RANDOM_STATEMENT, generator.generate())); + } + + @After + public void reset() { + // This ensures that each test gets a fresh Spanner instance. This is necessary to get a new + // dialect result for each connection. + SpannerPool.closeSpannerPool(); + } + + @Test + public void testSelectRandomResults() throws SQLException { + try (Connection connection = createJdbcConnection()) { + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + ResultSetMetaData metadata = resultSet.getMetaData(); + int col = 0; + assertEquals(Types.BOOLEAN, metadata.getColumnType(++col)); + assertEquals(Types.BIGINT, metadata.getColumnType(++col)); + assertEquals(Types.REAL, metadata.getColumnType(++col)); + assertEquals(Types.DOUBLE, metadata.getColumnType(++col)); + assertEquals(Types.NUMERIC, metadata.getColumnType(++col)); + assertEquals(Types.NVARCHAR, metadata.getColumnType(++col)); + assertEquals(Types.NVARCHAR, metadata.getColumnType(++col)); + assertEquals(Types.BINARY, metadata.getColumnType(++col)); + assertEquals(Types.DATE, metadata.getColumnType(++col)); + assertEquals(Types.TIMESTAMP, metadata.getColumnType(++col)); + + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // boolean + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // bigint + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // real + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // double + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // numeric + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // nvarchar + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // nvarchar + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // binary + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // date + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // timestamp + + // GoogleSQL also includes proto columns. + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + // Skip for now, as support for this has not yet been added. + // assertEquals(Types.OTHER, metadata.getColumnType(++col)); + // assertEquals(Types.OTHER, metadata.getColumnType(++col)); + // assertEquals(Types.ARRAY, metadata.getColumnType(++col)); + // assertEquals(Types.ARRAY, metadata.getColumnType(++col)); + col += 4; + } + + assertEquals(col, metadata.getColumnCount()); + + int rowCount = 0; + while (resultSet.next()) { + // Verify that we can get all columns as an object. + for (col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) { + if (dialect == Dialect.GOOGLE_STANDARD_SQL && col > 20) { + // Proto columns are not yet supported, so skipping. + } else if (dialect == Dialect.POSTGRESQL && col == 7) { + // PG_JSONB is not yet recognized by the JDBC driver, so skipping. + } else if (dialect == Dialect.POSTGRESQL && col == 15) { + // getObject for ARRAY tries to get the array as a List. + // That fails if the array contains a NaN, so skipping. + } else { + resultSet.getObject(col); + } + } + + // Verify that we can get the results as the actual type. + col = 0; + resultSet.getBoolean(++col); + resultSet.getLong(++col); + resultSet.getFloat(++col); + resultSet.getDouble(++col); + resultSet.getFloat(++col); + resultSet.getString(++col); + resultSet.getString(++col); // JSON + resultSet.getBytes(++col); + resultSet.getDate(++col); + resultSet.getTimestamp(++col); + + resultSet.getArray(++col); + resultSet.getArray(++col); + resultSet.getArray(++col); + resultSet.getArray(++col); + if (dialect == Dialect.POSTGRESQL) { + // Skipping, as getArray(..) returns an array of BigDecimal for PG_NUMERIC, and that is + // not supported if the array contains a NaN. + ++col; + } else { + resultSet.getArray(++col); + } + resultSet.getArray(++col); + resultSet.getArray(++col); + resultSet.getArray(++col); + resultSet.getArray(++col); + resultSet.getArray(++col); + + // GoogleSQL also includes proto columns. + if (dialect == Dialect.GOOGLE_STANDARD_SQL) { + // Skip for now, as support for this has not yet been added. + col += 4; + } + assertEquals(col, resultSet.getMetaData().getColumnCount()); + + rowCount++; + } + assertEquals(RANDOM_RESULT_SET_ROW_COUNT, rowCount); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index 5527c8b952c6..2198c9464b49 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -227,7 +227,9 @@ public void testPreparedStatement() throws Exception { preparedStatement.setShort(3, (short) 1); preparedStatement.setInt(4, 1); preparedStatement.setLong(5, 1L); - preparedStatement.setFloat(6, 1F); + // TODO: Change to setFloat(..) when float32 is supported. + // preparedStatement.setFloat(6, 1f); + preparedStatement.setDouble(6, 1d); preparedStatement.setDouble(7, 1D); preparedStatement.setBigDecimal(8, new BigDecimal("1")); preparedStatement.setObject(9, (byte) 1); @@ -239,7 +241,9 @@ public void testPreparedStatement() throws Exception { preparedStatement.setObject(15, new BigDecimal("1")); preparedStatement.setObject(16, Value.pgNumeric("1")); - preparedStatement.setFloat(17, Float.NaN); + // TODO: Change to setFloat(..) when float32 is supported. + // preparedStatement.setFloat(17, Float.NaN); + preparedStatement.setDouble(17, Double.NaN); preparedStatement.setDouble(18, Double.NaN); preparedStatement.setObject(19, Value.pgNumeric("NaN")); From 9753d08ad967ee5250d035dc978d165a01256576 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:08:16 +0100 Subject: [PATCH 1206/1979] chore(main): release 2.16.0 (#1515) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d4d5f25814c7..db9160047552 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.16.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.5...v2.16.0) (2024-03-07) + + +### Features + +* Support float32 ([#1518](https://github.com/googleapis/java-spanner-jdbc/issues/1518)) ([635ac41](https://github.com/googleapis/java-spanner-jdbc/commit/635ac41e054814cf3b58d37cbc42b01ac183b2a1)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.27.0 ([#1521](https://github.com/googleapis/java-spanner-jdbc/issues/1521)) ([a8eecfb](https://github.com/googleapis/java-spanner-jdbc/commit/a8eecfb3a731505ba309b4a359dea7b88990c88a)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.60.1 ([#1514](https://github.com/googleapis/java-spanner-jdbc/issues/1514)) ([cf8fe9e](https://github.com/googleapis/java-spanner-jdbc/commit/cf8fe9eea2423f64867c9ecd790916b81165e575)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.61.0 ([#1523](https://github.com/googleapis/java-spanner-jdbc/issues/1523)) ([0c1e281](https://github.com/googleapis/java-spanner-jdbc/commit/0c1e28177131f30405b09cf38fa7a78645a3508a)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.27.0 ([#1522](https://github.com/googleapis/java-spanner-jdbc/issues/1522)) ([28986f9](https://github.com/googleapis/java-spanner-jdbc/commit/28986f9dddabfe2d89b2e3155885434413c3941e)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.23 ([#1527](https://github.com/googleapis/java-spanner-jdbc/issues/1527)) ([1e7a4f7](https://github.com/googleapis/java-spanner-jdbc/commit/1e7a4f73339479134868206730c275fe752e8d0d)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.3 ([#1512](https://github.com/googleapis/java-spanner-jdbc/issues/1512)) ([e5825c9](https://github.com/googleapis/java-spanner-jdbc/commit/e5825c9a4aa9df68b1ca911430ef37cb6d3549c4)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.3 ([#1513](https://github.com/googleapis/java-spanner-jdbc/issues/1513)) ([8cfaa1a](https://github.com/googleapis/java-spanner-jdbc/commit/8cfaa1a523c32ebed307f747fd939bd900c28b34)) + ## [2.15.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.4...v2.15.5) (2024-02-21) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9b9a6fb8a3d1..5ee420fc8e8a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.15.6-SNAPSHOT + 2.16.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 832a1bf1f3f6..319b7d2f8e33 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.6-SNAPSHOT + 2.16.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a6e48e1b81c6..b03866d33cb9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.15.5:2.15.6-SNAPSHOT +google-cloud-spanner-jdbc:2.16.0:2.16.0 From caea945bbb25e3b4472b10d1a4915d771ef0bf53 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:22:16 +0000 Subject: [PATCH 1207/1979] chore(main): release 2.16.1-SNAPSHOT (#1528) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5ee420fc8e8a..25830373048f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.0 + 2.16.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 319b7d2f8e33..37e5d923438f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.0 + 2.16.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b03866d33cb9..9fcb342c986c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.0:2.16.0 +google-cloud-spanner-jdbc:2.16.0:2.16.1-SNAPSHOT From 0fd9b7d57810aac503fcb2950533746d97ee037d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 8 Mar 2024 14:01:08 +0100 Subject: [PATCH 1208/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.16.0 (#1529) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0fabc41fb449..a52052ae6f21 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.15.5 + 2.16.0 From 822d0219c17e501b5bccd1d93550f99f7256c864 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 8 Mar 2024 14:01:28 +0100 Subject: [PATCH 1209/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.34.0 (#1530) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 57231a4c770d..6c96387334a8 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.33.0 + 26.34.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 79af944277d6..5900dc78f847 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.33.0 + 26.34.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index ef02f014a019..f0c8a5183fd7 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.33.0 + 26.34.0 import pom From 3a0e8dc4554d22d180e20cf06f8dff4ff38b808b Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:26:32 -0400 Subject: [PATCH 1210/1979] chore: restore sdk-platform-java-config changes (#1531) --- java-spanner-jdbc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 25830373048f..ca1808449444 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -13,8 +13,8 @@ com.google.cloud - google-cloud-shared-config - 1.7.4 + sdk-platform-java-config + 3.27.0 @@ -69,7 +69,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.27.0 + ${google-cloud-shared-dependencies.version} pom import From ee3ec2dede8a3e0e3484395d77321327725b2945 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Mar 2024 11:46:41 +0100 Subject: [PATCH 1211/1979] deps: update dependency org.postgresql:postgresql to v42.7.3 (#1532) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5900dc78f847..ce3d03ba2825 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -52,7 +52,7 @@ org.postgresql postgresql - 42.7.2 + 42.7.3 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index f0c8a5183fd7..7f9afd554b92 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.7.2 + 42.7.3 From 2c55fed9c49bd8c796023c16682728ceef0316d5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Mar 2024 17:18:35 +0100 Subject: [PATCH 1212/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.1.4 (#1533) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ce3d03ba2825..4f08d2a6f470 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.1.3 + 2023.1.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 7f9afd554b92..eeb4c66e0d06 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.1.3 + 2023.1.4 import pom From c67b7535dd93199813d64bdc2efa4843b6a2c1ee Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:19:03 +0100 Subject: [PATCH 1213/1979] chore: update requirements.txt to address dependabot security alerts. (#1936) (#1535) Created by running: pip-compile requirements.in --generate-hashes --upgrade within synthtool/gcp/templates/java_library/.kokoro and synthtool/docker/owlbot/java/src/ Source-Link: https://github.com/googleapis/synthtool/commit/853dbcd49ea3598fd896007dc48dc97175ee88f1 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:084ad4c60551b075846bcb2405ec1c14b0d00ec1eb5503d4dd0d2a92cdc2d3e2 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/renovate.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index bf48c82da143..db1099bec8e3 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:0d1bb26a1a99ae0456176bf891b8490e9aab424a5cb4e4d301d9703c4dc43b58 -# created: 2024-01-30T19:46:55.029238294Z + digest: sha256:084ad4c60551b075846bcb2405ec1c14b0d00ec1eb5503d4dd0d2a92cdc2d3e2 +# created: 2024-03-15T14:33:32.257974519Z diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index fe0d0ccdb3f1..15ce4ecae61c 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -66,7 +66,8 @@ "^com.google.truth:truth", "^org.mockito:mockito-core", "^org.objenesis:objenesis", - "^com.google.cloud:google-cloud-conformance-tests" + "^com.google.cloud:google-cloud-conformance-tests", + "^org.graalvm.buildtools:junit-platform-native" ], "semanticCommitType": "test", "semanticCommitScope": "deps" From a2c6a110878e22a799f64d004e9036972f11b5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 20 Mar 2024 09:20:18 +0100 Subject: [PATCH 1214/1979] deps: bump Spanner client to 6.62.0 (#1539) Bumping both Spanner client to 6.62.0 and cloud-sdk-java-config to 3.28.1 at the same time, as bumping them separately causes dependency issues. --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ca1808449444..9a115e2c619e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.27.0 + 3.28.1 @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.61.0 + 6.62.0 pom import From 114c5942a7cdedcbfade8ffcd41c4c20c98e2b13 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Mar 2024 15:09:41 +0100 Subject: [PATCH 1215/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.28.1 (#1537) --- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 56db68092d21..c2a88196e84d 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.27.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.28.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 6283184778e7..94e00cbaa0a1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.27.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.28.1" } env_vars: { From 0fbf88465b52fec400110d2a022c50e2d0cf65ab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Mar 2024 13:59:21 +0100 Subject: [PATCH 1216/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.4 (#1540) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 4f08d2a6f470..34664f77be6f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.2.3 + 3.2.4 From 90cb755ba6b4422cf6efca88caca8bb970bf8458 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Mar 2024 13:59:37 +0100 Subject: [PATCH 1217/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.4 (#1541) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index eeb4c66e0d06..4f8dccf9d3fd 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.3 + 3.2.4 From a2f126733d36fedbd3179e7a37901ed07da5fcd2 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 22 Mar 2024 14:10:16 +0000 Subject: [PATCH 1218/1979] chore(main): release 2.16.1 (#1534) :robot: I have created a release *beep* *boop* --- ## [2.16.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.16.0...v2.16.1) (2024-03-22) ### Dependencies * Bump Spanner client to 6.62.0 ([#1539](https://togithub.com/googleapis/java-spanner-jdbc/issues/1539)) ([a2c6a11](https://togithub.com/googleapis/java-spanner-jdbc/commit/a2c6a110878e22a799f64d004e9036972f11b5fd)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.28.1 ([#1537](https://togithub.com/googleapis/java-spanner-jdbc/issues/1537)) ([114c594](https://togithub.com/googleapis/java-spanner-jdbc/commit/114c5942a7cdedcbfade8ffcd41c4c20c98e2b13)) * Update dependency org.postgresql:postgresql to v42.7.3 ([#1532](https://togithub.com/googleapis/java-spanner-jdbc/issues/1532)) ([ee3ec2d](https://togithub.com/googleapis/java-spanner-jdbc/commit/ee3ec2dede8a3e0e3484395d77321327725b2945)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.4 ([#1540](https://togithub.com/googleapis/java-spanner-jdbc/issues/1540)) ([0fbf884](https://togithub.com/googleapis/java-spanner-jdbc/commit/0fbf88465b52fec400110d2a022c50e2d0cf65ab)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.4 ([#1541](https://togithub.com/googleapis/java-spanner-jdbc/issues/1541)) ([90cb755](https://togithub.com/googleapis/java-spanner-jdbc/commit/90cb755ba6b4422cf6efca88caca8bb970bf8458)) * Update dependency org.springframework.data:spring-data-bom to v2023.1.4 ([#1533](https://togithub.com/googleapis/java-spanner-jdbc/issues/1533)) ([2c55fed](https://togithub.com/googleapis/java-spanner-jdbc/commit/2c55fed9c49bd8c796023c16682728ceef0316d5)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index db9160047552..fd7acea519e7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.16.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.0...v2.16.1) (2024-03-22) + + +### Dependencies + +* Bump Spanner client to 6.62.0 ([#1539](https://github.com/googleapis/java-spanner-jdbc/issues/1539)) ([ca274fb](https://github.com/googleapis/java-spanner-jdbc/commit/ca274fb22cbbb974fe71fffbe9f8c3a56f40628c)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.28.1 ([#1537](https://github.com/googleapis/java-spanner-jdbc/issues/1537)) ([4d1d38e](https://github.com/googleapis/java-spanner-jdbc/commit/4d1d38ea4312d637d1cad61b8230d12cdbf0ba51)) +* Update dependency org.postgresql:postgresql to v42.7.3 ([#1532](https://github.com/googleapis/java-spanner-jdbc/issues/1532)) ([b09da60](https://github.com/googleapis/java-spanner-jdbc/commit/b09da609950b94157564f4f9987a3ce60221568e)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.4 ([#1540](https://github.com/googleapis/java-spanner-jdbc/issues/1540)) ([21faff8](https://github.com/googleapis/java-spanner-jdbc/commit/21faff8d72ad209835971162caadb694c602175d)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.4 ([#1541](https://github.com/googleapis/java-spanner-jdbc/issues/1541)) ([2c76488](https://github.com/googleapis/java-spanner-jdbc/commit/2c76488e5e80ecad2824311ed399142495bfc2e4)) +* Update dependency org.springframework.data:spring-data-bom to v2023.1.4 ([#1533](https://github.com/googleapis/java-spanner-jdbc/issues/1533)) ([ec7d3b0](https://github.com/googleapis/java-spanner-jdbc/commit/ec7d3b04fd0bf97ea17ebd1849d02fdfdb31ded3)) + ## [2.16.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.15.5...v2.16.0) (2024-03-07) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9a115e2c619e..0d3858e851a8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.1-SNAPSHOT + 2.16.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 37e5d923438f..2cf73702e096 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.1-SNAPSHOT + 2.16.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9fcb342c986c..5aa7bb71c6e5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.0:2.16.1-SNAPSHOT +google-cloud-spanner-jdbc:2.16.1:2.16.1 From 4c4fe57c138f7b185cf148f657dff62d2cee448b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 22 Mar 2024 15:24:16 +0000 Subject: [PATCH 1219/1979] chore(main): release 2.16.2-SNAPSHOT (#1542) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0d3858e851a8..841d2648bda1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.1 + 2.16.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2cf73702e096..baaf8bb8916b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.1 + 2.16.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5aa7bb71c6e5..21a50e390060 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.1:2.16.1 +google-cloud-spanner-jdbc:2.16.1:2.16.2-SNAPSHOT From 889aacdce69b63774a8cc593b952a3cc436cec20 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 25 Mar 2024 16:19:10 +0100 Subject: [PATCH 1220/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.16.1 (#1543) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a52052ae6f21..a2537a7e645c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.0 + 2.16.1 From a65430b71e031b8e5e7918d6e19638d3c7df6a82 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 20:43:15 +0100 Subject: [PATCH 1221/1979] chore: update ignore paths in renovate config (#1945) (#1545) Source-Link: https://github.com/googleapis/synthtool/commit/571a0916913e0aff0f66ca513514072893d534eb Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:81c3ec554428c8ff6c92f0d58668b7ef52265d053a82284c97a326745e786949 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/renovate.json | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index db1099bec8e3..6167135e9534 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:084ad4c60551b075846bcb2405ec1c14b0d00ec1eb5503d4dd0d2a92cdc2d3e2 -# created: 2024-03-15T14:33:32.257974519Z + digest: sha256:81c3ec554428c8ff6c92f0d58668b7ef52265d053a82284c97a326745e786949 +# created: 2024-03-27T17:59:25.436353226Z diff --git a/java-spanner-jdbc/renovate.json b/java-spanner-jdbc/renovate.json index 15ce4ecae61c..d47519b156c4 100644 --- a/java-spanner-jdbc/renovate.json +++ b/java-spanner-jdbc/renovate.json @@ -12,7 +12,10 @@ ], "ignorePaths": [ ".kokoro/requirements.txt", - ".github/workflows/**" + ".github/workflows/approve-readme.yaml", + ".github/workflows/ci.yaml", + ".github/workflows/renovate_config_check.yaml", + ".github/workflows/samples.yaml" ], "customManagers": [ { @@ -23,6 +26,15 @@ "matchStrings": ["value: \"gcr.io/cloud-devrel-public-resources/graalvm.*:(?.*?)\""], "depNameTemplate": "com.google.cloud:sdk-platform-java-config", "datasourceTemplate": "maven" + }, + { + "customType": "regex", + "fileMatch": [ + "^.github/workflows/unmanaged_dependency_check.yaml$" + ], + "matchStrings": ["uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v(?.+?)\\n"], + "depNameTemplate": "com.google.cloud:sdk-platform-java-config", + "datasourceTemplate": "maven" } ], "packageRules": [ From 1b9a83c5b59a26d91f91b4abee59d0c921aa198d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Apr 2024 08:41:03 +0200 Subject: [PATCH 1222/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.35.0 (#1551) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6c96387334a8..f36192293645 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.34.0 + 26.35.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 34664f77be6f..4d35a208729d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.34.0 + 26.35.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 4f8dccf9d3fd..1ec0e4b9287e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.34.0 + 26.35.0 import pom From a9252a5844dc2a1fd4e057c4e6806ea3f0baf71f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Apr 2024 08:41:30 +0200 Subject: [PATCH 1223/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.63.0 (#1552) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 841d2648bda1..38d49832b0c4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.62.0 + 6.63.0 pom import From 8a040b6791e53debfa37149cca0216921bf2291f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Apr 2024 09:01:25 +0200 Subject: [PATCH 1224/1979] deps: update actions/checkout digest to b4ffde6 (#1546) --- .../.github/workflows/integration-tests-against-emulator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index f299be4f9cb5..eff700ea5268 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -16,7 +16,7 @@ jobs: - 9020:9020 steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - uses: stCarolas/setup-maven@v4 with: maven-version: 3.8.1 From 0d3fe89af83479d3a6a50e187c46bb8fa4c6a8a1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Apr 2024 09:01:48 +0200 Subject: [PATCH 1225/1979] deps: update actions/checkout action to v4 (#1547) --- .../.github/workflows/spring-data-jdbc-sample.yaml | 2 +- .../.github/workflows/spring-data-mybatis-sample.yaml | 2 +- .../.github/workflows/unmanaged-dependency-check.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index 028a486318ce..fc488ab89143 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-jdbc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index 39be0e6e6a47..636f71258c9a 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-jdbc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml index 4ca518aea539..a8a2e2ee3d8b 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml @@ -5,7 +5,7 @@ jobs: unmanaged_dependency_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin From 0f8dd26d76931988df8dc36060087cbc40ffb0b6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 1 Apr 2024 09:02:14 +0200 Subject: [PATCH 1226/1979] deps: update actions/github-script action to v7 (#1548) --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 7a106d007edf..18d92e5a28dd 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest if: contains(github.head_ref, 'release-please') steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} debug: true From 0771d260174065e84a68abd0543c3fc9edf1867d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 4 Apr 2024 17:42:18 +0200 Subject: [PATCH 1227/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.36.0 (#1555) 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.35.0` -> `26.36.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.35.0/26.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.35.0/26.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.36.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26360-2024-04-03) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.35.0...v26.36.0) ##### Dependencies - update dependency com.google.cloud:gapic-libraries-bom to v1.34.0 ([#​6519](https://togithub.com/googleapis/java-cloud-bom/issues/6519)) ([602ba0c](https://togithub.com/googleapis/java-cloud-bom/commit/602ba0c894123089b0c8eb297d32c638265ccf03))
    --- ### 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f36192293645..dfe37f9db182 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.35.0 + 26.36.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 4d35a208729d..ed88ebf92d40 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.35.0 + 26.36.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 1ec0e4b9287e..4aeb753802d5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.35.0 + 26.36.0 import pom From c4150552c033d7e8d411f77b610061fbf00655fa Mon Sep 17 00:00:00 2001 From: Joe Wang <106995533+JoeWang1127@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:41:24 +0000 Subject: [PATCH 1228/1979] chore: update version of unmanaged dependency check (#1556) --- ...ed-dependency-check.yaml => unmanaged_dependency_check.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename java-spanner-jdbc/.github/workflows/{unmanaged-dependency-check.yaml => unmanaged_dependency_check.yaml} (87%) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml similarity index 87% rename from java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml rename to java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index a8a2e2ee3d8b..4406831cb721 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged-dependency-check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@unmanaged-dependencies-check-latest + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.28.1 with: bom-path: pom.xml From 91578b093512cc497985d25767990953c4c12c59 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 5 Apr 2024 06:59:37 +0200 Subject: [PATCH 1229/1979] deps: update stcarolas/setup-maven action to v5 (#1550) --- .../.github/workflows/integration-tests-against-emulator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index eff700ea5268..0a330e1a8932 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - - uses: stCarolas/setup-maven@v4 + - uses: stCarolas/setup-maven@v5 with: maven-version: 3.8.1 - uses: actions/setup-java@v1 From 256479622d2e8df41e24bb977eb6bc5e57279919 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 5 Apr 2024 09:57:31 +0200 Subject: [PATCH 1230/1979] deps: update actions/setup-java action to v4 (#1549) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update actions/setup-java action to v4 * build: add distribution + actual version number * build: remove redundant Maven setup --------- Co-authored-by: Knut Olav Løite --- .../workflows/integration-tests-against-emulator.yaml | 8 +++----- .../.github/workflows/spring-data-jdbc-sample.yaml | 2 +- .../.github/workflows/spring-data-mybatis-sample.yaml | 2 +- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index 0a330e1a8932..ccf1ebd1fd66 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -16,12 +16,10 @@ jobs: - 9020:9020 steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - - uses: stCarolas/setup-maven@v5 - with: - maven-version: 3.8.1 - - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: + distribution: temurin java-version: 8 - run: java -version - run: .kokoro/build.sh diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index fc488ab89143..0185a2905d78 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index 636f71258c9a..5267d6f599f2 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 4406831cb721..c724f3dab88c 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 From da6c7ffbe05ab744de2fe01e433e74ee29ae157e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 5 Apr 2024 19:08:00 +0200 Subject: [PATCH 1231/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.37.0 (#1557) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index dfe37f9db182..29bc0371c1f3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.36.0 + 26.37.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ed88ebf92d40..c9fbf898de18 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.36.0 + 26.37.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 4aeb753802d5..16e8c3d3792d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.36.0 + 26.37.0 import pom From 4bd8aa40c27a0628b8a2197bba5ffe0a6c268079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 9 Apr 2024 14:07:54 +0200 Subject: [PATCH 1232/1979] chore: add connection helper to get Spanner instance (#1558) Add a connection helper to get the underlying Spanner instance. This helper will be removed once the getSpanner() method has been made public in the Java client library. --- .../spanner/connection/ConnectionHelper.java | 31 +++++++++++++++++++ .../spanner/jdbc/AbstractJdbcConnection.java | 6 ++++ 2 files changed, 37 insertions(+) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java new file mode 100644 index 000000000000..5f71ec605b6a --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.connection; + +import com.google.cloud.spanner.Spanner; + +/** Static helper class to get the {@link Spanner} instance from the underlying connection. */ +public class ConnectionHelper { + + /** Private constructor to prevent instantiation. */ + private ConnectionHelper() {} + + public static Spanner getSpanner(Connection connection) { + // TODO: Remove once getSpanner() has been added to the public interface. + return ((ConnectionImpl) connection).getSpanner(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 33cf3bc574a0..340b6d40964f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -17,8 +17,10 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.AbstractStatementParser; +import com.google.cloud.spanner.connection.ConnectionHelper; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; @@ -78,6 +80,10 @@ ConnectionOptions getConnectionOptions() { return options; } + Spanner getSpanner() { + return ConnectionHelper.getSpanner(this.spanner); + } + @Override public Dialect getDialect() { return spanner.getDialect(); From 1c5178e2ab2b363ecfaf55d161245002c3f47c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 10 Apr 2024 14:28:02 +0200 Subject: [PATCH 1233/1979] docs: create samples for quickstart guide (#1536) * docs: create samples for quickstart guide * docs: add createConnection sample * docs: add sample for DML * docs: add sample for mutations * feat: add dml batch sample * feat: add more samples * feat: add more samples * feat: add data boost sample * chore: fix style * chore: add run commands * fix: shorten method length * test: add sample test runner * fix: duplicate name * chore: fix tag prefix * chore: add more commands * feat: add sample for emulator * feat: add tagging sample * chore: use fixed port binding for now * chore: remove changes to JdbcDriver --- .../.github/workflows/sample-tests.yml | 30 + .../samples/snippets/java.header | 15 + .../samples/snippets/license-checks.xml | 10 + java-spanner-jdbc/samples/snippets/pom.xml | 92 +- .../com/example/spanner/jdbc/JdbcSample.java | 1830 +++++++++++++++++ .../example/spanner/jdbc/package-info.java | 18 + .../example/spanner/jdbc/JdbcSampleTest.java | 396 ++++ 7 files changed, 2382 insertions(+), 9 deletions(-) create mode 100644 java-spanner-jdbc/.github/workflows/sample-tests.yml create mode 100644 java-spanner-jdbc/samples/snippets/java.header create mode 100644 java-spanner-jdbc/samples/snippets/license-checks.xml create mode 100644 java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java create mode 100644 java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/package-info.java create mode 100644 java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml new file mode 100644 index 000000000000..cec19c7a2c1d --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -0,0 +1,30 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Github action job to test core java library features on +# downstream client libraries before they are released. +on: + pull_request: +name: samples +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 8 + - name: Run sample tests + run: mvn --quiet --batch-mode test + working-directory: samples/snippets diff --git a/java-spanner-jdbc/samples/snippets/java.header b/java-spanner-jdbc/samples/snippets/java.header new file mode 100644 index 000000000000..d0970ba7d375 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/java.header @@ -0,0 +1,15 @@ +^/\*$ +^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)$ +^ \*$ +^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ +^ \* you may not use this file except in compliance with the License\.$ +^ \* You may obtain a copy of the License at$ +^ \*$ +^ \*[ ]+https?://www.apache.org/licenses/LICENSE-2\.0$ +^ \*$ +^ \* Unless required by applicable law or agreed to in writing, software$ +^ \* distributed under the License is distributed on an "AS IS" BASIS,$ +^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ +^ \* See the License for the specific language governing permissions and$ +^ \* limitations under the License\.$ +^ \*/$ diff --git a/java-spanner-jdbc/samples/snippets/license-checks.xml b/java-spanner-jdbc/samples/snippets/license-checks.xml new file mode 100644 index 000000000000..a7a61194058d --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/license-checks.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 29bc0371c1f3..047c0c761440 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -1,20 +1,16 @@ 4.0.0 - com.google.cloud spanner-jdbc-snippets jar Google Google Cloud Spanner JDBC Snippets https://github.com/googleapis/java-spanner-jdbc - - com.google.cloud.samples - shared-configuration - 1.2.0 + com.google.cloud + sdk-platform-java-config + 3.27.0 + @@ -42,6 +38,84 @@ com.google.cloud google-cloud-spanner-jdbc
    + + + + com.google.cloud + google-cloud-spanner + + + + org.testcontainers + testcontainers + 1.19.7 + test + + + junit + junit + 4.13.2 + test + - + + + + + maven-resources-plugin + + + copy-resources + validate + + copy-resources + + + ${project.build.directory}/jdbc-snippets + + + resources + true + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/jdbc-snippets/lib + false + false + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + jdbc-snippets/jdbc-samples + + false + + com.example.spanner.jdbc.JdbcSample + true + lib/ + + + + + + diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java new file mode 100644 index 000000000000..2e46058de4e4 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java @@ -0,0 +1,1830 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.spanner.jdbc; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.DatabaseDialect; +import com.google.spanner.admin.instance.v1.InstanceName; +import com.google.spanner.v1.DatabaseName; +import io.grpc.ManagedChannelBuilder; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ExecutionException; + +public final class JdbcSample { + static class Singer { + + /** Primary key in the Singers table. */ + private final long singerId; + + /** Mapped to the FirstName column. */ + private final String firstName; + + /** Mapped to the FirstName column. */ + private final String lastName; + + Singer(final long id, final String first, final String last) { + this.singerId = id; + this.firstName = first; + this.lastName = last; + } + + public long getSingerId() { + return singerId; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + } + + static class Album { + + /** The first part of the primary key of Albums. */ + private final long singerId; + + /** The second part of the primary key of Albums. */ + private final long albumId; + + /** Mapped to the AlbumTitle column. */ + private final String albumTitle; + + Album(final long singer, final long album, final String title) { + this.singerId = singer; + this.albumId = album; + this.albumTitle = title; + } + + public long getSingerId() { + return singerId; + } + + public long getAlbumId() { + return albumId; + } + + public String getAlbumTitle() { + return albumTitle; + } + } + + // [START spanner_insert_data] + // [START spanner_postgresql_insert_data] + /** The list of Singers to insert. */ + static final List SINGERS = + Arrays.asList( + new Singer(1, "Marc", "Richards"), + new Singer(2, "Catalina", "Smith"), + new Singer(3, "Alice", "Trentor"), + new Singer(4, "Lea", "Martin"), + new Singer(5, "David", "Lomond")); + + /** The list of Albums to insert. */ + static final List ALBUMS = + Arrays.asList( + new Album(1, 1, "Total Junk"), + new Album(1, 2, "Go, Go, Go"), + new Album(2, 1, "Green"), + new Album(2, 2, "Forever Hold Your Peace"), + new Album(2, 3, "Terrified")); + + // [END spanner_insert_data] + // [END spanner_postgresql_insert_data] + + private JdbcSample() { + } + + // [START spanner_create_database] + static void createDatabase( + final DatabaseAdminClient dbAdminClient, + final InstanceName instanceName, + final String databaseId, + final Properties properties) throws SQLException { + // Use the Spanner admin client to create a database. + CreateDatabaseRequest createDatabaseRequest = + CreateDatabaseRequest.newBuilder() + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setParent(instanceName.toString()) + .build(); + try { + dbAdminClient.createDatabaseAsync(createDatabaseRequest).get(); + } catch (ExecutionException e) { + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + throw SpannerExceptionFactory.propagateInterrupt(e); + } + + // Connect to the database with the JDBC driver and create two test tables. + String projectId = instanceName.getProject(); + String instanceId = instanceName.getInstance(); + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId), + properties)) { + try (Statement statement = connection.createStatement()) { + // Create the tables in one batch. + statement.addBatch( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)," + + " FullName STRING(2048) AS " + + " (ARRAY_TO_STRING([FirstName, LastName], \" \")) STORED" + + ") PRIMARY KEY (SingerId)"); + statement.addBatch( + "CREATE TABLE Albums (" + + " SingerId INT64 NOT NULL," + + " AlbumId INT64 NOT NULL," + + " AlbumTitle STRING(MAX)" + + ") PRIMARY KEY (SingerId, AlbumId)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"); + statement.executeBatch(); + } + } + System.out.printf( + "Created database [%s]\n", + DatabaseName.of(projectId, instanceId, databaseId)); + } + // [END spanner_create_database] + + // [START spanner_postgresql_create_database] + static void createPostgreSQLDatabase( + final DatabaseAdminClient dbAdminClient, + final InstanceName instanceName, + final String databaseId, + final Properties properties) throws SQLException { + // Use the Spanner admin client to create a database. + CreateDatabaseRequest createDatabaseRequest = + CreateDatabaseRequest.newBuilder() + // PostgreSQL database names and other identifiers + // must be quoted using double quotes. + .setCreateStatement("create database \"" + databaseId + "\"") + .setParent(instanceName.toString()) + .setDatabaseDialect(DatabaseDialect.POSTGRESQL) + .build(); + try { + dbAdminClient.createDatabaseAsync(createDatabaseRequest).get(); + } catch (ExecutionException e) { + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + throw SpannerExceptionFactory.propagateInterrupt(e); + } + + // Connect to the database with the JDBC driver and create two test tables. + String projectId = instanceName.getProject(); + String instanceId = instanceName.getInstance(); + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId), + properties)) { + try (Statement statement = connection.createStatement()) { + // Create the tables in one batch. + statement.addBatch( + "create table singers (" + + " singer_id bigint primary key not null," + + " first_name varchar(1024)," + + " last_name varchar(1024)," + + " singer_info bytea," + + " full_name varchar(2048) generated always as (\n" + + " case when first_name is null then last_name\n" + + " when last_name is null then first_name\n" + + " else first_name || ' ' || last_name\n" + + " end) stored" + + ")"); + statement.addBatch( + "create table albums (" + + " singer_id bigint not null," + + " album_id bigint not null," + + " album_title varchar," + + " primary key (singer_id, album_id)" + + ") interleave in parent singers on delete cascade"); + statement.executeBatch(); + } + } + System.out.printf( + "Created database [%s]\n", + DatabaseName.of(projectId, instanceId, databaseId)); + } + // [END spanner_postgresql_create_database] + + // [START spanner_create_jdbc_connection] + static void createConnection( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + // Connection properties can be specified both with in a Properties object + // and in the connection URL. + properties.put("numChannels", "8"); + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s" + + ";minSessions=400;maxSessions=400", + project, instance, database), + properties)) { + try (ResultSet resultSet = + connection.createStatement().executeQuery("select 'Hello World!'")) { + while (resultSet.next()) { + System.out.println(resultSet.getString(1)); + } + } + } + } + // [END spanner_create_jdbc_connection] + + // [START spanner_create_jdbc_connection_with_emulator] + static void createConnectionWithEmulator( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + // Add autoConfigEmulator=true to the connection URL to instruct the JDBC + // driver to connect to the Spanner emulator on localhost:9010. + // The Spanner instance and database are automatically created if these + // don't already exist. + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s" + + ";autoConfigEmulator=true", + project, instance, database), + properties)) { + try (ResultSet resultSet = + connection.createStatement().executeQuery("select 'Hello World!'")) { + while (resultSet.next()) { + System.out.println(resultSet.getString(1)); + } + } + } + } + // [END spanner_create_jdbc_connection_with_emulator] + + // [START spanner_dml_getting_started_insert] + static void writeDataWithDml( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Add 4 rows in one statement. + // JDBC always uses '?' as a parameter placeholder. + try (PreparedStatement preparedStatement = + connection.prepareStatement( + "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES " + + "(?, ?, ?), " + + "(?, ?, ?), " + + "(?, ?, ?), " + + "(?, ?, ?)")) { + + final ImmutableList singers = + ImmutableList.of( + new Singer(/* SingerId = */ 12L, "Melissa", "Garcia"), + new Singer(/* SingerId = */ 13L, "Russel", "Morales"), + new Singer(/* SingerId = */ 14L, "Jacqueline", "Long"), + new Singer(/* SingerId = */ 15L, "Dylan", "Shaw")); + + // Note that JDBC parameters start at index 1. + int paramIndex = 0; + for (Singer singer : singers) { + preparedStatement.setLong(++paramIndex, singer.singerId); + preparedStatement.setString(++paramIndex, singer.firstName); + preparedStatement.setString(++paramIndex, singer.lastName); + } + + int updateCount = preparedStatement.executeUpdate(); + System.out.printf("%d records inserted.\n", updateCount); + } + } + } + // [END spanner_dml_getting_started_insert] + + // [START spanner_postgresql_dml_getting_started_insert] + static void writeDataWithDmlPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Add 4 rows in one statement. + // JDBC always uses '?' as a parameter placeholder. + try (PreparedStatement preparedStatement = + connection.prepareStatement( + "INSERT INTO singers (singer_id, first_name, last_name) VALUES " + + "(?, ?, ?), " + + "(?, ?, ?), " + + "(?, ?, ?), " + + "(?, ?, ?)")) { + + final ImmutableList singers = + ImmutableList.of( + new Singer(/* SingerId = */ 12L, "Melissa", "Garcia"), + new Singer(/* SingerId = */ 13L, "Russel", "Morales"), + new Singer(/* SingerId = */ 14L, "Jacqueline", "Long"), + new Singer(/* SingerId = */ 15L, "Dylan", "Shaw")); + + // Note that JDBC parameters start at index 1. + int paramIndex = 0; + for (Singer singer : singers) { + preparedStatement.setLong(++paramIndex, singer.singerId); + preparedStatement.setString(++paramIndex, singer.firstName); + preparedStatement.setString(++paramIndex, singer.lastName); + } + + int updateCount = preparedStatement.executeUpdate(); + System.out.printf("%d records inserted.\n", updateCount); + } + } + } + // [END spanner_postgresql_dml_getting_started_insert] + + // [START spanner_dml_batch] + static void writeDataWithDmlBatch( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Add multiple rows in one DML batch. + // JDBC always uses '?' as a parameter placeholder. + try (PreparedStatement preparedStatement = + connection.prepareStatement( + "INSERT INTO Singers (SingerId, FirstName, LastName) " + + "VALUES (?, ?, ?)")) { + final ImmutableList singers = + ImmutableList.of( + new Singer(/* SingerId = */ 16L, "Sarah", "Wilson"), + new Singer(/* SingerId = */ 17L, "Ethan", "Miller"), + new Singer(/* SingerId = */ 18L, "Maya", "Patel")); + + for (Singer singer : singers) { + // Note that JDBC parameters start at index 1. + int paramIndex = 0; + preparedStatement.setLong(++paramIndex, singer.singerId); + preparedStatement.setString(++paramIndex, singer.firstName); + preparedStatement.setString(++paramIndex, singer.lastName); + preparedStatement.addBatch(); + } + + int[] updateCounts = preparedStatement.executeBatch(); + System.out.printf( + "%d records inserted.\n", + Arrays.stream(updateCounts).sum()); + } + } + } + // [END spanner_dml_batch] + + // [START spanner_postgresql_dml_batch] + static void writeDataWithDmlBatchPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Add multiple rows in one DML batch. + // JDBC always uses '?' as a parameter placeholder. + try (PreparedStatement preparedStatement = + connection.prepareStatement( + "INSERT INTO singers (singer_id, first_name, last_name)" + + " VALUES (?, ?, ?)")) { + final ImmutableList singers = + ImmutableList.of( + new Singer(/* SingerId = */ 16L, "Sarah", "Wilson"), + new Singer(/* SingerId = */ 17L, "Ethan", "Miller"), + new Singer(/* SingerId = */ 18L, "Maya", "Patel")); + + for (Singer singer : singers) { + // Note that JDBC parameters start at index 1. + int paramIndex = 0; + preparedStatement.setLong(++paramIndex, singer.singerId); + preparedStatement.setString(++paramIndex, singer.firstName); + preparedStatement.setString(++paramIndex, singer.lastName); + preparedStatement.addBatch(); + } + + int[] updateCounts = preparedStatement.executeBatch(); + System.out.printf( + "%d records inserted.\n", + Arrays.stream(updateCounts).sum()); + } + } + } + // [END spanner_postgresql_dml_batch] + + // [START spanner_insert_data] + static void writeDataWithMutations( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Unwrap the CloudSpannerJdbcConnection interface + // from the java.sql.Connection. + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + + List mutations = new ArrayList<>(); + for (Singer singer : SINGERS) { + mutations.add( + Mutation.newInsertBuilder("Singers") + .set("SingerId") + .to(singer.singerId) + .set("FirstName") + .to(singer.firstName) + .set("LastName") + .to(singer.lastName) + .build()); + } + for (Album album : ALBUMS) { + mutations.add( + Mutation.newInsertBuilder("Albums") + .set("SingerId") + .to(album.singerId) + .set("AlbumId") + .to(album.albumId) + .set("AlbumTitle") + .to(album.albumTitle) + .build()); + } + // Apply the mutations atomically to Spanner. + cloudSpannerJdbcConnection.write(mutations); + System.out.printf("Inserted %d rows.\n", mutations.size()); + } + } + // [END spanner_insert_data] + + // [START spanner_postgresql_insert_data] + static void writeDataWithMutationsPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Unwrap the CloudSpannerJdbcConnection interface + // from the java.sql.Connection. + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + + List mutations = new ArrayList<>(); + for (Singer singer : SINGERS) { + mutations.add( + Mutation.newInsertBuilder("singers") + .set("singer_id") + .to(singer.singerId) + .set("first_name") + .to(singer.firstName) + .set("last_name") + .to(singer.lastName) + .build()); + } + for (Album album : ALBUMS) { + mutations.add( + Mutation.newInsertBuilder("albums") + .set("singer_id") + .to(album.singerId) + .set("album_id") + .to(album.albumId) + .set("album_title") + .to(album.albumTitle) + .build()); + } + // Apply the mutations atomically to Spanner. + cloudSpannerJdbcConnection.write(mutations); + System.out.printf("Inserted %d rows.\n", mutations.size()); + } + } + // [END spanner_postgresql_insert_data] + + // [START spanner_query_data] + static void queryData( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT SingerId, AlbumId, AlbumTitle " + + "FROM Albums")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("SingerId"), + resultSet.getLong("AlbumId"), + resultSet.getString("AlbumTitle")); + } + } + } + } + // [END spanner_query_data] + + // [START spanner_postgresql_query_data] + static void queryDataPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT singer_id, album_id, album_title " + + "FROM albums")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("singer_id"), + resultSet.getLong("album_id"), + resultSet.getString("album_title")); + } + } + } + } + // [END spanner_postgresql_query_data] + + // [START spanner_query_with_parameter] + static void queryWithParameter( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (PreparedStatement statement = + connection.prepareStatement( + "SELECT SingerId, FirstName, LastName " + + "FROM Singers " + + "WHERE LastName = ?")) { + statement.setString(1, "Garcia"); + try (ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + System.out.printf( + "%d %s %s\n", + resultSet.getLong("SingerId"), + resultSet.getString("FirstName"), + resultSet.getString("LastName")); + } + } + } + } + } + // [END spanner_query_with_parameter] + + // [START spanner_postgresql_query_with_parameter] + static void queryWithParameterPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (PreparedStatement statement = + connection.prepareStatement( + "SELECT singer_id, first_name, last_name " + + "FROM singers " + + "WHERE last_name = ?")) { + statement.setString(1, "Garcia"); + try (ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + System.out.printf( + "%d %s %s\n", + resultSet.getLong("singer_id"), + resultSet.getString("first_name"), + resultSet.getString("last_name")); + } + } + } + } + } + // [END spanner_postgresql_query_with_parameter] + + // [START spanner_add_column] + static void addColumn( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + connection + .createStatement() + .execute("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"); + System.out.println("Added MarketingBudget column"); + } + } + // [END spanner_add_column] + + // [START spanner_postgresql_add_column] + static void addColumnPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + connection + .createStatement() + .execute("alter table albums add column marketing_budget bigint"); + System.out.println("Added marketing_budget column"); + } + } + // [END spanner_postgresql_add_column] + + // [START spanner_ddl_batch] + static void ddlBatch( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (Statement statement = connection.createStatement()) { + // Create two new tables in one batch. + statement.addBatch( + "CREATE TABLE Venues (" + + " VenueId INT64 NOT NULL," + + " Name STRING(1024)," + + " Description JSON" + + ") PRIMARY KEY (VenueId)"); + statement.addBatch( + "CREATE TABLE Concerts (" + + " ConcertId INT64 NOT NULL," + + " VenueId INT64 NOT NULL," + + " SingerId INT64 NOT NULL," + + " StartTime TIMESTAMP," + + " EndTime TIMESTAMP," + + " CONSTRAINT Fk_Concerts_Venues FOREIGN KEY" + + " (VenueId) REFERENCES Venues (VenueId)," + + " CONSTRAINT Fk_Concerts_Singers FOREIGN KEY" + + " (SingerId) REFERENCES Singers (SingerId)," + + ") PRIMARY KEY (ConcertId)"); + statement.executeBatch(); + } + System.out.println("Added Venues and Concerts tables"); + } + } + // [END spanner_ddl_batch] + + // [START spanner_postgresql_ddl_batch] + static void ddlBatchPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (Statement statement = connection.createStatement()) { + // Create two new tables in one batch. + statement.addBatch( + "CREATE TABLE venues (" + + " venue_id bigint not null primary key," + + " name varchar(1024)," + + " description jsonb" + + ")"); + statement.addBatch( + "CREATE TABLE concerts (" + + " concert_id bigint not null primary key ," + + " venue_id bigint not null," + + " singer_id bigint not null," + + " start_time timestamptz," + + " end_time timestamptz," + + " constraint fk_concerts_venues foreign key" + + " (venue_id) references venues (venue_id)," + + " constraint fk_concerts_singers foreign key" + + " (singer_id) references singers (singer_id)" + + ")"); + statement.executeBatch(); + } + System.out.println("Added venues and concerts tables"); + } + } + // [END spanner_postgresql_ddl_batch] + + // [START spanner_update_data] + static void updateDataWithMutations( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Unwrap the CloudSpannerJdbcConnection interface + // from the java.sql.Connection. + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + + final long marketingBudgetAlbum1 = 100000L; + final long marketingBudgetAlbum2 = 500000L; + // Mutation can be used to update/insert/delete a single row in a table. + // Here we use newUpdateBuilder to create update mutations. + List mutations = + Arrays.asList( + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(1) + .set("AlbumId") + .to(1) + .set("MarketingBudget") + .to(marketingBudgetAlbum1) + .build(), + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(2) + .set("AlbumId") + .to(2) + .set("MarketingBudget") + .to(marketingBudgetAlbum2) + .build()); + // This writes all the mutations to Cloud Spanner atomically. + cloudSpannerJdbcConnection.write(mutations); + System.out.println("Updated albums"); + } + } + // [END spanner_update_data] + + // [START spanner_postgresql_update_data] + static void updateDataWithMutationsPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Unwrap the CloudSpannerJdbcConnection interface + // from the java.sql.Connection. + CloudSpannerJdbcConnection cloudSpannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + + final long marketingBudgetAlbum1 = 100000L; + final long marketingBudgetAlbum2 = 500000L; + // Mutation can be used to update/insert/delete a single row in a table. + // Here we use newUpdateBuilder to create update mutations. + List mutations = + Arrays.asList( + Mutation.newUpdateBuilder("albums") + .set("singer_id") + .to(1) + .set("album_id") + .to(1) + .set("marketing_budget") + .to(marketingBudgetAlbum1) + .build(), + Mutation.newUpdateBuilder("albums") + .set("singer_id") + .to(2) + .set("album_id") + .to(2) + .set("marketing_budget") + .to(marketingBudgetAlbum2) + .build()); + // This writes all the mutations to Cloud Spanner atomically. + cloudSpannerJdbcConnection.write(mutations); + System.out.println("Updated albums"); + } + } + // [END spanner_postgresql_update_data] + + // [START spanner_query_data_with_new_column] + static void queryDataWithNewColumn( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Rows without an explicit value for MarketingBudget will have a + // MarketingBudget equal to null. + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT SingerId, AlbumId, MarketingBudget " + + "FROM Albums")) { + while (resultSet.next()) { + // Use the ResultSet#getObject(String) method to get data + // of any type from the ResultSet. + System.out.printf( + "%s %s %s\n", + resultSet.getObject("SingerId"), + resultSet.getObject("AlbumId"), + resultSet.getObject("MarketingBudget")); + } + } + } + } + // [END spanner_query_data_with_new_column] + + // [START spanner_postgresql_query_data_with_new_column] + static void queryDataWithNewColumnPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Rows without an explicit value for marketing_budget will have a + // marketing_budget equal to null. + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "select singer_id, album_id, marketing_budget " + + "from albums")) { + while (resultSet.next()) { + // Use the ResultSet#getObject(String) method to get data + // of any type from the ResultSet. + System.out.printf( + "%s %s %s\n", + resultSet.getObject("singer_id"), + resultSet.getObject("album_id"), + resultSet.getObject("marketing_budget")); + } + } + } + } + // [END spanner_postgresql_query_data_with_new_column] + + // [START spanner_dml_getting_started_update] + static void writeWithTransactionUsingDml( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + + // Transfer marketing budget from one album to another. + // We do it in a transaction to ensure that the transfer is atomic. + // There is no need to explicitly start the transaction. The first + // statement on the connection will start a transaction when + // AutoCommit=false. + String selectMarketingBudgetSql = + "SELECT MarketingBudget " + + "FROM Albums " + + "WHERE SingerId = ? AND AlbumId = ?"; + long album2Budget = 0; + try (PreparedStatement selectMarketingBudgetStatement = + connection.prepareStatement(selectMarketingBudgetSql)) { + // Bind the query parameters to SingerId=2 and AlbumId=2. + selectMarketingBudgetStatement.setLong(1, 2); + selectMarketingBudgetStatement.setLong(2, 2); + try (ResultSet resultSet = + selectMarketingBudgetStatement.executeQuery()) { + while (resultSet.next()) { + album2Budget = resultSet.getLong("MarketingBudget"); + } + } + // The transaction will only be committed if this condition still holds + // at the time of commit. Otherwise, the transaction will be aborted. + final long transfer = 200000; + if (album2Budget >= transfer) { + long album1Budget = 0; + // Re-use the existing PreparedStatement for selecting the + // MarketingBudget to get the budget for Album 1. + // Bind the query parameters to SingerId=1 and AlbumId=1. + selectMarketingBudgetStatement.setLong(1, 1); + selectMarketingBudgetStatement.setLong(2, 1); + try (ResultSet resultSet = + selectMarketingBudgetStatement.executeQuery()) { + while (resultSet.next()) { + album1Budget = resultSet.getLong("MarketingBudget"); + } + } + + // Transfer part of the marketing budget of Album 2 to Album 1. + album1Budget += transfer; + album2Budget -= transfer; + String updateSql = + "UPDATE Albums " + + "SET MarketingBudget = ? " + + "WHERE SingerId = ? and AlbumId = ?"; + try (PreparedStatement updateStatement = + connection.prepareStatement(updateSql)) { + // Update Album 1. + int paramIndex = 0; + updateStatement.setLong(++paramIndex, album1Budget); + updateStatement.setLong(++paramIndex, 1); + updateStatement.setLong(++paramIndex, 1); + // Create a DML batch by calling addBatch on + // the current PreparedStatement. + updateStatement.addBatch(); + + // Update Album 2 in the same DML batch. + paramIndex = 0; + updateStatement.setLong(++paramIndex, album2Budget); + updateStatement.setLong(++paramIndex, 2); + updateStatement.setLong(++paramIndex, 2); + updateStatement.addBatch(); + + // Execute both DML statements in one batch. + updateStatement.executeBatch(); + } + } + } + // Commit the current transaction. + connection.commit(); + System.out.println( + "Transferred marketing budget from Album 2 to Album 1"); + } + } + // [END spanner_dml_getting_started_update] + + // [START spanner_postgresql_dml_getting_started_update] + static void writeWithTransactionUsingDmlPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + + // Transfer marketing budget from one album to another. We do it in a + // transaction to ensure that the transfer is atomic. There is no need + // to explicitly start the transaction. The first statement on the + // connection will start a transaction when AutoCommit=false. + String selectMarketingBudgetSql = + "SELECT marketing_budget " + + "from albums " + + "WHERE singer_id = ? and album_id = ?"; + long album2Budget = 0; + try (PreparedStatement selectMarketingBudgetStatement = + connection.prepareStatement(selectMarketingBudgetSql)) { + // Bind the query parameters to SingerId=2 and AlbumId=2. + selectMarketingBudgetStatement.setLong(1, 2); + selectMarketingBudgetStatement.setLong(2, 2); + try (ResultSet resultSet = + selectMarketingBudgetStatement.executeQuery()) { + while (resultSet.next()) { + album2Budget = resultSet.getLong("marketing_budget"); + } + } + // The transaction will only be committed if this condition still holds + // at the time of commit. Otherwise, the transaction will be aborted. + final long transfer = 200000; + if (album2Budget >= transfer) { + long album1Budget = 0; + // Re-use the existing PreparedStatement for selecting the + // marketing_budget to get the budget for Album 1. + // Bind the query parameters to SingerId=1 and AlbumId=1. + selectMarketingBudgetStatement.setLong(1, 1); + selectMarketingBudgetStatement.setLong(2, 1); + try (ResultSet resultSet = + selectMarketingBudgetStatement.executeQuery()) { + while (resultSet.next()) { + album1Budget = resultSet.getLong("marketing_budget"); + } + } + + // Transfer part of the marketing budget of Album 2 to Album 1. + album1Budget += transfer; + album2Budget -= transfer; + String updateSql = + "UPDATE albums " + + "SET marketing_budget = ? " + + "WHERE singer_id = ? and album_id = ?"; + try (PreparedStatement updateStatement = + connection.prepareStatement(updateSql)) { + // Update Album 1. + int paramIndex = 0; + updateStatement.setLong(++paramIndex, album1Budget); + updateStatement.setLong(++paramIndex, 1); + updateStatement.setLong(++paramIndex, 1); + // Create a DML batch by calling addBatch + // on the current PreparedStatement. + updateStatement.addBatch(); + + // Update Album 2 in the same DML batch. + paramIndex = 0; + updateStatement.setLong(++paramIndex, album2Budget); + updateStatement.setLong(++paramIndex, 2); + updateStatement.setLong(++paramIndex, 2); + updateStatement.addBatch(); + + // Execute both DML statements in one batch. + updateStatement.executeBatch(); + } + } + } + // Commit the current transaction. + connection.commit(); + System.out.println( + "Transferred marketing budget from Album 2 to Album 1"); + } + } + // [END spanner_postgresql_dml_getting_started_update] + + // [START spanner_transaction_and_statement_tag] + static void tags( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + // Set the TRANSACTION_TAG session variable to set a transaction tag + // for the current transaction. + connection + .createStatement() + .execute("SET TRANSACTION_TAG='example-tx-tag'"); + + // Set the STATEMENT_TAG session variable to set the request tag + // that should be included with the next SQL statement. + connection + .createStatement() + .execute("SET STATEMENT_TAG='query-marketing-budget'"); + long marketingBudget = 0L; + long singerId = 1L; + long albumId = 1L; + try (PreparedStatement statement = connection.prepareStatement( + "SELECT MarketingBudget " + + "FROM Albums " + + "WHERE SingerId=? AND AlbumId=?")) { + statement.setLong(1, singerId); + statement.setLong(2, albumId); + try (ResultSet albumResultSet = statement.executeQuery()) { + while (albumResultSet.next()) { + marketingBudget = albumResultSet.getLong(1); + } + } + } + // Reduce the marketing budget by 10% if it is more than 1,000. + final long maxMarketingBudget = 1000L; + final float reduction = 0.1f; + if (marketingBudget > maxMarketingBudget) { + marketingBudget -= (long) (marketingBudget * reduction); + connection + .createStatement() + .execute("SET STATEMENT_TAG='reduce-marketing-budget'"); + try (PreparedStatement statement = connection.prepareStatement( + "UPDATE Albums SET MarketingBudget=? " + + "WHERE SingerId=? AND AlbumId=?")) { + int paramIndex = 0; + statement.setLong(++paramIndex, marketingBudget); + statement.setLong(++paramIndex, singerId); + statement.setLong(++paramIndex, albumId); + statement.executeUpdate(); + } + } + + // Commit the current transaction. + connection.commit(); + System.out.println("Reduced marketing budget"); + } + } + // [END spanner_transaction_and_statement_tag] + + // [START spanner_postgresql_transaction_and_statement_tag] + static void tagsPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + // Set the TRANSACTION_TAG session variable to set a transaction tag + // for the current transaction. + connection + .createStatement() + .execute("set spanner.transaction_TAG='example-tx-tag'"); + + // Set the STATEMENT_TAG session variable to set the request tag + // that should be included with the next SQL statement. + connection + .createStatement() + .execute("set spanner.statement_tag='query-marketing-budget'"); + long marketingBudget = 0L; + long singerId = 1L; + long albumId = 1L; + try (PreparedStatement statement = connection.prepareStatement( + "select marketing_budget " + + "from albums " + + "where singer_id=? and album_id=?")) { + statement.setLong(1, singerId); + statement.setLong(2, albumId); + try (ResultSet albumResultSet = statement.executeQuery()) { + while (albumResultSet.next()) { + marketingBudget = albumResultSet.getLong(1); + } + } + } + // Reduce the marketing budget by 10% if it is more than 1,000. + final long maxMarketingBudget = 1000L; + final float reduction = 0.1f; + if (marketingBudget > maxMarketingBudget) { + marketingBudget -= (long) (marketingBudget * reduction); + connection + .createStatement() + .execute("set spanner.statement_tag='reduce-marketing-budget'"); + try (PreparedStatement statement = connection.prepareStatement( + "update albums set marketing_budget=? " + + "where singer_id=? AND album_id=?")) { + int paramIndex = 0; + statement.setLong(++paramIndex, marketingBudget); + statement.setLong(++paramIndex, singerId); + statement.setLong(++paramIndex, albumId); + statement.executeUpdate(); + } + } + + // Commit the current transaction. + connection.commit(); + System.out.println("Reduced marketing budget"); + } + } + // [END spanner_postgresql_transaction_and_statement_tag] + + // [START spanner_read_only_transaction] + static void readOnlyTransaction( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + // This SQL statement instructs the JDBC driver to use + // a read-only transaction. + connection.createStatement().execute("SET TRANSACTION READ ONLY"); + + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT SingerId, AlbumId, AlbumTitle " + + "FROM Albums " + + "ORDER BY SingerId, AlbumId")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("SingerId"), + resultSet.getLong("AlbumId"), + resultSet.getString("AlbumTitle")); + } + } + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT SingerId, AlbumId, AlbumTitle " + + "FROM Albums " + + "ORDER BY AlbumTitle")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("SingerId"), + resultSet.getLong("AlbumId"), + resultSet.getString("AlbumTitle")); + } + } + // End the read-only transaction by calling commit(). + connection.commit(); + } + } + // [END spanner_read_only_transaction] + + // [START spanner_postgresql_read_only_transaction] + static void readOnlyTransactionPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Set AutoCommit=false to enable transactions. + connection.setAutoCommit(false); + // This SQL statement instructs the JDBC driver to use + // a read-only transaction. + connection.createStatement().execute("set transaction read only"); + + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT singer_id, album_id, album_title " + + "FROM albums " + + "ORDER BY singer_id, album_id")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("singer_id"), + resultSet.getLong("album_id"), + resultSet.getString("album_title")); + } + } + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "SELECT singer_id, album_id, album_title " + + "FROM albums " + + "ORDER BY album_title")) { + while (resultSet.next()) { + System.out.printf( + "%d %d %s\n", + resultSet.getLong("singer_id"), + resultSet.getLong("album_id"), + resultSet.getString("album_title")); + } + } + // End the read-only transaction by calling commit(). + connection.commit(); + } + } + // [END spanner_postgresql_read_only_transaction] + + // [START spanner_data_boost] + static void dataBoost( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // This enables Data Boost for all partitioned queries on this connection. + connection.createStatement().execute("SET DATA_BOOST_ENABLED=TRUE"); + + // Run a partitioned query. This query will use Data Boost. + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "RUN PARTITIONED QUERY " + + "SELECT SingerId, FirstName, LastName " + + "FROM Singers")) { + while (resultSet.next()) { + System.out.printf( + "%d %s %s\n", + resultSet.getLong("SingerId"), + resultSet.getString("FirstName"), + resultSet.getString("LastName")); + } + } + } + } + // [END spanner_data_boost] + + // [START spanner_postgresql_data_boost] + static void dataBoostPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // This enables Data Boost for all partitioned queries on this connection. + connection + .createStatement() + .execute("set spanner.data_boost_enabled=true"); + + // Run a partitioned query. This query will use Data Boost. + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + "run partitioned query " + + "select singer_id, first_name, last_name " + + "from singers")) { + while (resultSet.next()) { + System.out.printf( + "%d %s %s\n", + resultSet.getLong("singer_id"), + resultSet.getString("first_name"), + resultSet.getString("last_name")); + } + } + } + } + // [END spanner_postgresql_data_boost] + + // [START spanner_partitioned_dml] + static void partitionedDml( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Enable Partitioned DML on this connection. + connection + .createStatement() + .execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); + // Back-fill a default value for the MarketingBudget column. + long lowerBoundUpdateCount = + connection + .createStatement() + .executeUpdate("UPDATE Albums " + + "SET MarketingBudget=0 " + + "WHERE MarketingBudget IS NULL"); + System.out.printf("Updated at least %d albums\n", lowerBoundUpdateCount); + } + } + // [END spanner_partitioned_dml] + + // [START spanner_postgresql_partitioned_dml] + static void partitionedDmlPostgreSQL( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Enable Partitioned DML on this connection. + connection + .createStatement() + .execute("set spanner.autocommit_dml_mode='partitioned_non_atomic'"); + // Back-fill a default value for the MarketingBudget column. + long lowerBoundUpdateCount = + connection + .createStatement() + .executeUpdate("update albums " + + "set marketing_budget=0 " + + "where marketing_budget is null"); + System.out.printf("Updated at least %d albums\n", lowerBoundUpdateCount); + } + } + // [END spanner_postgresql_partitioned_dml] + + /** The expected number of command line arguments. */ + private static final int NUM_EXPECTED_ARGS = 3; + + /** + * Main method for running a sample. + * + * @param args the command line arguments + */ + public static void main(final String[] args) throws Exception { + if (args.length != NUM_EXPECTED_ARGS) { + printUsageAndExit(); + } + try (DatabaseAdminClient dbAdminClient = createDatabaseAdminClient()) { + final String command = args[0]; + DatabaseId databaseId = DatabaseId.of( + SpannerOptions.getDefaultInstance().getProjectId(), + args[1], + args[2]); + + run(dbAdminClient, command, databaseId); + } + System.out.println(); + System.out.println("Finished running sample"); + } + + static DatabaseAdminClient createDatabaseAdminClient() throws Exception { + String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST"); + if (!Strings.isNullOrEmpty(emulatorHost)) { + return DatabaseAdminClient.create( + DatabaseAdminSettings.newBuilder() + .setTransportChannelProvider( + InstantiatingGrpcChannelProvider.newBuilder() + .setEndpoint(emulatorHost) + .setChannelConfigurator( + ManagedChannelBuilder::usePlaintext) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build()); + } + return DatabaseAdminClient.create(); + } + + static Properties createProperties() { + Properties properties = new Properties(); + String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST"); + if (!Strings.isNullOrEmpty(emulatorHost)) { + properties.put("autoConfigEmulator", "true"); + properties.put("endpoint", emulatorHost); + } + return properties; + } + + static void run( + final DatabaseAdminClient dbAdminClient, + final String command, + final DatabaseId database) throws Exception { + if ( + !runGoogleSQLSample(dbAdminClient, command, database) + && !runPostgreSQLSample(dbAdminClient, command, database)) { + System.err.println(); + System.err.println("Unknown command: " + command); + System.err.println(); + printUsageAndExit(); + } + } + + static boolean runGoogleSQLSample( + final DatabaseAdminClient dbAdminClient, + final String command, + final DatabaseId database) throws Exception { + switch (command) { + case "createdatabase": + createDatabase( + dbAdminClient, + InstanceName.of( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance()), + database.getDatabase(), + createProperties()); + return true; + case "writeusingdml": + writeDataWithDml( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "writeusingdmlbatch": + writeDataWithDmlBatch( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "write": + writeDataWithMutations( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "query": + queryData( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "querywithparameter": + queryWithParameter( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "addmarketingbudget": + addColumn( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "ddlbatch": + ddlBatch( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "update": + updateDataWithMutations( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "querymarketingbudget": + queryDataWithNewColumn( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "writewithtransactionusingdml": + writeWithTransactionUsingDml( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "tags": + tags( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "readonlytransaction": + readOnlyTransaction( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "databoost": + dataBoost( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "pdml": + partitionedDml( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + default: + return false; + } + } + + static boolean runPostgreSQLSample( + final DatabaseAdminClient dbAdminClient, + final String command, + final DatabaseId database) throws Exception { + switch (command) { + case "createpgdatabase": + createPostgreSQLDatabase( + dbAdminClient, + InstanceName.of( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance()), + database.getDatabase(), + createProperties()); + return true; + case "writeusingdmlpg": + writeDataWithDmlPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "writeusingdmlbatchpg": + writeDataWithDmlBatchPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "writepg": + writeDataWithMutationsPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "querypg": + queryDataPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "querywithparameterpg": + queryWithParameterPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "addmarketingbudgetpg": + addColumnPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "ddlbatchpg": + ddlBatchPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "updatepg": + updateDataWithMutationsPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "querymarketingbudgetpg": + queryDataWithNewColumnPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "writewithtransactionusingdmlpg": + writeWithTransactionUsingDmlPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "tagspg": + tagsPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "readonlytransactionpg": + readOnlyTransactionPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "databoostpg": + dataBoostPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + case "pdmlpg": + partitionedDmlPostgreSQL( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; + default: + return false; + } + } + + static void printUsageAndExit() { + System.err.println("Usage:"); + System.err.println(" JdbcSample "); + System.err.println(); + System.err.println("Examples:"); + System.err.println(" JdbcSample createdatabase my-instance example-db"); + System.exit(1); + } +} diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/package-info.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/package-info.java new file mode 100644 index 000000000000..bdaf4070ccf5 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/package-info.java @@ -0,0 +1,18 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Sample package for the Spanner JDBC driver. */ +package com.example.spanner.jdbc; diff --git a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java new file mode 100644 index 000000000000..9365ad9bfee2 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java @@ -0,0 +1,396 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.spanner.jdbc; + +import static com.example.spanner.jdbc.JdbcSample.addColumn; +import static com.example.spanner.jdbc.JdbcSample.addColumnPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.createConnection; +import static com.example.spanner.jdbc.JdbcSample.createConnectionWithEmulator; +import static com.example.spanner.jdbc.JdbcSample.createDatabase; +import static com.example.spanner.jdbc.JdbcSample.createPostgreSQLDatabase; +import static com.example.spanner.jdbc.JdbcSample.dataBoost; +import static com.example.spanner.jdbc.JdbcSample.dataBoostPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.ddlBatch; +import static com.example.spanner.jdbc.JdbcSample.ddlBatchPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.partitionedDml; +import static com.example.spanner.jdbc.JdbcSample.partitionedDmlPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.queryData; +import static com.example.spanner.jdbc.JdbcSample.queryDataPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.queryDataWithNewColumn; +import static com.example.spanner.jdbc.JdbcSample.queryDataWithNewColumnPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.queryWithParameter; +import static com.example.spanner.jdbc.JdbcSample.queryWithParameterPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.readOnlyTransaction; +import static com.example.spanner.jdbc.JdbcSample.readOnlyTransactionPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.tags; +import static com.example.spanner.jdbc.JdbcSample.tagsPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.updateDataWithMutations; +import static com.example.spanner.jdbc.JdbcSample.updateDataWithMutationsPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithDml; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithDmlBatch; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithDmlBatchPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithDmlPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithMutations; +import static com.example.spanner.jdbc.JdbcSample.writeDataWithMutationsPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.writeWithTransactionUsingDml; +import static com.example.spanner.jdbc.JdbcSample.writeWithTransactionUsingDmlPostgreSQL; +import static org.junit.Assert.assertEquals; + +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient; +import com.google.cloud.spanner.admin.instance.v1.InstanceAdminSettings; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.instance.v1.Instance; +import com.google.spanner.admin.instance.v1.InstanceConfig; +import com.google.spanner.admin.instance.v1.InstanceName; +import com.google.spanner.admin.instance.v1.ProjectName; +import com.google.spanner.v1.DatabaseName; +import io.grpc.ManagedChannelBuilder; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Properties; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +@RunWith(JUnit4.class) +public class JdbcSampleTest { + private static final String PROJECT_ID = "emulator-project"; + private static final String INSTANCE_ID = "test-instance"; + private static final String DATABASE_ID = "test-database"; + private static final String PG_DATABASE_ID = "pg-test-database"; + + private static final ProjectName PROJECT_NAME = ProjectName.of(PROJECT_ID); + + private static final InstanceName INSTANCE_NAME = InstanceName.of(PROJECT_ID, INSTANCE_ID); + + private static GenericContainer emulator; + + private static Properties properties; + + @BeforeClass + public static void setup() throws Exception { + emulator = + new GenericContainer<>( + DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) + // .withExposedPorts(9010) + .waitingFor(Wait.forListeningPort()); + // TODO: Remove and replace with dynamic port binding when Spanner client library 6.64.0 has + // been released. + emulator.setPortBindings(ImmutableList.of("9010:9010")); + emulator.start(); + try (InstanceAdminClient client = + InstanceAdminClient.create( + InstanceAdminSettings.newBuilder() + .setTransportChannelProvider( + InstantiatingGrpcChannelProvider.newBuilder() + .setEndpoint(emulator.getHost() + ":" + emulator.getMappedPort(9010)) + .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build())) { + InstanceConfig config = + client.listInstanceConfigs(PROJECT_NAME).iterateAll().iterator().next(); + client + .createInstanceAsync( + PROJECT_NAME, + INSTANCE_ID, + Instance.newBuilder() + .setConfig(config.getName()) + .setDisplayName("Test Instance") + .setNodeCount(1) + .build()) + .get(); + } + // Create properties for the JDBC driver to connect to the emulator. + properties = new Properties(); + properties.put("autoConfigEmulator", "true"); + properties.put("lenient", "true"); + properties.put("endpoint", emulator.getHost() + ":" + emulator.getMappedPort(9010)); + } + + @AfterClass + public static void cleanup() { + SpannerPool.closeSpannerPool(); + emulator.stop(); + } + + DatabaseAdminClient createDatabaseAdminClient() throws Exception { + return DatabaseAdminClient.create( + DatabaseAdminSettings.newBuilder() + .setTransportChannelProvider( + InstantiatingGrpcChannelProvider.newBuilder() + .setEndpoint(emulator.getHost() + ":" + emulator.getMappedPort(9010)) + .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) + .build()) + .setCredentialsProvider(NoCredentialsProvider.create()) + .build()); + } + + @Test + public void testGoogleSQLSamples() throws Exception { + String result; + try (DatabaseAdminClient client = createDatabaseAdminClient()) { + result = runSample(() -> createDatabase(client, INSTANCE_NAME, DATABASE_ID, properties)); + } + assertEquals( + "Created database [" + DatabaseName.of(PROJECT_ID, INSTANCE_ID, DATABASE_ID) + "]\n", + result); + + result = runSample(() -> createConnection(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Hello World!\n", result); + + result = runSample(() -> createConnectionWithEmulator(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Hello World!\n", result); + + result = runSample(() -> writeDataWithDml(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("4 records inserted.\n", result); + + result = + runSample(() -> writeDataWithDmlBatch(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("3 records inserted.\n", result); + + result = + runSample(() -> writeDataWithMutations(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Inserted 10 rows.\n", result); + + result = runSample(() -> queryData(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals( + "1 2 Go, Go, Go\n" + + "2 2 Forever Hold Your Peace\n" + + "1 1 Total Junk\n" + + "2 1 Green\n" + + "2 3 Terrified\n", + result); + + result = runSample(() -> queryWithParameter(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("12 Melissa Garcia\n", result); + + result = runSample(() -> addColumn(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Added MarketingBudget column\n", result); + + result = runSample(() -> ddlBatch(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Added Venues and Concerts tables\n", result); + + result = + runSample(() -> updateDataWithMutations(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Updated albums\n", result); + + result = + runSample(() -> queryDataWithNewColumn(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals( + "1 2 null\n" + "2 2 500000\n" + "1 1 100000\n" + "2 1 null\n" + "2 3 null\n", result); + + result = + runSample( + () -> writeWithTransactionUsingDml(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Transferred marketing budget from Album 2 to Album 1\n", result); + + result = + runSample( + () -> tags(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Reduced marketing budget\n", result); + + result = runSample(() -> readOnlyTransaction(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals( + "1 1 Total Junk\n" + + "1 2 Go, Go, Go\n" + + "2 1 Green\n" + + "2 2 Forever Hold Your Peace\n" + + "2 3 Terrified\n" + + "2 2 Forever Hold Your Peace\n" + + "1 2 Go, Go, Go\n" + + "2 1 Green\n" + + "2 3 Terrified\n" + + "1 1 Total Junk\n", + result); + + result = runSample(() -> dataBoost(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals( + "2 Catalina Smith\n" + + "4 Lea Martin\n" + + "12 Melissa Garcia\n" + + "14 Jacqueline Long\n" + + "16 Sarah Wilson\n" + + "18 Maya Patel\n" + + "1 Marc Richards\n" + + "3 Alice Trentor\n" + + "5 David Lomond\n" + + "13 Russel Morales\n" + + "15 Dylan Shaw\n" + + "17 Ethan Miller\n", + result); + + result = runSample(() -> partitionedDml(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Updated at least 3 albums\n", result); + } + + @Test + public void testPostgreSQLSamples() throws Exception { + String result; + try (DatabaseAdminClient client = createDatabaseAdminClient()) { + result = + runSample( + () -> createPostgreSQLDatabase(client, INSTANCE_NAME, PG_DATABASE_ID, properties)); + } + assertEquals( + "Created database [" + DatabaseName.of(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID) + "]\n", + result); + + result = runSample(() -> createConnection(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Hello World!\n", result); + + result = runSample(() -> createConnectionWithEmulator(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Hello World!\n", result); + + result = + runSample( + () -> writeDataWithDmlPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("4 records inserted.\n", result); + + result = + runSample( + () -> + writeDataWithDmlBatchPostgreSQL( + PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("3 records inserted.\n", result); + + result = + runSample( + () -> + writeDataWithMutationsPostgreSQL( + PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Inserted 10 rows.\n", result); + + result = + runSample(() -> queryDataPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals( + "1 2 Go, Go, Go\n" + + "2 2 Forever Hold Your Peace\n" + + "1 1 Total Junk\n" + + "2 1 Green\n" + + "2 3 Terrified\n", + result); + + result = + runSample( + () -> + queryWithParameterPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("12 Melissa Garcia\n", result); + + result = + runSample(() -> addColumnPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Added marketing_budget column\n", result); + + result = + runSample(() -> ddlBatchPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Added venues and concerts tables\n", result); + + result = + runSample( + () -> + updateDataWithMutationsPostgreSQL( + PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Updated albums\n", result); + + result = + runSample( + () -> + queryDataWithNewColumnPostgreSQL( + PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals( + "1 2 null\n" + "2 2 500000\n" + "1 1 100000\n" + "2 1 null\n" + "2 3 null\n", result); + + result = + runSample( + () -> + writeWithTransactionUsingDmlPostgreSQL( + PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Transferred marketing budget from Album 2 to Album 1\n", result); + + result = + runSample( + () -> + tagsPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Reduced marketing budget\n", result); + + result = + runSample( + () -> + readOnlyTransactionPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals( + "1 1 Total Junk\n" + + "1 2 Go, Go, Go\n" + + "2 1 Green\n" + + "2 2 Forever Hold Your Peace\n" + + "2 3 Terrified\n" + + "2 2 Forever Hold Your Peace\n" + + "1 2 Go, Go, Go\n" + + "2 1 Green\n" + + "2 3 Terrified\n" + + "1 1 Total Junk\n", + result); + + result = + runSample(() -> dataBoostPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals( + "2 Catalina Smith\n" + + "4 Lea Martin\n" + + "12 Melissa Garcia\n" + + "14 Jacqueline Long\n" + + "16 Sarah Wilson\n" + + "18 Maya Patel\n" + + "1 Marc Richards\n" + + "3 Alice Trentor\n" + + "5 David Lomond\n" + + "13 Russel Morales\n" + + "15 Dylan Shaw\n" + + "17 Ethan Miller\n", + result); + + result = + runSample( + () -> partitionedDmlPostgreSQL(PROJECT_ID, INSTANCE_ID, PG_DATABASE_ID, properties)); + assertEquals("Updated at least 3 albums\n", result); + } + + interface Sample { + void run() throws Exception; + } + + String runSample(Sample sample) throws Exception { + PrintStream stdOut = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + System.setOut(out); + try { + sample.run(); + } finally { + System.setOut(stdOut); + } + return bout.toString(); + } +} From 6158a959d2413b6e1487a965f1cc203651dc9e39 Mon Sep 17 00:00:00 2001 From: Hengfeng Li Date: Wed, 10 Apr 2024 23:20:08 +1000 Subject: [PATCH 1234/1979] chore: add OpenTelemetry metric for client lib latencies (#1559) --- java-spanner-jdbc/pom.xml | 11 ++++ .../spanner/jdbc/AbstractJdbcStatement.java | 5 ++ .../cloud/spanner/jdbc/JdbcConnection.java | 31 +++++++++++ .../google/cloud/spanner/jdbc/Metrics.java | 53 +++++++++++++++++++ .../JdbcConnectionGeneratedSqlScriptTest.java | 2 + .../spanner/jdbc/JdbcConnectionTest.java | 7 ++- 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Metrics.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 38d49832b0c4..2e9478636268 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -66,6 +66,13 @@ pom import
    + + io.opentelemetry + opentelemetry-bom + 1.36.0 + pom + import + com.google.cloud google-cloud-shared-dependencies @@ -152,6 +159,10 @@ com.google.api.grpc proto-google-cloud-spanner-v1 + + io.opentelemetry + opentelemetry-api + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 97131724d9eb..61c272fb7dfa 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -24,11 +24,13 @@ 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.common.base.Stopwatch; import com.google.rpc.Code; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; +import java.time.Duration; import java.util.Arrays; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -227,7 +229,10 @@ private T doWithStatementTimeout( StatementTimeout originalTimeout = setTemporaryStatementTimeout(); T result = null; try { + Stopwatch stopwatch = Stopwatch.createStarted(); result = runnable.get(); + Duration executionDuration = stopwatch.elapsed(); + connection.recordClientLibLatencyMetric(executionDuration.toMillis()); return result; } catch (SpannerException spannerException) { throw JdbcSqlExceptionFactory.of(spannerException); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 2c7d6cc00823..bafdc6b09d19 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -21,17 +21,23 @@ import com.google.api.client.util.Preconditions; import com.google.cloud.spanner.CommitResponse; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerOptions; 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; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; @@ -80,9 +86,21 @@ class JdbcConnection extends AbstractJdbcConnection { private final boolean useLegacyIsValidCheck; + private final Metrics metrics; + + private final Attributes metricAttributes; + JdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException { super(connectionUrl, options); this.useLegacyIsValidCheck = useLegacyValidCheck(); + OpenTelemetry openTelemetry; + if (SpannerOptions.isEnabledOpenTelemetryMetrics()) { + openTelemetry = this.getSpanner().getOptions().getOpenTelemetry(); + } else { + openTelemetry = OpenTelemetry.noop(); + } + this.metrics = new Metrics(openTelemetry); + this.metricAttributes = createMetricAttributes(this.getConnectionOptions().getDatabaseId()); } static boolean useLegacyValidCheck() { @@ -96,6 +114,19 @@ static boolean useLegacyValidCheck() { return false; } + @VisibleForTesting + static Attributes createMetricAttributes(DatabaseId databaseId) { + AttributesBuilder attributesBuilder = Attributes.builder(); + attributesBuilder.put("database", databaseId.getDatabase()); + attributesBuilder.put("instance_id", databaseId.getInstanceId().getInstance()); + attributesBuilder.put("project_id", databaseId.getInstanceId().getProject()); + return attributesBuilder.build(); + } + + public void recordClientLibLatencyMetric(long value) { + metrics.recordClientLibLatency(value, metricAttributes); + } + @Override public Statement createStatement() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Metrics.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Metrics.java new file mode 100644 index 000000000000..77f238466ebe --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/Metrics.java @@ -0,0 +1,53 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.spanner.jdbc; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.LongHistogram; +import io.opentelemetry.api.metrics.Meter; +import java.util.Arrays; +import java.util.List; + +class Metrics { + static final String INSTRUMENTATION_SCOPE = "cloud.google.com/java"; + static final String SPANNER_CLIENT_LIB_LATENCY = "spanner/jdbc/client_lib_latencies"; + static final String SPANNER_CLIENT_LIB_LATENCY_DESCRIPTION = + "Latency when the client library receives a call and returns a response"; + + private final LongHistogram spannerClientLibLatencies; + + Metrics(OpenTelemetry openTelemetry) { + Meter meter = openTelemetry.getMeter(INSTRUMENTATION_SCOPE); + List RPC_MILLIS_BUCKET_BOUNDARIES = + Arrays.asList( + 1L, 2L, 3L, 4L, 5L, 6L, 8L, 10L, 13L, 16L, 20L, 25L, 30L, 40L, 50L, 65L, 80L, 100L, + 130L, 160L, 200L, 250L, 300L, 400L, 500L, 650L, 800L, 1000L, 2000L, 5000L, 10000L, + 20000L, 50000L, 100000L); + spannerClientLibLatencies = + meter + .histogramBuilder(SPANNER_CLIENT_LIB_LATENCY) + .ofLongs() + .setDescription(SPANNER_CLIENT_LIB_LATENCY_DESCRIPTION) + .setUnit("ms") + .setExplicitBucketBoundariesAdvice(RPC_MILLIS_BUCKET_BOUNDARIES) + .build(); + } + + void recordClientLibLatency(long value, Attributes attributes) { + spannerClientLibLatencies.record(value, attributes); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index 5844feefbaae..a5d350501e1f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.connection.AbstractConnectionImplTest; @@ -64,6 +65,7 @@ public GenericConnection getConnection() { ConnectionImplTest.createConnection(options, dialect); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); + when(options.getDatabaseId()).thenReturn(DatabaseId.of("project", "instance", "database")); try { JdbcConnection connection = new JdbcConnection( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 8d26bb31736f..96ea743819c6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -23,10 +23,12 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ResultSets; @@ -80,13 +82,16 @@ private JdbcConnection createConnection(ConnectionOptions options) throws SQLExc ConnectionImplTest.createConnection(options, dialect); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); + when(options.getDatabaseId()).thenReturn(DatabaseId.of("project", "instance", "database")); return new JdbcConnection( "jdbc:cloudspanner://localhost/projects/project/instances/instance/databases/database;credentialsUrl=url", options); } private ConnectionOptions mockOptions() { - return mock(ConnectionOptions.class); + ConnectionOptions options = mock(ConnectionOptions.class); + when(options.getDatabaseId()).thenReturn(DatabaseId.of("project", "instance", "database")); + return options; } @Test From 22618ea5b6723b767098b0095341c4db67980150 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 10 Apr 2024 15:44:18 +0200 Subject: [PATCH 1235/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.28.1 (#1560) 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:sdk-platform-java-config](https://togithub.com/googleapis/java-shared-config) | `3.27.0` -> `3.28.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:sdk-platform-java-config/3.28.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:sdk-platform-java-config/3.28.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:sdk-platform-java-config/3.27.0/3.28.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:sdk-platform-java-config/3.27.0/3.28.1?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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 047c0c761440..5928ec6aba93 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.27.0 + 3.28.1 From d24a56a3a2156f7b29174440632f4c76124a9868 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 12 Apr 2024 15:26:51 +0200 Subject: [PATCH 1236/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.1.5 (#1564) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c9fbf898de18..c1dc7cc00b1f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.1.4 + 2023.1.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 16e8c3d3792d..ef9d1d89e7c9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.1.4 + 2023.1.5 import pom From 8b1c53de1db8023e8d7658f52e16394fb32804fb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 12 Apr 2024 15:27:09 +0200 Subject: [PATCH 1237/1979] deps: update actions/setup-java action to v4 (#1563) --- java-spanner-jdbc/.github/workflows/sample-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml index cec19c7a2c1d..7e464ef17883 100644 --- a/java-spanner-jdbc/.github/workflows/sample-tests.yml +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 From fca7710764455a703e7cdac20581170e20638718 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 14 Apr 2024 15:28:01 +0200 Subject: [PATCH 1238/1979] deps: update actions/checkout action to v4 (#1561) --- java-spanner-jdbc/.github/workflows/sample-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml index 7e464ef17883..eae9314cf8f1 100644 --- a/java-spanner-jdbc/.github/workflows/sample-tests.yml +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -20,7 +20,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: temurin From c8f647bcb510889c777fce779eea2f0df5584c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 16 Apr 2024 08:07:25 +0200 Subject: [PATCH 1239/1979] chore: make connection property all lower-case (#1566) --- .../src/main/java/com/example/spanner/jdbc/JdbcSample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java index 2e46058de4e4..b17c6b4d8f6f 100644 --- a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java @@ -1235,7 +1235,7 @@ static void tagsPostgreSQL( // for the current transaction. connection .createStatement() - .execute("set spanner.transaction_TAG='example-tx-tag'"); + .execute("set spanner.transaction_tag='example-tx-tag'"); // Set the STATEMENT_TAG session variable to set the request tag // that should be included with the next SQL statement. From 7b30b8a0b03194f06a15f3094a160225d7d5d240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 16 Apr 2024 10:44:09 +0200 Subject: [PATCH 1240/1979] fix: release ResultSet on Statement#close() (#1567) * fix: release ResultSet on Statement#close() Release the underlying resources of any ResultSet when Statement#close() is called. This is necessary in case someone executes a query in auto-commit mode using Statement#execute(String), and never reads and/or closes the result that was returned. * fix: close result set when Statement is closed --- .../spanner/jdbc/AbstractJdbcStatement.java | 2 +- .../cloud/spanner/jdbc/JdbcStatement.java | 19 +++- .../spanner/jdbc/StatementResourcesTest.java | 88 +++++++++++++++++++ 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResourcesTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 61c272fb7dfa..d12678bf2915 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -359,7 +359,7 @@ public void cancel() throws SQLException { } @Override - public void close() { + public void close() throws SQLException { this.closed = true; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 1db0c4070746..19b32565419f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -62,6 +62,12 @@ enum BatchType { super(connection); } + @Override + public void close() throws SQLException { + setCurrentResultSet(null); + super.close(); + } + @Override public ResultSet executeQuery(String sql) throws SQLException { checkClosed(); @@ -267,7 +273,7 @@ boolean executeStatement(Statement statement, ImmutableList generatedKey // 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()); + setCurrentResultSet(JdbcResultSet.of(this, result.getResultSet())); currentUpdateCount = JdbcConstants.STATEMENT_RESULT_SET; return true; } @@ -275,11 +281,11 @@ boolean executeStatement(Statement statement, ImmutableList generatedKey this.currentUpdateCount = extractUpdateCountAndClose(result.getResultSet()); return false; case UPDATE_COUNT: - currentResultSet = null; + setCurrentResultSet(null); currentUpdateCount = result.getUpdateCount(); return false; case NO_RESULT: - currentResultSet = null; + setCurrentResultSet(null); currentUpdateCount = JdbcConstants.STATEMENT_NO_RESULT; return false; default: @@ -294,6 +300,13 @@ public ResultSet getResultSet() throws SQLException { return currentResultSet; } + void setCurrentResultSet(ResultSet resultSet) throws SQLException { + if (this.currentResultSet != null) { + this.currentResultSet.close(); + } + this.currentResultSet = resultSet; + } + /** * Returns the update count of the last update statement. Will return {@link * JdbcConstants#STATEMENT_RESULT_SET} if the last statement returned a {@link ResultSet} and will diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResourcesTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResourcesTest.java new file mode 100644 index 000000000000..ea1b313acddc --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementResourcesTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class StatementResourcesTest extends AbstractMockServerTest { + private static final int MIN_SESSIONS = 1; + private static final int MAX_SESSIONS = 2; + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s" + + "?usePlainText=true;minSessions=%d;maxSessions=%d", + getPort(), "proj", "inst", "db", MIN_SESSIONS, MAX_SESSIONS); + } + + @Test + public void testMultipleQueriesOnOneStatement() throws SQLException { + try (Connection connection = DriverManager.getConnection(createUrl())) { + try (Statement statement = connection.createStatement()) { + for (int i = 0; i < MAX_SESSIONS + 1; i++) { + // Execute a query without reading or closing the result. + statement.execute("SELECT 1"); + } + } + } + } + + @Test + public void testMultipleStatementsWithOneQuery() throws SQLException { + try (Connection connection = DriverManager.getConnection(createUrl())) { + for (int i = 0; i < MAX_SESSIONS + 1; i++) { + try (Statement statement = connection.createStatement()) { + // Execute a query without reading or closing the result. + statement.execute("SELECT 1"); + } + } + } + } + + @Test + public void testMultipleQueriesOnOnePreparedStatement() throws SQLException { + try (Connection connection = DriverManager.getConnection(createUrl())) { + try (PreparedStatement statement = connection.prepareStatement("SELECT 1")) { + for (int i = 0; i < MAX_SESSIONS + 1; i++) { + // Execute a query without reading or closing the result. + statement.execute(); + } + } + } + } + + @Test + public void testMultiplePreparedStatementsWithOneQuery() throws SQLException { + try (Connection connection = DriverManager.getConnection(createUrl())) { + for (int i = 0; i < MAX_SESSIONS + 1; i++) { + try (PreparedStatement statement = connection.prepareStatement("SELECT 1")) { + // Execute a query without reading or closing the result. + statement.execute(); + } + } + } + } +} From 3d4d9c8f83bb92a9eeaa83fcb51196a8bd1939a7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Apr 2024 13:04:10 +0200 Subject: [PATCH 1241/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.64.0 (#1565) 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.63.0` -> `6.64.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.64.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.64.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.63.0/6.64.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.63.0/6.64.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.64.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6640-2024-04-12) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.63.0...v6.64.0) ##### Features - Add endpoint connection URL property ([#​2969](https://togithub.com/googleapis/java-spanner/issues/2969)) ([c9be29c](https://togithub.com/googleapis/java-spanner/commit/c9be29c717924d7f4c5acd8fe09ee371d0101642)) - Add PG OID support ([#​2736](https://togithub.com/googleapis/java-spanner/issues/2736)) ([ba2a4af](https://togithub.com/googleapis/java-spanner/commit/ba2a4afa5c1d64c932e9687d52b15c28d9dd7d91)) - Add SessionPoolOptions, SpannerOptions protos in executor protos ([#​2932](https://togithub.com/googleapis/java-spanner/issues/2932)) ([1673fd7](https://togithub.com/googleapis/java-spanner/commit/1673fd70df4ebfaa4b5fa07112d152119427699a)) - Support max_commit_delay in Connection API ([#​2954](https://togithub.com/googleapis/java-spanner/issues/2954)) ([a8f1852](https://togithub.com/googleapis/java-spanner/commit/a8f185261c812e7d6c92cb61ecc1f9c78ba3c4d9)) ##### Bug Fixes - Executor framework changes skipped in clirr checks, and added exception for partition methods in admin class ([#​3000](https://togithub.com/googleapis/java-spanner/issues/3000)) ([c2d8e95](https://togithub.com/googleapis/java-spanner/commit/c2d8e955abddb0117f1b3b94c2d9650d2cf4fdfd)) ##### Dependencies - Update actions/checkout action to v4 ([#​3006](https://togithub.com/googleapis/java-spanner/issues/3006)) ([368a9f3](https://togithub.com/googleapis/java-spanner/commit/368a9f33758961d8e3fd387ec94d380e7c6460cc)) - Update actions/github-script action to v7 ([#​3007](https://togithub.com/googleapis/java-spanner/issues/3007)) ([b0cfea6](https://togithub.com/googleapis/java-spanner/commit/b0cfea6e73b7293f564357e8d1c8c6bb2e0cf855)) - Update actions/setup-java action to v4 ([#​3008](https://togithub.com/googleapis/java-spanner/issues/3008)) ([d337080](https://togithub.com/googleapis/java-spanner/commit/d337080089dbd58cb4bf94f2cb5925f627435d39)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.42.0 ([#​2997](https://togithub.com/googleapis/java-spanner/issues/2997)) ([0615beb](https://togithub.com/googleapis/java-spanner/commit/0615beb806ef62dbbfcc6bbffd082adc9c62372c)) - Update dependency com.google.cloud:google-cloud-trace to v2.41.0 ([#​2998](https://togithub.com/googleapis/java-spanner/issues/2998)) ([f50cd04](https://togithub.com/googleapis/java-spanner/commit/f50cd04660f480c62ddbd6c8a9e892cd95ec16b0)) - Update dependency commons-io:commons-io to v2.16.1 ([#​3020](https://togithub.com/googleapis/java-spanner/issues/3020)) ([aafd5b9](https://togithub.com/googleapis/java-spanner/commit/aafd5b9514c14a0dbfd0bf2616990f3c347ac0c6)) - Update opentelemetry.version to v1.37.0 ([#​3021](https://togithub.com/googleapis/java-spanner/issues/3021)) ([8f1ed2a](https://togithub.com/googleapis/java-spanner/commit/8f1ed2ac20896fb413749bb18652764096f1fb2d)) - Update stcarolas/setup-maven action to v5 ([#​3009](https://togithub.com/googleapis/java-spanner/issues/3009)) ([541acd2](https://togithub.com/googleapis/java-spanner/commit/541acd23aaf2c9336615406e30618fb65606e6c5))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- .../spanner/jdbc/AbstractJdbcWrapper.java | 8 ++-- .../cloud/spanner/jdbc/JdbcResultSet.java | 43 +++++++++++-------- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 16 +++++++ .../spanner/jdbc/AllTypesMockServerTest.java | 34 +++++++++++++-- .../jdbc/PartitionedQueryMockServerTest.java | 3 +- .../spanner/jdbc/RandomResultSetTest.java | 16 +++++-- 7 files changed, 93 insertions(+), 29 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2e9478636268..f4a9fc8555e3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.63.0 + 6.64.0 pom import diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index b06e5999e4a5..aa65ee6f98f4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.getMainTypeCode; + import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.Code; @@ -42,7 +44,7 @@ abstract class AbstractJdbcWrapper implements Wrapper { */ static int extractColumnType(Type type) { Preconditions.checkNotNull(type); - switch (type.getCode()) { + switch (getMainTypeCode(type)) { case BOOL: return Types.BOOLEAN; case BYTES: @@ -139,7 +141,7 @@ static String getClassName(int sqlType) { */ static String getClassName(Type type) { Preconditions.checkNotNull(type); - switch (type.getCode()) { + switch (getMainTypeCode(type)) { case BOOL: return Boolean.class.getName(); case BYTES: @@ -162,7 +164,7 @@ static String getClassName(Type type) { case TIMESTAMP: return Timestamp.class.getName(); case ARRAY: - switch (type.getArrayElementType().getCode()) { + switch (getMainTypeCode(type.getArrayElementType())) { case BOOL: return Boolean[].class.getName(); case BYTES: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 91ec976b8534..dcb259857a70 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.getMainTypeCode; + import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; @@ -195,7 +197,7 @@ public String getString(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? null : String.valueOf(spanner.getBoolean(spannerIndex)); @@ -233,7 +235,7 @@ public boolean getBoolean(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return !isNull && spanner.getBoolean(spannerIndex); @@ -266,7 +268,7 @@ public byte getByte(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? (byte) 0 : (spanner.getBoolean(spannerIndex) ? (byte) 1 : 0); @@ -305,7 +307,7 @@ public short getShort(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (short) 1 : 0); @@ -344,7 +346,7 @@ public int getInt(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? 1 : 0); @@ -383,7 +385,7 @@ public long getLong(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? 0L : (spanner.getBoolean(spannerIndex) ? 1L : 0L); @@ -418,7 +420,7 @@ public float getFloat(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (float) 1 : 0); @@ -451,7 +453,7 @@ public double getDouble(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case BOOL: return isNull ? 0 : (spanner.getBoolean(spannerIndex) ? (double) 1 : 0); @@ -492,7 +494,7 @@ public Date getDate(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case DATE: return isNull ? null : JdbcTypeConverter.toSqlDate(spanner.getDate(spannerIndex)); @@ -523,7 +525,7 @@ public Time getTime(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case STRING: return isNull ? null : parseTime(spanner.getString(spannerIndex)); @@ -551,7 +553,7 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case DATE: return isNull ? null : JdbcTypeConverter.toSqlTimestamp(spanner.getDate(spannerIndex)); @@ -716,6 +718,7 @@ public Object getObject(int columnIndex) throws SQLException { } private Object getObject(Type type, int columnIndex) throws SQLException { + // TODO: Refactor to check based on type code. if (type == Type.bool()) return getBoolean(columnIndex); if (type == Type.bytes()) return getBytes(columnIndex); if (type == Type.date()) return getDate(columnIndex); @@ -723,7 +726,9 @@ private Object getObject(Type type, int columnIndex) throws SQLException { return getFloat(columnIndex); } if (type == Type.float64()) return getDouble(columnIndex); - if (type == Type.int64()) return getLong(columnIndex); + if (type == Type.int64() || type == Type.pgOid()) { + return getLong(columnIndex); + } if (type == Type.numeric()) return getBigDecimal(columnIndex); if (type == Type.pgNumeric()) { final String value = getString(columnIndex); @@ -734,7 +739,9 @@ private Object getObject(Type type, int columnIndex) throws SQLException { } } if (type == Type.string()) return getString(columnIndex); - if (type == Type.json()) return getString(columnIndex); + if (type == Type.json() || type == Type.pgJsonb()) { + return getString(columnIndex); + } if (type == Type.timestamp()) return getTimestamp(columnIndex); if (type.getCode() == Code.ARRAY) return getArray(columnIndex); throw JdbcSqlExceptionFactory.of("Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT); @@ -792,7 +799,7 @@ public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLExcepti private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) throws SQLException { int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); boolean isNull = isNull(columnIndex); BigDecimal res; switch (type) { @@ -888,7 +895,7 @@ public Array getArray(int columnIndex) throws SQLException { throw JdbcSqlExceptionFactory.of( "Column with index " + columnIndex + " does not contain an array", com.google.rpc.Code.INVALID_ARGUMENT); - final Code elementCode = type.getArrayElementType().getCode(); + final Code elementCode = getMainTypeCode(type.getArrayElementType()); final JdbcDataType dataType = JdbcDataType.getType(elementCode); try { List elements = dataType.getArrayElements(spanner, columnIndex - 1); @@ -907,7 +914,7 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { return null; } int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case DATE: return JdbcTypeConverter.toSqlDate(spanner.getDate(spannerIndex), cal); @@ -941,7 +948,7 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { checkClosedAndValidRow(); boolean isNull = isNull(columnIndex); int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case STRING: return isNull ? null : parseTime(spanner.getString(spannerIndex), cal); @@ -975,7 +982,7 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException return null; } int spannerIndex = columnIndex - 1; - Code type = spanner.getColumnType(spannerIndex).getCode(); + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); switch (type) { case DATE: return JdbcTypeConverter.toSqlTimestamp(spanner.getDate(spannerIndex), cal); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index c6be0a824975..1733302c5b71 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -22,6 +22,7 @@ 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 java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; @@ -46,6 +47,17 @@ class JdbcTypeConverter { private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ISO_OFFSET_DATE_TIME; private static final Charset UTF8 = StandardCharsets.UTF_8; + // TODO: Remove when this is supported in the Java client library. + static Code getMainTypeCode(Type type) { + Preconditions.checkNotNull(type); + switch (type.getCode()) { + case PG_OID: + return Code.INT64; + default: + return type.getCode(); + } + } + /** * Converts the given value from the Google {@link Type} to the Java {@link Class} type. The input * value and the {@link Type} must be consistent with each other. @@ -205,6 +217,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx Arrays.asList((Double[]) ((java.sql.Array) value).getArray())); case INT64: return Value.int64Array(Arrays.asList((Long[]) ((java.sql.Array) value).getArray())); + case PG_OID: + return Value.pgOidArray(Arrays.asList((Long[]) ((java.sql.Array) value).getArray())); case NUMERIC: return Value.numericArray( Arrays.asList((BigDecimal[]) ((java.sql.Array) value).getArray())); @@ -238,6 +252,8 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.float64((Double) value); case INT64: return Value.int64((Long) value); + case PG_OID: + return Value.pgOid((Long) value); case NUMERIC: return Value.numeric((BigDecimal) value); case PG_NUMERIC: diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java index 4a1eb6a6f335..cf4b7dfb589f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java @@ -75,6 +75,9 @@ public void testSelectAllTypes() { DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), resultSet.getDate(++col)); assertEquals(TIMESTAMP_VALUE.toSqlTimestamp(), resultSet.getTimestamp(++col)); + if (dialect == Dialect.POSTGRESQL) { + assertEquals(PG_OID_VALUE, resultSet.getLong(++col)); + } assertEquals( BOOL_ARRAY_VALUE, Arrays.asList((Boolean[]) resultSet.getArray(++col).getArray())); @@ -122,6 +125,10 @@ public void testSelectAllTypes() { .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp()) .collect(Collectors.toList()), Arrays.asList((Timestamp[]) resultSet.getArray(++col).getArray())); + if (dialect == Dialect.POSTGRESQL) { + assertEquals( + PG_OID_ARRAY_VALUE, Arrays.asList((Long[]) resultSet.getArray(++col).getArray())); + } assertFalse(resultSet.next()); } @@ -140,7 +147,7 @@ public void testInsertAllTypes() { insertStatement .toBuilder() .replace(insertStatement.getSql().replaceAll("@p", "\\$")) - .bind("p15") + .bind("p16") .to( com.google.cloud.spanner.Value.pgNumericArray( NUMERIC_ARRAY_VALUE.stream() @@ -179,6 +186,9 @@ public void testInsertAllTypes() { DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth())); statement.setTimestamp(++param, TIMESTAMP_VALUE.toSqlTimestamp()); + if (dialect == Dialect.POSTGRESQL) { + statement.setLong(++param, PG_OID_VALUE); + } // TODO: Support PostgreSQL type names for creating arrays. statement.setArray( @@ -241,6 +251,10 @@ public void testInsertAllTypes() { TIMESTAMP_ARRAY_VALUE.stream() .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp()) .toArray(Timestamp[]::new))); + if (dialect == Dialect.POSTGRESQL) { + statement.setArray( + ++param, connection.createArrayOf("INT64", PG_OID_ARRAY_VALUE.toArray(new Long[0]))); + } assertEquals(1, statement.executeUpdate()); } @@ -249,8 +263,8 @@ public void testInsertAllTypes() { ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); Map paramTypes = request.getParamTypesMap(); Map params = request.getParams().getFieldsMap(); - assertEquals(20, paramTypes.size()); - assertEquals(20, params.size()); + assertEquals(dialect == Dialect.POSTGRESQL ? 22 : 20, paramTypes.size()); + assertEquals(dialect == Dialect.POSTGRESQL ? 22 : 20, params.size()); // Verify param types. ImmutableList expectedTypes = @@ -265,6 +279,10 @@ public void testInsertAllTypes() { TypeCode.BYTES, TypeCode.DATE, TypeCode.TIMESTAMP); + if (dialect == Dialect.POSTGRESQL) { + expectedTypes = + ImmutableList.builder().addAll(expectedTypes).add(TypeCode.INT64).build(); + } for (int col = 0; col < expectedTypes.size(); col++) { assertEquals(expectedTypes.get(col), paramTypes.get("p" + (col + 1)).getCode()); int arrayCol = col + expectedTypes.size(); @@ -290,6 +308,9 @@ public void testInsertAllTypes() { params.get("p" + ++col).getStringValue()); assertEquals(DATE_VALUE.toString(), params.get("p" + ++col).getStringValue()); assertEquals(TIMESTAMP_VALUE.toString(), params.get("p" + ++col).getStringValue()); + if (dialect == Dialect.POSTGRESQL) { + assertEquals(String.valueOf(PG_OID_VALUE), params.get("p" + ++col).getStringValue()); + } assertEquals( BOOL_ARRAY_VALUE, @@ -365,6 +386,13 @@ public void testInsertAllTypes() { ? null : com.google.cloud.Timestamp.parseTimestamp(value.getStringValue())) .collect(Collectors.toList())); + if (dialect == Dialect.POSTGRESQL) { + assertEquals( + PG_OID_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : Long.valueOf(value.getStringValue())) + .collect(Collectors.toList())); + } } catch (SQLException sqlException) { throw new RuntimeException(sqlException); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index 31842409bd40..5b521b6218ca 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -73,7 +73,8 @@ public void clearRequests() { private int getExpectedColumnCount(Dialect dialect) { // GoogleSQL also adds 4 PROTO columns. - return dialect == Dialect.GOOGLE_STANDARD_SQL ? 24 : 20; + // PostgreSQL adds 2 OID columns. + return dialect == Dialect.GOOGLE_STANDARD_SQL ? 24 : 22; } private String createUrl() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java index 4d24068dc01e..e00907ee94d5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java @@ -78,6 +78,9 @@ public void testSelectRandomResults() throws SQLException { assertEquals(Types.BINARY, metadata.getColumnType(++col)); assertEquals(Types.DATE, metadata.getColumnType(++col)); assertEquals(Types.TIMESTAMP, metadata.getColumnType(++col)); + if (dialect == Dialect.POSTGRESQL) { + assertEquals(Types.BIGINT, metadata.getColumnType(++col)); + } assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // boolean assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // bigint @@ -89,6 +92,9 @@ public void testSelectRandomResults() throws SQLException { assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // binary assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // date assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // timestamp + if (dialect == Dialect.POSTGRESQL) { + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // oid + } // GoogleSQL also includes proto columns. if (dialect == Dialect.GOOGLE_STANDARD_SQL) { @@ -108,9 +114,7 @@ public void testSelectRandomResults() throws SQLException { for (col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) { if (dialect == Dialect.GOOGLE_STANDARD_SQL && col > 20) { // Proto columns are not yet supported, so skipping. - } else if (dialect == Dialect.POSTGRESQL && col == 7) { - // PG_JSONB is not yet recognized by the JDBC driver, so skipping. - } else if (dialect == Dialect.POSTGRESQL && col == 15) { + } else if (dialect == Dialect.POSTGRESQL && col == 16) { // getObject for ARRAY tries to get the array as a List. // That fails if the array contains a NaN, so skipping. } else { @@ -130,6 +134,9 @@ public void testSelectRandomResults() throws SQLException { resultSet.getBytes(++col); resultSet.getDate(++col); resultSet.getTimestamp(++col); + if (dialect == Dialect.POSTGRESQL) { + resultSet.getLong(++col); // oid + } resultSet.getArray(++col); resultSet.getArray(++col); @@ -147,6 +154,9 @@ public void testSelectRandomResults() throws SQLException { resultSet.getArray(++col); resultSet.getArray(++col); resultSet.getArray(++col); + if (dialect == Dialect.POSTGRESQL) { + resultSet.getArray(++col); // oid[] + } // GoogleSQL also includes proto columns. if (dialect == Dialect.GOOGLE_STANDARD_SQL) { From a4e2541e81dac40bfc20cc145c3aabd7c1b304df Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 18 Apr 2024 12:57:46 +0200 Subject: [PATCH 1242/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.37.0 (#1562) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f4a9fc8555e3..4d9824792a85 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ io.opentelemetry opentelemetry-bom - 1.36.0 + 1.37.0 pom import From 3fa199faa0da8835a8f9b0345ee9110a86700cd5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 19 Apr 2024 08:05:28 +0200 Subject: [PATCH 1243/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.29.0 (#1572) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index c724f3dab88c..a17720ffbc86 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.28.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.29.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index c2a88196e84d..326361c6b5e3 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.28.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.29.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 94e00cbaa0a1..1b1d4c4bfe36 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.28.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.29.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4d9824792a85..5657f0250f5f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.28.1 + 3.29.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5928ec6aba93..d1768c622861 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.28.1 + 3.29.0 From d5e87984901069a34b6cc0b6a7409a9c9ac1cdfd Mon Sep 17 00:00:00 2001 From: Alice <65933803+alicejli@users.noreply.github.com> Date: Fri, 19 Apr 2024 02:06:33 -0400 Subject: [PATCH 1244/1979] chore: include recommended_package in repo-metadata.json (#1571) --- java-spanner-jdbc/.repo-metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index 6a760b5e4b77..8887ec91f3d2 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -10,6 +10,7 @@ "repo_short": "java-spanner-jdbc", "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc", "library_type": "OTHER", - "codeowner_team": "@googleapis/api-spanner-java" + "codeowner_team": "@googleapis/api-spanner-java", + "recommended_package": "com.google.cloud.spanner.jdbc" } From 9758bf3ea0c1d7ebe230be80087665ddd66293d9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 19 Apr 2024 08:07:47 +0200 Subject: [PATCH 1245/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.5 (#1570) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index ef9d1d89e7c9..92e9142146e1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.4 + 3.2.5 From 31895ef64420457ff930fe3f8bd6ba0d3530a699 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 19 Apr 2024 08:08:26 +0200 Subject: [PATCH 1246/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.5 (#1569) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c1dc7cc00b1f..960fe8da4ed0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.2.4 + 3.2.5 From b0831de5c83478432e8f2d98010ab99ae5a9ba3d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 19:43:30 +0200 Subject: [PATCH 1247/1979] chore(main): release 2.16.2 (#1554) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 31 ++++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index fd7acea519e7..38941b4d4edd 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [2.16.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.1...v2.16.2) (2024-04-19) + + +### Bug Fixes + +* Release ResultSet on Statement#close() ([#1567](https://github.com/googleapis/java-spanner-jdbc/issues/1567)) ([2258ae3](https://github.com/googleapis/java-spanner-jdbc/commit/2258ae3331a7e89036a202f243b9284108301fc0)) + + +### Dependencies + +* Update actions/checkout action to v4 ([#1547](https://github.com/googleapis/java-spanner-jdbc/issues/1547)) ([736e3af](https://github.com/googleapis/java-spanner-jdbc/commit/736e3afa54149dd11803bd715569afd9ec8e87f2)) +* Update actions/checkout action to v4 ([#1561](https://github.com/googleapis/java-spanner-jdbc/issues/1561)) ([6053d79](https://github.com/googleapis/java-spanner-jdbc/commit/6053d79816546130eca7a7016dc9299c079e411f)) +* Update actions/checkout digest to b4ffde6 ([#1546](https://github.com/googleapis/java-spanner-jdbc/issues/1546)) ([18c5ad4](https://github.com/googleapis/java-spanner-jdbc/commit/18c5ad4d4124f095547d50c0d2e154bc06380642)) +* Update actions/github-script action to v7 ([#1548](https://github.com/googleapis/java-spanner-jdbc/issues/1548)) ([d1d422c](https://github.com/googleapis/java-spanner-jdbc/commit/d1d422cdf0a74231c468262662fdf5ce4d27b8ef)) +* Update actions/setup-java action to v4 ([#1549](https://github.com/googleapis/java-spanner-jdbc/issues/1549)) ([cb2b911](https://github.com/googleapis/java-spanner-jdbc/commit/cb2b911b0b332e97f85974ec880a5ab7a12a7578)) +* Update actions/setup-java action to v4 ([#1563](https://github.com/googleapis/java-spanner-jdbc/issues/1563)) ([01d4de1](https://github.com/googleapis/java-spanner-jdbc/commit/01d4de1df21144e9c3bcf0b4e5192b12cd19dc82)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.63.0 ([#1552](https://github.com/googleapis/java-spanner-jdbc/issues/1552)) ([ac75b9f](https://github.com/googleapis/java-spanner-jdbc/commit/ac75b9faf0eaeb499428ecefda1f3285b3d28e67)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.64.0 ([#1565](https://github.com/googleapis/java-spanner-jdbc/issues/1565)) ([b57662f](https://github.com/googleapis/java-spanner-jdbc/commit/b57662fb65b74b329103ef63265192d7026b2c2d)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.28.1 ([#1560](https://github.com/googleapis/java-spanner-jdbc/issues/1560)) ([afcbe5e](https://github.com/googleapis/java-spanner-jdbc/commit/afcbe5ea5701a799729543c9564759570f05feb8)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.29.0 ([#1572](https://github.com/googleapis/java-spanner-jdbc/issues/1572)) ([3d43707](https://github.com/googleapis/java-spanner-jdbc/commit/3d437076f2c699e261daf7dcb470085765dba14f)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.37.0 ([#1562](https://github.com/googleapis/java-spanner-jdbc/issues/1562)) ([22f766f](https://github.com/googleapis/java-spanner-jdbc/commit/22f766f098944c23084776c70dbd9dba21efa59c)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.2.5 ([#1569](https://github.com/googleapis/java-spanner-jdbc/issues/1569)) ([784ac1e](https://github.com/googleapis/java-spanner-jdbc/commit/784ac1e68ac29628fe55d7b9e772326f10ffeaec)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.2.5 ([#1570](https://github.com/googleapis/java-spanner-jdbc/issues/1570)) ([f54d4dd](https://github.com/googleapis/java-spanner-jdbc/commit/f54d4dd1211508785cb899e0a3c9b585c0908421)) +* Update dependency org.springframework.data:spring-data-bom to v2023.1.5 ([#1564](https://github.com/googleapis/java-spanner-jdbc/issues/1564)) ([dbbcca3](https://github.com/googleapis/java-spanner-jdbc/commit/dbbcca342a83476b1f942aab23f21469cf6c8304)) +* Update stcarolas/setup-maven action to v5 ([#1550](https://github.com/googleapis/java-spanner-jdbc/issues/1550)) ([121d08e](https://github.com/googleapis/java-spanner-jdbc/commit/121d08e16db0bbb1f6041a201d620829e7121f4d)) + + +### Documentation + +* Create samples for quickstart guide ([#1536](https://github.com/googleapis/java-spanner-jdbc/issues/1536)) ([194c820](https://github.com/googleapis/java-spanner-jdbc/commit/194c8205dee9cc4144b18e219df43027b9f15cf2)) + ## [2.16.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.0...v2.16.1) (2024-03-22) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5657f0250f5f..6edcf1c68549 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.2-SNAPSHOT + 2.16.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index baaf8bb8916b..f50a9b998c99 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.2-SNAPSHOT + 2.16.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 21a50e390060..d27860f6af79 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.1:2.16.2-SNAPSHOT +google-cloud-spanner-jdbc:2.16.2:2.16.2 From d657a24fdb54bde856eb45a8a764e820d2779962 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 19:10:18 +0000 Subject: [PATCH 1248/1979] chore(main): release 2.16.3-SNAPSHOT (#1574) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6edcf1c68549..fd0f2a23f36e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.2 + 2.16.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f50a9b998c99..3f6656101731 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.2 + 2.16.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d27860f6af79..cb1335317005 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.2:2.16.2 +google-cloud-spanner-jdbc:2.16.2:2.16.3-SNAPSHOT From d10ba31e062838de9c1c37b3da8edafa317590c5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 20 Apr 2024 22:07:31 +0200 Subject: [PATCH 1249/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.0 (#1573) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd0f2a23f36e..001af1a1ff25 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.64.0 + 6.65.0 pom import From 88886589d6fd7d1b95a3b51e11b6059f871ee072 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 21:20:17 +0000 Subject: [PATCH 1250/1979] chore(main): release 2.16.3 (#1576) :robot: I have created a release *beep* *boop* --- ## [2.16.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.16.2...v2.16.3) (2024-04-20) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.0 ([#1573](https://togithub.com/googleapis/java-spanner-jdbc/issues/1573)) ([d10ba31](https://togithub.com/googleapis/java-spanner-jdbc/commit/d10ba31e062838de9c1c37b3da8edafa317590c5)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 38941b4d4edd..f3525a5c52d3 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.16.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.2...v2.16.3) (2024-04-20) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.0 ([#1573](https://github.com/googleapis/java-spanner-jdbc/issues/1573)) ([ecc18f1](https://github.com/googleapis/java-spanner-jdbc/commit/ecc18f1307933bb0f4f576ce2df81af226f8a2cb)) + ## [2.16.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.1...v2.16.2) (2024-04-19) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 001af1a1ff25..72452f925151 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.3-SNAPSHOT + 2.16.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3f6656101731..29000ae82861 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.3-SNAPSHOT + 2.16.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index cb1335317005..a9c98ac7ed7b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.2:2.16.3-SNAPSHOT +google-cloud-spanner-jdbc:2.16.3:2.16.3 From 1af4b2fc470fc6572f36c246c2500541fa924671 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 22:38:16 +0000 Subject: [PATCH 1251/1979] chore(main): release 2.16.4-SNAPSHOT (#1577) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 72452f925151..48ce6daf2b50 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.3 + 2.16.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 29000ae82861..d05de6b4e8cb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.3 + 2.16.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a9c98ac7ed7b..f1551f67f53c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.3:2.16.3 +google-cloud-spanner-jdbc:2.16.3:2.16.4-SNAPSHOT From ec39cbbb6efb9bf2406ffaaeb279572dfdd87fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 21 Apr 2024 09:36:25 +0200 Subject: [PATCH 1252/1979] feat: concurrent transactions on emulator (#1578) The JDBC driver now supports running multiple concurrent transactions on the emulator using a single thread. The emulator still only supports one read/write transaction per database at any time, but the JDBC driver works around this by manually setting a Savepoint after each statement, and using that Savepoint to automatically resume the transaction when it has been aborted by the emulator. --- java-spanner-jdbc/pom.xml | 6 + .../ConcurrentTransactionOnEmulatorTest.java | 105 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 48ce6daf2b50..644108cf3d10 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -171,6 +171,12 @@ test-jar test
    + + org.testcontainers + testcontainers + 1.19.7 + test + com.google.truth truth diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java new file mode 100644 index 000000000000..e9931e604350 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import com.google.cloud.spanner.connection.SpannerPool; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +@RunWith(JUnit4.class) +public class ConcurrentTransactionOnEmulatorTest { + private static GenericContainer emulator; + + private static Properties properties; + + @BeforeClass + public static void startEmulator() { + assumeTrue(DockerClientFactory.instance().isDockerAvailable()); + + emulator = + new GenericContainer<>( + DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) + .withExposedPorts(9010) + .waitingFor(Wait.forListeningPort()); + emulator.start(); + properties = new Properties(); + properties.setProperty("autoConfigEmulator", "true"); + properties.setProperty( + "endpoint", String.format("%s:%d", emulator.getHost(), emulator.getMappedPort(9010))); + } + + @AfterClass + public static void cleanup() { + SpannerPool.closeSpannerPool(); + if (emulator != null) { + emulator.stop(); + } + } + + @Test + public void testRunConcurrentTransactions() throws SQLException { + String connectionUrl = + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + "emulator-project", "test-instance", "test-database"); + try (Connection connection1 = DriverManager.getConnection(connectionUrl, properties); + Connection connection2 = DriverManager.getConnection(connectionUrl, properties)) { + // Create a test table. + connection1 + .createStatement() + .execute("create table test (id int64, value string(max)) primary key (id)"); + + // Put both connections into autoCommit=false mode and verify that both connections can run + // a transaction using a single thread. + connection1.setAutoCommit(false); + connection2.setAutoCommit(false); + + connection1.createStatement().executeUpdate("insert into test (id, value) values (1, 'One')"); + connection2.createStatement().executeUpdate("insert into test (id, value) values (2, 'Two')"); + connection1.commit(); + connection2.commit(); + + // Verify that both transactions succeeded. + connection1.setAutoCommit(true); + try (ResultSet resultSet = + connection1.createStatement().executeQuery("select * from test order by id")) { + assertTrue(resultSet.next()); + assertEquals("One", resultSet.getString("value")); + assertTrue(resultSet.next()); + assertEquals("Two", resultSet.getString("value")); + assertFalse(resultSet.next()); + } + } + } +} From a3be9e1522b3f37482f2cd99a230ce31cf84e2ee Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 21 Apr 2024 09:55:50 +0200 Subject: [PATCH 1253/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.16.3 (#1575) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a2537a7e645c..0be1c776c748 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.1 + 2.16.3 From 95e65517e30c5f4d066960242c6a4f4c2f44f131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 21 Apr 2024 09:56:43 +0200 Subject: [PATCH 1254/1979] feat: support statement tags in hints (#1579) --- .../jdbc/ClientSideStatementHintsTest.java | 114 ++++++++++++++++++ .../cloud/spanner/jdbc/TagMockServerTest.java | 67 ++++++---- 2 files changed, 160 insertions(+), 21 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java new file mode 100644 index 000000000000..9a69ba2623ab --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.RequestOptions.Priority; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +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 ClientSideStatementHintsTest extends AbstractMockServerTest { + + @Parameter public Dialect dialect; + + private Dialect currentDialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + @Before + public void setupDialect() { + if (this.dialect != currentDialect) { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + this.currentDialect = dialect; + } + } + + @After + public void clearRequests() { + mockSpanner.clearRequests(); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testStatementTagInHint() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + dialect == Dialect.POSTGRESQL + ? "/*@statement_tag='test-tag'*/SELECT 1" + : "@{statement_tag='test-tag'}SELECT 1")) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(1)); + assertFalse(resultSet.next()); + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("test-tag", request.getRequestOptions().getRequestTag()); + } + + @Test + public void testRpcPriorityInHint() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + dialect == Dialect.POSTGRESQL + ? "/*@rpc_priority=PRIORITY_LOW*/SELECT 1" + : "@{rpc_priority=PRIORITY_LOW}SELECT 1")) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(1)); + assertFalse(resultSet.next()); + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals(Priority.PRIORITY_LOW, request.getRequestOptions().getPriority()); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java index 5c626c0f95e7..8401297c097b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.Dialect; @@ -40,8 +41,14 @@ @RunWith(Parameterized.class) public class TagMockServerTest extends AbstractMockServerTest { + private static final String SELECT_RANDOM_SQL = SELECT_RANDOM_STATEMENT.getSql(); + + private static final String INSERT_SQL = INSERT_STATEMENT.getSql(); + @Parameter public Dialect dialect; + private Dialect currentDialect; + @Parameters(name = "dialect = {0}") public static Object[] data() { return Dialect.values(); @@ -49,7 +56,10 @@ public static Object[] data() { @Before public void setupDialect() { - mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + if (this.dialect != currentDialect) { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + this.currentDialect = dialect; + } } @After @@ -77,8 +87,7 @@ public void testStatementTagForQuery() throws SQLException { connection .createStatement() .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); - try (ResultSet resultSet = - connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { assertTrue(resultSet.next()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); @@ -87,8 +96,7 @@ public void testStatementTagForQuery() throws SQLException { // Verify that the tag is cleared after having been used. mockSpanner.clearRequests(); - try (ResultSet resultSet = - connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { assertTrue(resultSet.next()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); @@ -103,8 +111,7 @@ public void testTransactionTagForQuery() throws SQLException { connection .createStatement() .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); - try (ResultSet resultSet = - connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { assertTrue(resultSet.next()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); @@ -113,8 +120,7 @@ public void testTransactionTagForQuery() throws SQLException { // Verify that the tag is used for the entire transaction. mockSpanner.clearRequests(); - try (ResultSet resultSet = - connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { assertTrue(resultSet.next()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); @@ -125,8 +131,7 @@ public void testTransactionTagForQuery() throws SQLException { connection.commit(); mockSpanner.clearRequests(); - try (ResultSet resultSet = - connection.createStatement().executeQuery(SELECT_RANDOM_STATEMENT.getSql())) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { assertTrue(resultSet.next()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); @@ -143,8 +148,8 @@ public void testStatementTagForBatchDml() throws SQLException { .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); try (Statement statement = connection.createStatement()) { - statement.addBatch(INSERT_STATEMENT.getSql()); - statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_SQL); + statement.addBatch(INSERT_SQL); assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); @@ -155,8 +160,8 @@ public void testStatementTagForBatchDml() throws SQLException { // Verify that the tag is cleared after having been used. mockSpanner.clearRequests(); try (Statement statement = connection.createStatement()) { - statement.addBatch(INSERT_STATEMENT.getSql()); - statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_SQL); + statement.addBatch(INSERT_SQL); assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); @@ -173,8 +178,8 @@ public void testTransactionTagForBatchDml() throws SQLException { .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); try (Statement statement = connection.createStatement()) { - statement.addBatch(INSERT_STATEMENT.getSql()); - statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_SQL); + statement.addBatch(INSERT_SQL); assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); @@ -185,8 +190,8 @@ public void testTransactionTagForBatchDml() throws SQLException { // Verify that the tag is used for the entire transaction. mockSpanner.clearRequests(); try (Statement statement = connection.createStatement()) { - statement.addBatch(INSERT_STATEMENT.getSql()); - statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_SQL); + statement.addBatch(INSERT_SQL); assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); @@ -197,8 +202,8 @@ public void testTransactionTagForBatchDml() throws SQLException { connection.commit(); mockSpanner.clearRequests(); try (Statement statement = connection.createStatement()) { - statement.addBatch(INSERT_STATEMENT.getSql()); - statement.addBatch(INSERT_STATEMENT.getSql()); + statement.addBatch(INSERT_SQL); + statement.addBatch(INSERT_SQL); assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); } assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); @@ -206,4 +211,24 @@ public void testTransactionTagForBatchDml() throws SQLException { assertEquals("", request.getRequestOptions().getTransactionTag()); } } + + @Test + public void testStatementTagInHint() throws SQLException { + try (Connection connection = createConnection()) { + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery( + dialect == Dialect.POSTGRESQL + ? "/*@statement_tag='test-tag'*/SELECT 1" + : "@{statement_tag='test-tag'}SELECT 1")) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(1)); + assertFalse(resultSet.next()); + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertEquals("test-tag", request.getRequestOptions().getRequestTag()); + } } From b6ad295773a788de22eecc0fd8e67c9c2c82352b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 21 Apr 2024 09:57:35 +0200 Subject: [PATCH 1255/1979] build: stop auto merging releases (#1361) Stop auto-merging releases, even if they only contain dependency updates, as it causes a too large number of releases to go out. --- java-spanner-jdbc/.github/workflows/auto-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml index 18d92e5a28dd..c6577b779110 100644 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ b/java-spanner-jdbc/.github/workflows/auto-release.yaml @@ -99,5 +99,5 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - labels: ['kokoro:force-run', 'automerge'] + labels: ['kokoro:force-run'] }); From 5b5f44a67ad780118ad7f1fabf3e75d83361eeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 21 Apr 2024 09:57:59 +0200 Subject: [PATCH 1256/1979] feat: support max_commit_delay (#1581) Support added for 'set max_commit_delay=' statement. Setting a max_commit_delay can increase throughput of bulk updates, as Spanner can batch more updates together, but at the expense of higher latency for a single request. --- ...t.java => JdbcTransactionOptionsTest.java} | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) rename java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/{JdbcCommitStatsTest.java => JdbcTransactionOptionsTest.java} (84%) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java similarity index 84% rename from java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java rename to java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java index 0782566ddfeb..a34e449e76cf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcCommitStatsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -25,16 +26,18 @@ import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.SpannerPool; +import com.google.spanner.v1.CommitRequest; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.Duration; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) -public class JdbcCommitStatsTest extends AbstractMockServerTest { +public class JdbcTransactionOptionsTest extends AbstractMockServerTest { @After public void closeSpannerPool() { @@ -120,4 +123,19 @@ public void testSetAndUseReturnCommitStatsUsingSql() throws SQLException { } } } + + @Test + public void testMaxCommitDelay() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.createStatement().execute("SET max_commit_delay='50ms'"); + connection + .unwrap(CloudSpannerJdbcConnection.class) + .bufferedWrite(Mutation.newInsertBuilder("FOO").set("ID").to(1L).build()); + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + CommitRequest request = mockSpanner.getRequestsOfType(CommitRequest.class).get(0); + assertEquals(Duration.ofMillis(50).toNanos(), request.getMaxCommitDelay().getNanos()); + } + } } From b379fa6d596ad888e210e21bb6aad88b8c9e6a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 21 Apr 2024 09:58:16 +0200 Subject: [PATCH 1257/1979] feat: support endpoint connection URL property (#1582) Added support for an 'endpoint' connection URL property. This property can be added to either the Connection URL or the Properties object that is used to create a Connection, and can be used in combination with the autoConfigEmulator connection property to connect to an emulator instance that uses a randomly assigned port number. See https://github.com/googleapis/java-spanner-jdbc/blob/main/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java for an example on how to use this property. --- .../java/com/google/cloud/spanner/jdbc/JdbcDriver.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 5df6cf63844d..54d699b654e7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -84,6 +84,12 @@ * instance and database in the connection string will automatically be created if these do * not yet exist on the emulator. This means that you do not need to execute any `gcloud` * commands on the emulator to create the instance and database before you can connect to it. + *
  • endpoint (string): Set this property to specify a custom endpoint that the JDBC driver + * should connect to. You can use this property in combination with the autoConfigEmulator + * property to instruct the JDBC driver to connect to an emulator instance that uses a + * randomly assigned port numer. See ConcurrentTransactionOnEmulatorTest + * for a concrete example of how to use this property. *
  • usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted * connection to the server. This option can only be used when connecting to a local emulator * that does not require an encrypted connection, and that does not require authentication. @@ -101,8 +107,7 @@ * connection. *
  • retryAbortsInternally (boolean): Sets the initial retryAbortsInternally mode for the * connection. Default is true. @see {@link - * com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} - * for more information. + * CloudSpannerJdbcConnection#setRetryAbortsInternally(boolean)} for more information. *
  • minSessions (int): Sets the minimum number of sessions in the backing session pool. * Defaults to 100. *
  • maxSessions (int): Sets the maximum number of sessions in the backing session pool. From a6bf90d631705a76ca3ffdd3febe29e4f59c7309 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:00:29 +0000 Subject: [PATCH 1258/1979] chore(main): release 2.17.0 (#1580) :robot: I have created a release *beep* *boop* --- ## [2.17.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.16.3...v2.17.0) (2024-04-21) ### Features * Concurrent transactions on emulator ([#1578](https://togithub.com/googleapis/java-spanner-jdbc/issues/1578)) ([ec39cbb](https://togithub.com/googleapis/java-spanner-jdbc/commit/ec39cbbb6efb9bf2406ffaaeb279572dfdd87fb1)) * Support endpoint connection URL property ([#1582](https://togithub.com/googleapis/java-spanner-jdbc/issues/1582)) ([b379fa6](https://togithub.com/googleapis/java-spanner-jdbc/commit/b379fa6d596ad888e210e21bb6aad88b8c9e6a91)) * Support max_commit_delay ([#1581](https://togithub.com/googleapis/java-spanner-jdbc/issues/1581)) ([5b5f44a](https://togithub.com/googleapis/java-spanner-jdbc/commit/5b5f44a67ad780118ad7f1fabf3e75d83361eeac)) * Support statement tags in hints ([#1579](https://togithub.com/googleapis/java-spanner-jdbc/issues/1579)) ([95e6551](https://togithub.com/googleapis/java-spanner-jdbc/commit/95e65517e30c5f4d066960242c6a4f4c2f44f131)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index f3525a5c52d3..4dcf5b8ed45d 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.17.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.3...v2.17.0) (2024-04-21) + + +### Features + +* Concurrent transactions on emulator ([#1578](https://github.com/googleapis/java-spanner-jdbc/issues/1578)) ([0234fb3](https://github.com/googleapis/java-spanner-jdbc/commit/0234fb3eb43695c657b845946e6d1122827dcae5)) +* Support endpoint connection URL property ([#1582](https://github.com/googleapis/java-spanner-jdbc/issues/1582)) ([b589c96](https://github.com/googleapis/java-spanner-jdbc/commit/b589c96a3187390e9ffa576d1e0ee285e223c559)) +* Support max_commit_delay ([#1581](https://github.com/googleapis/java-spanner-jdbc/issues/1581)) ([06e43c0](https://github.com/googleapis/java-spanner-jdbc/commit/06e43c05a65f25da9a4dbff73e2e75c1b5ec155b)) +* Support statement tags in hints ([#1579](https://github.com/googleapis/java-spanner-jdbc/issues/1579)) ([0c3aec1](https://github.com/googleapis/java-spanner-jdbc/commit/0c3aec1a5eec212e9ecacc7bec7f2a8980c9af78)) + ## [2.16.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.2...v2.16.3) (2024-04-20) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 644108cf3d10..0e0d75e2a663 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.16.4-SNAPSHOT + 2.17.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d05de6b4e8cb..0225f6f80c97 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.4-SNAPSHOT + 2.17.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f1551f67f53c..f35ef1371f96 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.16.3:2.16.4-SNAPSHOT +google-cloud-spanner-jdbc:2.17.0:2.17.0 From bb8e4340fc13961b8884d1dd4686793419ef67f8 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 07:46:34 +0200 Subject: [PATCH 1259/1979] chore(main): release 2.17.1-SNAPSHOT (#1583) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0e0d75e2a663..14ecefb23c9f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.17.0 + 2.17.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0225f6f80c97..3367d50044f5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.0 + 2.17.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f35ef1371f96..5c57c1928594 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.17.0:2.17.0 +google-cloud-spanner-jdbc:2.17.0:2.17.1-SNAPSHOT From 2b60cee481e4027a0af622b256b3be517b312665 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 22 Apr 2024 07:46:52 +0200 Subject: [PATCH 1260/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.17.0 (#1584) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0be1c776c748..036788da119a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.16.3 + 2.17.0 From 0a3960d3e8312465852d43e1dc5e6c4081ef1b67 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 Apr 2024 19:10:13 +0200 Subject: [PATCH 1261/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.1 (#1588) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14ecefb23c9f..32ff166aa937 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.65.0 + 6.65.1 pom import From 7bed22f30295d81757d341156714169fa503f1b1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 Apr 2024 19:10:31 +0200 Subject: [PATCH 1262/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.3 (#1585) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 32ff166aa937..7e4f50e5e2af 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -273,7 +273,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.2 + 3.5.3 From 0d7083eb7d52c73fbfae51e5496c7fa0851941c3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 30 Apr 2024 19:10:51 +0200 Subject: [PATCH 1263/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.2 (#1587) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 1e8df92bd6c2..89194028a307 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true From 507b5cbd7d83f538b40c38601a62644d975feeac Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 08:11:52 +0200 Subject: [PATCH 1264/1979] chore(main): release 2.17.1 (#1589) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 4 ++-- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4dcf5b8ed45d..4605592d2fbf 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.17.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.17.0...v2.17.1) (2024-04-30) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.1 ([#1588](https://github.com/googleapis/java-spanner-jdbc/issues/1588)) ([1b1218a](https://github.com/googleapis/java-spanner-jdbc/commit/1b1218adaa25ecec3def66b7031c7f0e5e8c23b0)) + ## [2.17.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.16.3...v2.17.0) (2024-04-21) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e4f50e5e2af..c194752b7e25 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.17.1-SNAPSHOT + 2.17.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc @@ -273,7 +273,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.3 + 3.5.2 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3367d50044f5..856702ff9873 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.1-SNAPSHOT + 2.17.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5c57c1928594..6af993023a04 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.17.0:2.17.1-SNAPSHOT +google-cloud-spanner-jdbc:2.17.1:2.17.1 From 47d5649ca6840f10b577e9f29d8e3459a6bba231 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 12:58:24 +0200 Subject: [PATCH 1265/1979] chore(main): release 2.17.2-SNAPSHOT (#1592) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c194752b7e25..e762626c59ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.17.1 + 2.17.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 856702ff9873..beebe6a8725b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.1 + 2.17.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6af993023a04..fa461f16e844 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.17.1:2.17.1 +google-cloud-spanner-jdbc:2.17.1:2.17.2-SNAPSHOT From 8dc21dad24e5b6fb47d0405e408c5e3b5e67d14e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 May 2024 12:58:43 +0200 Subject: [PATCH 1266/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.5.3 (#1591) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e762626c59ef..7e5797436789 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -273,7 +273,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.2 + 3.5.3 From 432f038d8d8baf80a0e9eec43bc73e8a8b0430a4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 May 2024 14:04:16 +0200 Subject: [PATCH 1267/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.17.1 (#1593) 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.17.0` -> `2.17.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.17.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.17.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.17.0/2.17.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.17.0/2.17.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.17.1`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2171-2024-04-30) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.17.0...v2.17.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.65.1 ([#​1588](https://togithub.com/googleapis/java-spanner-jdbc/issues/1588)) ([0a3960d](https://togithub.com/googleapis/java-spanner-jdbc/commit/0a3960d3e8312465852d43e1dc5e6c4081ef1b67))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 036788da119a..b3e406165fd2 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.0 + 2.17.1 From 718106b59aff4b0f834140b60294c32907b81b0a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 3 May 2024 19:23:55 +0200 Subject: [PATCH 1268/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.30.0 (#1597) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index a17720ffbc86..0c869e6b0e62 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.29.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.30.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 326361c6b5e3..b20ec8ff3525 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.29.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.30.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 1b1d4c4bfe36..aad0db97859a 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.29.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.30.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e5797436789..6759702c1dd1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.29.0 + 3.30.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d1768c622861..efedc8e12d20 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.29.0 + 3.30.0 From 5994c09dc41410b41af19806161d5866fe496dfa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 3 May 2024 19:24:14 +0200 Subject: [PATCH 1269/1979] deps: update dependency org.mybatis.dynamic-sql:mybatis-dynamic-sql to v1.5.1 (#1596) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 92e9142146e1..c06aec138933 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -51,7 +51,7 @@ org.mybatis.dynamic-sql mybatis-dynamic-sql - 1.5.0 + 1.5.1 From 14080603c60e126f719f9bbcd28488865e8cf335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 3 May 2024 19:25:27 +0200 Subject: [PATCH 1270/1979] fix: ClassCastException in Spring Data JDBC sample (#1595) --- .../java/com/google/cloud/spanner/sample/JdbcConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java index 2066647b513b..a5c24adcde06 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -64,7 +64,7 @@ public static boolean isCloudSpannerPG(JdbcOperations operations) { "The selected Cloud Spanner database does not use the PostgreSQL dialect"); } catch (DataAccessException exception) { if (exception.getCause() instanceof JdbcSqlException) { - JdbcSqlException jdbcSqlException = (JdbcSqlException) exception; + JdbcSqlException jdbcSqlException = (JdbcSqlException) exception.getCause(); if (jdbcSqlException.getCode() == Code.PERMISSION_DENIED || jdbcSqlException.getCode() == Code.NOT_FOUND) { throw new RuntimeException( From ec78e5411e410c82f43f4ca14539c2b2d5bf8ff1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 4 May 2024 09:08:17 +0200 Subject: [PATCH 1271/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.66.0 (#1599) 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.65.1` -> `6.66.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.66.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.66.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.65.1/6.66.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.65.1/6.66.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.66.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6660-2024-05-03) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.65.1...v6.66.0) ##### Features - Allow DDL with autocommit=false ([#​3057](https://togithub.com/googleapis/java-spanner/issues/3057)) ([22833ac](https://togithub.com/googleapis/java-spanner/commit/22833acf9f073271ce0ee10f2b496f3a1d39566a)) - Include stack trace of checked out sessions in exception ([#​3092](https://togithub.com/googleapis/java-spanner/issues/3092)) ([ba6a0f6](https://togithub.com/googleapis/java-spanner/commit/ba6a0f644b6caa4d2f3aa130c6061341b70957dd)) ##### Bug Fixes - Multiplexed session metrics were not included in refactor move ([#​3088](https://togithub.com/googleapis/java-spanner/issues/3088)) ([f3589c4](https://togithub.com/googleapis/java-spanner/commit/f3589c430b0e84933a91008bb306c26089788357)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.30.0 ([#​3082](https://togithub.com/googleapis/java-spanner/issues/3082)) ([ddfc98e](https://togithub.com/googleapis/java-spanner/commit/ddfc98e240fb47ef51075ba4461bf9a98aa25ce0))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- .../ConnectionImplGeneratedSqlScriptTest.sql | 9809 ++++++++--------- .../ConnectionImplGeneratedSqlScriptTest.sql | 9809 ++++++++--------- 3 files changed, 9803 insertions(+), 9817 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6759702c1dd1..85839f1e0bf9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.65.1 + 6.66.0 pom import diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql index be5a1671ae02..84275c3d5c3e 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql @@ -1,23 +1,23 @@ NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -26,125 +26,123 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -153,60 +151,58 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z' +SET AUTOCOMMIT=FALSE; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.061000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -221,34 +217,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -257,8 +253,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -301,46 +297,45 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -351,36 +346,28 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -389,173 +376,123 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -564,78 +501,58 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z' +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.474000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -650,48 +567,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -700,10 +603,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -746,62 +647,45 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -812,207 +696,324 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z' +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.868000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1027,34 +1028,55 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -NEW_CONNECTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1063,8 +1085,11 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1107,71 +1132,116 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -1180,125 +1250,195 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -1307,60 +1447,85 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.152000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1375,34 +1540,55 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1411,8 +1597,11 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1455,46 +1644,69 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1505,217 +1717,208 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z' +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.470000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1730,34 +1933,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1766,8 +1969,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1810,230 +2013,282 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.774000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null -SHOW VARIABLE COMMIT_RESPONSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2048,27 +2303,41 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2077,7 +2346,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2120,254 +2391,254 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.031000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2383,33 +2654,33 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2419,7 +2690,7 @@ SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2463,76 +2734,66 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2542,122 +2803,98 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -2667,57 +2904,48 @@ SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.261000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2733,33 +2961,26 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2769,7 +2990,6 @@ SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2813,44 +3033,36 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -2862,39 +3074,26 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2902,196 +3101,133 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -3099,86 +3235,59 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.514000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3192,56 +3301,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -3249,12 +3337,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3296,117 +3381,84 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -3414,196 +3466,181 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -3611,86 +3648,77 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.790000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3704,56 +3732,49 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -3761,12 +3782,11 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3808,282 +3828,305 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -NEW_CONNECTION; -SET READONLY=TRUE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.050000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4097,35 +4140,42 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -4133,9 +4183,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4177,283 +4228,255 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +START BATCH DDL; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.238000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.238000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4467,42 +4490,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -4510,10 +4526,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4555,255 +4570,377 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.477000000Z'; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.477000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4817,35 +4954,56 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -4853,9 +5011,12 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4897,220 +5058,279 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z' +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.698000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5124,28 +5344,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5153,8 +5380,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5196,243 +5424,266 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -NEW_CONNECTION; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.897000000Z'; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.897000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5447,34 +5698,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5483,8 +5734,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5527,284 +5778,380 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z' +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.065000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5819,41 +6166,55 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5862,9 +6223,11 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5907,87 +6270,113 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -5997,150 +6386,165 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6152,9 +6556,10 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6166,17 +6571,18 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -6186,77 +6592,84 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.341000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -6272,47 +6685,54 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -6322,9 +6742,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -6368,61 +6789,67 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -6433,137 +6860,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6575,68 +7003,68 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +SET READONLY=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.608000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -6652,33 +7080,33 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -6688,7 +7116,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -6732,193 +7160,206 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6929,76 +7370,76 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.834000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7013,34 +7454,41 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7049,8 +7497,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7093,200 +7542,190 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7297,76 +7736,65 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.161000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7381,34 +7809,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7417,8 +7845,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7461,81 +7889,67 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -7544,130 +7958,82 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7678,9 +8044,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7691,16 +8055,11 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -7709,69 +8068,49 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z' +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.402000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7786,41 +8125,27 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7829,9 +8154,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7874,54 +8197,36 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -7931,232 +8236,201 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +START BATCH DDL; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.626000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8172,33 +8446,33 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -8208,7 +8482,7 @@ SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8252,242 +8526,283 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT UPDATE_COUNT 1 +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z' +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.905000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8503,26 +8818,40 @@ SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -8532,6 +8861,8 @@ SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8575,66 +8906,86 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -8644,103 +8995,150 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -8752,7 +9150,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -8764,12 +9164,17 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -8779,57 +9184,77 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.118000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -8845,33 +9270,47 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -8881,7 +9320,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -8925,43 +9366,61 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -8972,198 +9431,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -9174,95 +9573,69 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z' +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.313000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -9277,48 +9650,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -9327,10 +9686,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9373,303 +9730,272 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.570000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.570000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -9685,40 +10011,33 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -9728,8 +10047,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -9773,254 +10091,280 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.779000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.779000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10035,34 +10379,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -10071,8 +10415,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10115,83 +10459,81 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -10200,167 +10542,130 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10371,11 +10676,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10386,19 +10689,16 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -10407,85 +10707,69 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.015000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10500,55 +10784,41 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -10557,11 +10827,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10604,68 +10872,54 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -10675,207 +10929,232 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z' +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.249000000Z'; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10890,34 +11169,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -10926,8 +11205,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10970,71 +11249,73 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11043,104 +11324,88 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11151,8 +11416,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11163,13 +11427,12 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -11178,58 +11441,51 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z' +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.423000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11244,34 +11500,27 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -11280,8 +11529,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11324,44 +11572,38 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -11371,40 +11613,27 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11412,206 +11641,126 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -11619,86 +11768,61 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.634000000Z'; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11712,56 +11836,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -11769,12 +11872,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11816,113 +11916,85 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET AUTOCOMMIT=FALSE; @@ -11932,204 +12004,172 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READONLY=FALSE; @@ -12139,84 +12179,77 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.943000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_VERSION='1'; @@ -12232,54 +12265,47 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @@ -12289,10 +12315,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET STATEMENT_TIMEOUT='1s'; @@ -12336,283 +12361,273 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=TRUE; -NEW_CONNECTION; -SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=TRUE; -NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.194000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -12627,34 +12642,34 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -12663,8 +12678,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -12707,286 +12722,260 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.388000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.388000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -13001,41 +12990,34 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13044,9 +13026,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13089,259 +13070,267 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.635000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.635000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -13356,34 +13345,34 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13392,8 +13381,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13436,68 +13425,75 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -13505,110 +13501,102 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT UPDATE_COUNT 1 +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -13616,50 +13604,52 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.872000000Z'; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -13673,28 +13663,28 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -13702,8 +13692,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13745,44 +13735,47 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql index ac9528cc83d5..e35ae5f3c3c7 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql @@ -1,23 +1,23 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -26,125 +26,123 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -153,60 +151,58 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z' +SET AUTOCOMMIT=FALSE; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.293000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -221,34 +217,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -257,8 +253,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -301,46 +297,45 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +COMMIT; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -351,36 +346,28 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -389,173 +376,123 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -564,78 +501,58 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z' +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:27.688000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -650,48 +567,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -700,10 +603,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -746,62 +647,45 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -812,207 +696,324 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -COMMIT; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z' +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.001000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -1027,34 +1028,55 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -NEW_CONNECTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -1063,8 +1085,11 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1107,71 +1132,116 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -1180,125 +1250,195 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -1307,60 +1447,85 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z' +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.314000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -1375,34 +1540,55 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -1411,8 +1597,11 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1455,46 +1644,69 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1505,217 +1717,208 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z' +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.639000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -1730,34 +1933,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -1766,8 +1969,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1810,230 +2013,282 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:28.902000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null -SHOW VARIABLE SPANNER.COMMIT_RESPONSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -2048,27 +2303,41 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -2077,7 +2346,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2120,254 +2391,254 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.148000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -2383,33 +2654,33 @@ SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -2419,7 +2690,7 @@ SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2463,76 +2734,66 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; -BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -COMMIT; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2542,122 +2803,98 @@ SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -2667,57 +2904,48 @@ SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.376000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -2733,33 +2961,26 @@ SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -2769,7 +2990,6 @@ SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2813,44 +3033,36 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -2862,39 +3074,26 @@ BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -2902,196 +3101,133 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -3099,86 +3235,59 @@ SET SPANNER.READONLY=TRUE; @EXPECT RESULT_SET 'SPANNER.READONLY',TRUE SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z' +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.657000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -3192,56 +3301,35 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -3249,12 +3337,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3296,117 +3381,84 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -3414,196 +3466,181 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -3611,86 +3648,77 @@ SET SPANNER.READONLY=TRUE; @EXPECT RESULT_SET 'SPANNER.READONLY',TRUE SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:29.941000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -3704,56 +3732,49 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -3761,12 +3782,11 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3808,282 +3828,305 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +NEW_CONNECTION; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.135000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -4097,35 +4140,42 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -4133,9 +4183,10 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4177,283 +4228,255 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.355000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.355000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -4467,42 +4490,35 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -4510,10 +4526,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4555,255 +4570,377 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.594000000Z'; +COMMIT; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.594000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -4817,35 +4954,56 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -4853,9 +5011,12 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4897,220 +5058,279 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; -SET AUTOCOMMIT=FALSE; SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z' +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.790000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -5124,28 +5344,35 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -5153,8 +5380,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5196,243 +5424,266 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=TRUE; +SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -NEW_CONNECTION; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:30.980000000Z'; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:30.980000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -5447,34 +5698,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -5483,8 +5734,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5527,284 +5778,380 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; +SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z' +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.151000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -5819,41 +6166,55 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -5862,9 +6223,11 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5907,87 +6270,113 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -5997,150 +6386,165 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6152,9 +6556,10 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6166,17 +6571,18 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE @@ -6186,77 +6592,84 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:31.485000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -6272,47 +6685,54 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -6322,9 +6742,10 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -6368,61 +6789,67 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -6433,137 +6860,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -6575,68 +7003,68 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READONLY=FALSE; +SET SPANNER.READONLY=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:31.700000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -6652,33 +7080,33 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -6688,7 +7116,7 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -6732,193 +7160,206 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -6929,76 +7370,76 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.018000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -7013,34 +7454,41 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -7049,8 +7497,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7093,200 +7542,190 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7297,76 +7736,65 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.292000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -7381,34 +7809,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -7417,8 +7845,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7461,81 +7889,67 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -7544,130 +7958,82 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7678,9 +8044,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -7691,16 +8055,11 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -7709,69 +8068,49 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z' +SET AUTOCOMMIT=FALSE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.518000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -7786,41 +8125,27 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -7829,9 +8154,7 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7874,54 +8197,36 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -7931,232 +8236,201 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'TEST',1 +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' +START BATCH DDL; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; -SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:32.770000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -8172,33 +8446,33 @@ SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -8208,7 +8482,7 @@ SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8252,242 +8526,283 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +START BATCH DDL; RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT UPDATE_COUNT 1 +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; -SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z' +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-03-23T14:42:33.018000000Z' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -8503,26 +8818,40 @@ SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -8532,6 +8861,8 @@ SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8575,66 +8906,86 @@ SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -8644,103 +8995,150 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -8752,7 +9150,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -8764,12 +9164,17 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE @@ -8779,57 +9184,77 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.206000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -8845,33 +9270,47 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -8881,7 +9320,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -8925,43 +9366,61 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -8972,198 +9431,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -9174,95 +9573,69 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READONLY=FALSE; -@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE -SHOW VARIABLE SPANNER.READONLY; -SET SPANNER.READONLY=TRUE; -@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE -SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.448000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:33.448000000Z' +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.449000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -9277,48 +9650,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -9327,10 +9686,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9373,303 +9730,272 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.677000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.677000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -9685,40 +10011,33 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -9728,8 +10047,7 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -9773,254 +10091,280 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:33.887000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:33.887000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -10035,34 +10379,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -10071,8 +10415,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10115,83 +10459,81 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -10200,167 +10542,130 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10371,11 +10676,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10386,19 +10689,16 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -10407,85 +10707,69 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.149000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -10500,55 +10784,41 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -10557,11 +10827,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10604,68 +10872,54 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -10675,207 +10929,232 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z' +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.333000000Z'; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -10890,34 +11169,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -10926,8 +11205,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10970,71 +11249,73 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11043,104 +11324,88 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11151,8 +11416,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11163,13 +11427,12 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -11178,58 +11441,51 @@ SET SPANNER.READONLY=TRUE; SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z' +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.517000000Z'; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -11244,34 +11500,27 @@ SET SPANNER.OPTIMIZER_VERSION=''; SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -11280,8 +11529,7 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11324,44 +11572,38 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -11371,40 +11613,27 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11412,206 +11641,126 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT UPDATE_COUNT 1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -11619,86 +11768,61 @@ SET SPANNER.READONLY=TRUE; @EXPECT RESULT_SET 'SPANNER.READONLY',TRUE SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z' +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:34.777000000Z'; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -11712,56 +11836,35 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -11769,12 +11872,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11816,113 +11916,85 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET AUTOCOMMIT=FALSE; @@ -11932,204 +12004,172 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.READONLY=FALSE; @@ -12139,84 +12179,77 @@ SET SPANNER.READONLY=TRUE; @EXPECT RESULT_SET 'SPANNER.READONLY',TRUE SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.084000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.OPTIMIZER_VERSION='1'; @@ -12232,54 +12265,47 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @@ -12289,10 +12315,9 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET STATEMENT_TIMEOUT='1s'; @@ -12336,283 +12361,273 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=TRUE; -NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READONLY=TRUE; -NEW_CONNECTION; SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.282000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -12627,34 +12642,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -12663,8 +12678,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -12707,286 +12722,260 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.509000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.509000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -13001,41 +12990,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13044,9 +13026,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13089,259 +13070,267 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null +@EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP' SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=FALSE; +@EXPECT RESULT_SET 'SPANNER.READONLY',FALSE +SHOW VARIABLE SPANNER.READONLY; SET SPANNER.READONLY=TRUE; +@EXPECT RESULT_SET 'SPANNER.READONLY',TRUE +SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.756000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.756000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' @@ -13356,34 +13345,34 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13392,8 +13381,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13436,68 +13425,75 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -13505,110 +13501,102 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT UPDATE_COUNT 1 +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.READ_TIMESTAMP',null SHOW VARIABLE SPANNER.READ_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.READONLY=FALSE; @EXPECT RESULT_SET 'SPANNER.READONLY',FALSE SHOW VARIABLE SPANNER.READONLY; @@ -13616,50 +13604,52 @@ SET SPANNER.READONLY=TRUE; @EXPECT RESULT_SET 'SPANNER.READONLY',TRUE SHOW VARIABLE SPANNER.READONLY; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','STRONG' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z' +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-03-23T14:42:35.963000000Z'; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_RESPONSE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','1' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; @@ -13673,28 +13663,28 @@ SET SPANNER.OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_VERSION','' SHOW VARIABLE SPANNER.OPTIMIZER_VERSION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.COMMIT_TIMESTAMP',null SHOW VARIABLE SPANNER.COMMIT_TIMESTAMP; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; @@ -13702,8 +13692,8 @@ SET SPANNER.OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13745,44 +13735,47 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'SPANNER.OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE SPANNER.OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET SPANNER.TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET SPANNER.READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET SPANNER.READONLY=TRUE; +SET AUTOCOMMIT=TRUE; From 1038de8bb85532b7bcfadfb22dfbca14c07869b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 4 May 2024 10:00:16 +0200 Subject: [PATCH 1272/1979] feat: allow DDL with autocommit=false (#1600) Adds support for running DDL statements when a connection is in autocommit=false mode. By default, DDL statements are only allowed when no transaction is active. That is; no query or DML statement has been executed which activated a read/write transaction. A new flag is added that can be used to revert the behavior back to the original behavior where DDL is always refused when autocommit=false. The same flag can also be used to make the API behave the same as MySQL and Oracle, where any active transaction is automatically committed whenever a DDL statement is encountered. Concretely this means that the following is now allowed: ``` set autocommit=false; create table Singers (SingerId INT64, Name STRING(MAX)) PRIMARY KEY (SingerId); ``` The following is by default NOT allowed, unless ddlInTransactionMode=AUTO_COMMIT_TRANSACTION ``` set autocommit=false; select * from singers; -- This starts a transaction create table Albums (AlbumId INT64) PRIMARY KEY (AlbumId); -- This is not allowed ``` --- .../cloud/spanner/jdbc/DdlMockServerTest.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java new file mode 100644 index 000000000000..76cac4fa604f --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.longrunning.Operation; +import com.google.protobuf.Any; +import com.google.protobuf.Empty; +import com.google.rpc.Code; +import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DdlMockServerTest extends AbstractMockServerTest { + + private String createUrl(boolean autoCommit) { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=%s", + getPort(), "proj", "inst", "db", autoCommit); + } + + private Connection createConnection(boolean autoCommit) throws SQLException { + return DriverManager.getConnection(createUrl(autoCommit)); + } + + @Test + public void testDdlInAutoCommitIsTrue_succeeds() throws SQLException { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + + try (Connection connection = createConnection(/* autoCommit = */ true)) { + assertFalse( + connection.createStatement().execute("create table foo (id int64) primary key (id)")); + } + } + + @Test + public void testDdlInAutoCommitIsFalse_succeedsWithNoActiveTransaction() throws SQLException { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + + try (Connection connection = createConnection(/* autoCommit = */ false)) { + assertFalse( + connection.createStatement().execute("create table foo (id int64) primary key (id)")); + } + } + + @Test + public void testDdlInAutoCommitIsFalse_failsWithActiveTransaction() throws SQLException { + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("update foo set bar=1 where true"), 1L)); + + try (Connection connection = createConnection(/* autoCommit = */ false)) { + assertFalse(connection.createStatement().execute("update foo set bar=1 where true")); + SQLException exception = + assertThrows( + SQLException.class, + () -> + connection + .createStatement() + .execute("create table foo (id int64) primary key (id)")); + assertTrue(exception instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) exception; + assertEquals(Code.FAILED_PRECONDITION, jdbcSqlException.getCode()); + } + } +} From aebab713267191236288e19a2f3b0a9dbd849d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 4 May 2024 10:08:07 +0200 Subject: [PATCH 1273/1979] feat: support concurrent transactions on the emulator (#1601) Adds support for overlapping transactions on the emulator in the Connection API, even when these are executed on one thread. This is normally not supported, as it requires multiple transactions to run concurrently on the emulator. This change works around that by keeping track of what the active transaction on the emulator is, and then abort that transaction when another transaction needs to make progress. The transaction that was aborted will be retried up to the point where it was when it again wants to make progress. This step-by-step progress is implemented by automatically setting a savepoint in the transaction after each successful step. The transaction is then rolled back to that savepoint when another transaction needs to make progress. The feature is only enabled if the autoConfigEmulator flag is enabled. --- .../java/com/google/cloud/spanner/jdbc/JdbcDriver.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 54d699b654e7..cdefb7363f7b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -84,6 +84,13 @@ * instance and database in the connection string will automatically be created if these do * not yet exist on the emulator. This means that you do not need to execute any `gcloud` * commands on the emulator to create the instance and database before you can connect to it. + * Setting this property to true also enables running concurrent transactions on the emulator. + * The emulator aborts any concurrent transaction on the emulator, and the JDBC driver works + * around this by automatically setting a savepoint after each statement that is executed. + * When the transaction has been aborted by the emulator and the JDBC connection wants to + * continue with that transaction, the transaction is replayed up until the savepoint that had + * automatically been set after the last statement that was executed before the transaction + * was aborted by the emulator. *
  • endpoint (string): Set this property to specify a custom endpoint that the JDBC driver * should connect to. You can use this property in combination with the autoConfigEmulator * property to instruct the JDBC driver to connect to an emulator instance that uses a From e12543d86ad6a6138aa6a9c3de0bd9bca643698a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 11:18:16 +0000 Subject: [PATCH 1274/1979] chore(main): release 2.18.0 (#1598) :robot: I have created a release *beep* *boop* --- ## [2.18.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.17.1...v2.18.0) (2024-05-04) ### Features * Allow DDL with autocommit=false ([#1600](https://togithub.com/googleapis/java-spanner-jdbc/issues/1600)) ([1038de8](https://togithub.com/googleapis/java-spanner-jdbc/commit/1038de8bb85532b7bcfadfb22dfbca14c07869b2)) * Support concurrent transactions on the emulator ([#1601](https://togithub.com/googleapis/java-spanner-jdbc/issues/1601)) ([aebab71](https://togithub.com/googleapis/java-spanner-jdbc/commit/aebab713267191236288e19a2f3b0a9dbd849d8f)) ### Bug Fixes * ClassCastException in Spring Data JDBC sample ([#1595](https://togithub.com/googleapis/java-spanner-jdbc/issues/1595)) ([1408060](https://togithub.com/googleapis/java-spanner-jdbc/commit/14080603c60e126f719f9bbcd28488865e8cf335)) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.66.0 ([#1599](https://togithub.com/googleapis/java-spanner-jdbc/issues/1599)) ([ec78e54](https://togithub.com/googleapis/java-spanner-jdbc/commit/ec78e5411e410c82f43f4ca14539c2b2d5bf8ff1)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.30.0 ([#1597](https://togithub.com/googleapis/java-spanner-jdbc/issues/1597)) ([718106b](https://togithub.com/googleapis/java-spanner-jdbc/commit/718106b59aff4b0f834140b60294c32907b81b0a)) * Update dependency org.mybatis.dynamic-sql:mybatis-dynamic-sql to v1.5.1 ([#1596](https://togithub.com/googleapis/java-spanner-jdbc/issues/1596)) ([5994c09](https://togithub.com/googleapis/java-spanner-jdbc/commit/5994c09dc41410b41af19806161d5866fe496dfa)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4605592d2fbf..d820a21dd086 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.18.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.17.1...v2.18.0) (2024-05-04) + + +### Features + +* Allow DDL with autocommit=false ([#1600](https://github.com/googleapis/java-spanner-jdbc/issues/1600)) ([a61c25d](https://github.com/googleapis/java-spanner-jdbc/commit/a61c25d8f90460ec507b383dbaee0ca686104ba8)) +* Support concurrent transactions on the emulator ([#1601](https://github.com/googleapis/java-spanner-jdbc/issues/1601)) ([7123991](https://github.com/googleapis/java-spanner-jdbc/commit/71239912a8078569dcd985314810131e593c0ed7)) + + +### Bug Fixes + +* ClassCastException in Spring Data JDBC sample ([#1595](https://github.com/googleapis/java-spanner-jdbc/issues/1595)) ([e96a86a](https://github.com/googleapis/java-spanner-jdbc/commit/e96a86a4b82ac4b47bd1ce25e810f01299597339)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.66.0 ([#1599](https://github.com/googleapis/java-spanner-jdbc/issues/1599)) ([84ea11a](https://github.com/googleapis/java-spanner-jdbc/commit/84ea11ac27635dbe6fb101134767d14488dde8c2)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.30.0 ([#1597](https://github.com/googleapis/java-spanner-jdbc/issues/1597)) ([40a7212](https://github.com/googleapis/java-spanner-jdbc/commit/40a721237c79882e55d86d48402c64cc09782522)) +* Update dependency org.mybatis.dynamic-sql:mybatis-dynamic-sql to v1.5.1 ([#1596](https://github.com/googleapis/java-spanner-jdbc/issues/1596)) ([f54beb2](https://github.com/googleapis/java-spanner-jdbc/commit/f54beb20d6bbe3f4974385c4758ba77d31d25ce3)) + ## [2.17.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.17.0...v2.17.1) (2024-04-30) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 85839f1e0bf9..3b717ff2e46a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.17.2-SNAPSHOT + 2.18.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index beebe6a8725b..1675895dd4a1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.2-SNAPSHOT + 2.18.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fa461f16e844..ed96e77f6c49 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.17.1:2.17.2-SNAPSHOT +google-cloud-spanner-jdbc:2.18.0:2.18.0 From e63d238ebfd905dbbf71442265300459d7d9b5c0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 12:38:16 +0000 Subject: [PATCH 1275/1979] chore(main): release 2.18.1-SNAPSHOT (#1602) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3b717ff2e46a..878ed8b050dd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.18.0 + 2.18.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1675895dd4a1..17be77fe572a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.0 + 2.18.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index ed96e77f6c49..e3f166be0857 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.18.0:2.18.0 +google-cloud-spanner-jdbc:2.18.0:2.18.1-SNAPSHOT From 4b415d9e0f7f589575a94733ac4d81f7b1fe36b7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 6 May 2024 17:42:00 +0200 Subject: [PATCH 1276/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.18.0 (#1603) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b3e406165fd2..5280486b9fa6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.17.1 + 2.18.0 From 97d113244a898875ce85dc4d104d1ebbc659e3ff Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 10 May 2024 19:43:22 +0200 Subject: [PATCH 1277/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.39.0 (#1590) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index efedc8e12d20..bd5be074cc45 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.37.0 + 26.39.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 960fe8da4ed0..318a4f2b269f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.37.0 + 26.39.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index c06aec138933..4396f4d32e75 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.37.0 + 26.39.0 import pom From dd2b60f3effe8bafa7bef81c626fde6f41f0d5e3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 10 May 2024 19:43:39 +0200 Subject: [PATCH 1278/1979] deps: update dependency org.testcontainers:testcontainers to v1.19.8 (#1604) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 878ed8b050dd..ad184c05ce18 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -174,7 +174,7 @@ org.testcontainers testcontainers - 1.19.7 + 1.19.8 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index bd5be074cc45..7d685eb4776d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -48,7 +48,7 @@ org.testcontainers testcontainers - 1.19.7 + 1.19.8 test From 70f146402aee28bb6dbf94fa3252e8975958c2b1 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 20:04:03 +0200 Subject: [PATCH 1279/1979] chore: update dependency versions in java templates (#1964) (#1605) * chore: update dependency versions in java templates * update other templates Source-Link: https://github.com/googleapis/synthtool/commit/0b86c72fe652dd7e52ba05a63f61bc1399ad5d65 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 +-- .../.github/workflows/approve-readme.yaml | 2 +- java-spanner-jdbc/.github/workflows/ci.yaml | 30 +++++++++---------- .../workflows/renovate_config_check.yaml | 2 +- .../.github/workflows/samples.yaml | 4 +-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 6167135e9534..5db36a5f7d8e 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:81c3ec554428c8ff6c92f0d58668b7ef52265d053a82284c97a326745e786949 -# created: 2024-03-27T17:59:25.436353226Z + digest: sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e +# created: 2024-05-09T16:31:37.168667071Z diff --git a/java-spanner-jdbc/.github/workflows/approve-readme.yaml b/java-spanner-jdbc/.github/workflows/approve-readme.yaml index f5fc7d5169eb..59f00b8eb6e6 100644 --- a/java-spanner-jdbc/.github/workflows/approve-readme.yaml +++ b/java-spanner-jdbc/.github/workflows/approve-readme.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} script: | diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index ae66b1973b17..b91fa381f56b 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -27,8 +27,8 @@ jobs: matrix: java: [11, 17, 21] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{matrix.java}} @@ -41,8 +41,8 @@ jobs: name: "units (8)" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: java-version: 8 distribution: temurin @@ -51,7 +51,7 @@ jobs: # 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 + - uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin @@ -63,8 +63,8 @@ jobs: steps: - name: Support longpaths run: git config --system core.longpaths true - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 @@ -78,8 +78,8 @@ jobs: matrix: java: [17] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{matrix.java}} @@ -88,8 +88,8 @@ jobs: javadoc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 @@ -100,8 +100,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 @@ -112,8 +112,8 @@ jobs: clirr: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml b/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml index 87d8eb2be8cd..7c5ec7865e11 100644 --- a/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml +++ b/java-spanner-jdbc/.github/workflows/renovate_config_check.yaml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '20' diff --git a/java-spanner-jdbc/.github/workflows/samples.yaml b/java-spanner-jdbc/.github/workflows/samples.yaml index 10d252d77538..03b2939567a9 100644 --- a/java-spanner-jdbc/.github/workflows/samples.yaml +++ b/java-spanner-jdbc/.github/workflows/samples.yaml @@ -20,8 +20,8 @@ jobs: checkstyle: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 From 6a6b91223b855972659108bc479c226b8b60ebea Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 15 May 2024 09:19:05 +0200 Subject: [PATCH 1280/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.38.0 (#1606) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ad184c05ce18..c2922c75556c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -69,7 +69,7 @@ io.opentelemetry opentelemetry-bom - 1.37.0 + 1.38.0 pom import From b567d7a61dbce3e2e2542b85a1889f463426446a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 16 May 2024 15:55:46 +0200 Subject: [PATCH 1281/1979] deps: remove open-telemetry dependency import (#1608) Remove the open-telemetry dependency import, as it is already defined in the shared dependencies. --- java-spanner-jdbc/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c2922c75556c..3ad14161b06b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -66,13 +66,6 @@ pom import - - io.opentelemetry - opentelemetry-bom - 1.38.0 - pom - import - com.google.cloud google-cloud-shared-dependencies From 2da6a4c8cfa0b947a7fe4bab91bd56d9b1427d1a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 May 2024 08:07:25 +0200 Subject: [PATCH 1282/1979] deps: update dependency org.springframework.data:spring-data-bom to v2023.1.6 (#1610) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 318a4f2b269f..7303c215b756 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.1.5 + 2023.1.6 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 4396f4d32e75..c4137b5fdc33 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.1.5 + 2023.1.6 import pom From cfe6cb5cba62603ea31aa0d9f08d5ebba5b647ae Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 20 May 2024 08:07:44 +0200 Subject: [PATCH 1283/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.6.0 (#1612) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5280486b9fa6..6dab90d5751a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.5.0 + 3.6.0 add-snippets-source diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 17be77fe572a..9fbeaa1cba9c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.5.0 + 3.6.0 add-snippets-source From 389e174c8d4a9a3ebebfd233978b793b55b537d8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 21 May 2024 11:34:49 +0200 Subject: [PATCH 1284/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.30.1 (#1609) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 0c869e6b0e62..fdecc15b402a 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.30.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.30.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index b20ec8ff3525..532f888ecbb9 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.30.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.30.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index aad0db97859a..1292cf163b17 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.30.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.30.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ad14161b06b..da528eba1d5e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.30.0 + 3.30.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7d685eb4776d..efd50fa3d1b5 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.30.0 + 3.30.1 From abc482b790e7013067aa2d6cf2816cd78e9e1f34 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 21 May 2024 11:35:01 +0200 Subject: [PATCH 1285/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024 (#1611) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 7303c215b756..615223b736cf 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2023.1.6 + 2024.0.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index c4137b5fdc33..bb8ede8e1b0e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2023.1.6 + 2024.0.0 import pom From 64a72d42ab577e8e32335422d4bea23bbdc60815 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 22 May 2024 21:36:18 +0200 Subject: [PATCH 1286/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.67.0 (#1613) 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.66.0` -> `6.67.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.67.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.67.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.66.0/6.67.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.66.0/6.67.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.67.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6670-2024-05-22) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.66.0...v6.67.0) ##### Features - Add tracing for batchUpdate, executeUpdate, and connections ([#​3097](https://togithub.com/googleapis/java-spanner/issues/3097)) ([45cdcfc](https://togithub.com/googleapis/java-spanner/commit/45cdcfcde02aa7976b017a90f81c2ccd28658c8f)) ##### Performance Improvements - Minor optimizations to the standard query path ([#​3101](https://togithub.com/googleapis/java-spanner/issues/3101)) ([ec820a1](https://togithub.com/googleapis/java-spanner/commit/ec820a16e2b3cb1a12a15231491b75cd73afaa13)) ##### Dependencies - Update dependency com.google.cloud:google-cloud-monitoring to v3.44.0 ([#​3099](https://togithub.com/googleapis/java-spanner/issues/3099)) ([da44e93](https://togithub.com/googleapis/java-spanner/commit/da44e932a39ac0124b63914f8ea926998c10ea2e)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.30.1 ([#​3116](https://togithub.com/googleapis/java-spanner/issues/3116)) ([d205a73](https://togithub.com/googleapis/java-spanner/commit/d205a73714786a609673012b771e7a0722b3e1f2))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index da528eba1d5e..477ceca39515 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.66.0 + 6.67.0 pom import From d4a5236d5f4da2631d7695561c58641df324a04e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 20:58:18 +0000 Subject: [PATCH 1287/1979] chore(main): release 2.18.1 (#1607) :robot: I have created a release *beep* *boop* --- ## [2.18.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.18.0...v2.18.1) (2024-05-22) ### Dependencies * Remove open-telemetry dependency import ([#1608](https://togithub.com/googleapis/java-spanner-jdbc/issues/1608)) ([b567d7a](https://togithub.com/googleapis/java-spanner-jdbc/commit/b567d7a61dbce3e2e2542b85a1889f463426446a)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.67.0 ([#1613](https://togithub.com/googleapis/java-spanner-jdbc/issues/1613)) ([64a72d4](https://togithub.com/googleapis/java-spanner-jdbc/commit/64a72d42ab577e8e32335422d4bea23bbdc60815)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.30.1 ([#1609](https://togithub.com/googleapis/java-spanner-jdbc/issues/1609)) ([389e174](https://togithub.com/googleapis/java-spanner-jdbc/commit/389e174c8d4a9a3ebebfd233978b793b55b537d8)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.38.0 ([#1606](https://togithub.com/googleapis/java-spanner-jdbc/issues/1606)) ([6a6b912](https://togithub.com/googleapis/java-spanner-jdbc/commit/6a6b91223b855972659108bc479c226b8b60ebea)) * Update dependency org.springframework.data:spring-data-bom to v2023.1.6 ([#1610](https://togithub.com/googleapis/java-spanner-jdbc/issues/1610)) ([2da6a4c](https://togithub.com/googleapis/java-spanner-jdbc/commit/2da6a4c8cfa0b947a7fe4bab91bd56d9b1427d1a)) * Update dependency org.springframework.data:spring-data-bom to v2024 ([#1611](https://togithub.com/googleapis/java-spanner-jdbc/issues/1611)) ([abc482b](https://togithub.com/googleapis/java-spanner-jdbc/commit/abc482b790e7013067aa2d6cf2816cd78e9e1f34)) * Update dependency org.testcontainers:testcontainers to v1.19.8 ([#1604](https://togithub.com/googleapis/java-spanner-jdbc/issues/1604)) ([dd2b60f](https://togithub.com/googleapis/java-spanner-jdbc/commit/dd2b60f3effe8bafa7bef81c626fde6f41f0d5e3)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d820a21dd086..6e731ee2b327 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.18.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.18.0...v2.18.1) (2024-05-22) + + +### Dependencies + +* Remove open-telemetry dependency import ([#1608](https://github.com/googleapis/java-spanner-jdbc/issues/1608)) ([fcb32ef](https://github.com/googleapis/java-spanner-jdbc/commit/fcb32efb4945807e0933341874644f042b7f33af)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.67.0 ([#1613](https://github.com/googleapis/java-spanner-jdbc/issues/1613)) ([12080e0](https://github.com/googleapis/java-spanner-jdbc/commit/12080e0579269fd9b893440d2f6ff3e784fb52ec)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.30.1 ([#1609](https://github.com/googleapis/java-spanner-jdbc/issues/1609)) ([46aed65](https://github.com/googleapis/java-spanner-jdbc/commit/46aed65c39cd9c6e60733fdf9cfd11f770e77019)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.38.0 ([#1606](https://github.com/googleapis/java-spanner-jdbc/issues/1606)) ([b45bed5](https://github.com/googleapis/java-spanner-jdbc/commit/b45bed575bc53898205aa183d7d8554b336a68f9)) +* Update dependency org.springframework.data:spring-data-bom to v2023.1.6 ([#1610](https://github.com/googleapis/java-spanner-jdbc/issues/1610)) ([aac170d](https://github.com/googleapis/java-spanner-jdbc/commit/aac170db26f8018b44f97d17f92faecb11117269)) +* Update dependency org.springframework.data:spring-data-bom to v2024 ([#1611](https://github.com/googleapis/java-spanner-jdbc/issues/1611)) ([6669c7a](https://github.com/googleapis/java-spanner-jdbc/commit/6669c7af373160fa9396a6dbcf2adff091d3c46a)) +* Update dependency org.testcontainers:testcontainers to v1.19.8 ([#1604](https://github.com/googleapis/java-spanner-jdbc/issues/1604)) ([e155a46](https://github.com/googleapis/java-spanner-jdbc/commit/e155a4624a021cb7959e72f7eb138ff8c685eaef)) + ## [2.18.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.17.1...v2.18.0) (2024-05-04) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 477ceca39515..dbd49408abda 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.18.1-SNAPSHOT + 2.18.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9fbeaa1cba9c..54619d9b8d38 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.1-SNAPSHOT + 2.18.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e3f166be0857..689c3863c556 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.18.0:2.18.1-SNAPSHOT +google-cloud-spanner-jdbc:2.18.1:2.18.1 From c54f0acd8f42cd5957827738c22d607650e2e6cd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 08:43:13 +0200 Subject: [PATCH 1288/1979] chore(main): release 2.18.2-SNAPSHOT (#1614) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dbd49408abda..a9b995ce823c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.18.1 + 2.18.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 54619d9b8d38..46e0fc60d9a4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.1 + 2.18.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 689c3863c556..de4db31cf7d5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.18.1:2.18.1 +google-cloud-spanner-jdbc:2.18.1:2.18.2-SNAPSHOT From 37e3ac99f972711efe0170aa8cd73128baf40ff7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 May 2024 08:43:33 +0200 Subject: [PATCH 1289/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.18.1 (#1615) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6dab90d5751a..9509c6bae55f 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.0 + 2.18.1 From 0e3f1538f05b00c809869b4868bf5fa896ec6c02 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 May 2024 20:06:32 +0200 Subject: [PATCH 1290/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.0 (#1616) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 615223b736cf..5aa23101ffc3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.2.5 + 3.3.0 From 157eb585c2789170ff94b5a22c7e38eaf43083f1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 May 2024 09:17:40 +0200 Subject: [PATCH 1291/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.0 (#1617) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index bb8ede8e1b0e..b8834866656a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.5 + 3.3.0 From 2a239b8083209f03789d8ec5b5ba752e1a6d39e5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 May 2024 17:06:04 +0200 Subject: [PATCH 1292/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.0 (#1620) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a9b995ce823c..56d86ef7ee10 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.67.0 + 6.68.0 pom import From 9238075ae240118852ff5c957031a4de2974b69e Mon Sep 17 00:00:00 2001 From: Sri Harsha CH <57220027+harshachinta@users.noreply.github.com> Date: Tue, 28 May 2024 17:19:23 +0530 Subject: [PATCH 1293/1979] feat: add Proto Columns support in JDBC (#1252) * feat: add code changes to support DML for Proto Columns * feat: support DML for Proto Columns * feat: add untyped null when inserting null value in array of proto columns * feat: add code changes to support DDL for Proto Columns * feat: code changes to support getArray and getResultSet in JdbcArray for Proto columns * feat: add unit tests for DML and DQL * feat: add integration tests for Proto Columns DDL * feat: add integration tests for Proto columns DML and DQL * feat: lint format * feat: code refactoring to throw exceptions and handle null values in JdbcArray * feat: update tests to validate null in JdbcArray * feat: Integration test refactoring * fix: add copyright header * feat: update junit assertions * feat: move array conversion logic for protos to seperate methods in JdbcTypeConverter * feat: add review suggestions to JdbcArray * feat: add review suggestion * feat: add review suggestions in JdbcParameterStore file * feat: add untyped null integration test * feat: add inter compatibilty and lint fix * feat: update schema and base64 protodescriptors files * feat: nit * chore: update java-spanner version * chore: lint fix * chore: skip tests on graalvm * chore: nit fixes --- .../clirr-ignored-differences.xml | 15 + .../spanner/jdbc/AbstractJdbcWrapper.java | 6 + .../jdbc/CloudSpannerJdbcConnection.java | 34 + .../google/cloud/spanner/jdbc/JdbcArray.java | 108 +- .../cloud/spanner/jdbc/JdbcConnection.java | 33 + .../cloud/spanner/jdbc/JdbcDataType.java | 59 + .../spanner/jdbc/JdbcParameterStore.java | 111 +- .../cloud/spanner/jdbc/JdbcResultSet.java | 32 + .../cloud/spanner/jdbc/JdbcTypeConverter.java | 119 +- .../cloud/spanner/jdbc/ProtoEnumType.java | 55 + .../cloud/spanner/jdbc/ProtoMessageType.java | 55 + .../cloud/spanner/jdbc/JdbcArrayTest.java | 74 + .../spanner/jdbc/JdbcParameterStoreTest.java | 139 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 130 +- .../spanner/jdbc/JdbcTypeConverterTest.java | 123 +- .../spanner/jdbc/it/ITProtoColumnsTest.java | 273 ++++ .../cloud/spanner/jdbc/it/SingerProto.java | 1191 +++++++++++++++++ .../google/cloud/spanner/jdbc/ITDdlTest.sql | 41 +- .../cloud/spanner/jdbc/it/descriptors.pb | Bin 0 -> 377 bytes .../google/cloud/spanner/jdbc/it/singer.proto | 21 + 20 files changed, 2590 insertions(+), 29 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/descriptors.pb create mode 100644 java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/singer.proto diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index acf11c5870e2..368e9ed99c36 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -57,5 +57,20 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setMaxPartitions(int) + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + byte[] getProtoDescriptors() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setProtoDescriptors(byte[]) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setProtoDescriptors(java.io.InputStream) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index aa65ee6f98f4..cd66cb38c17b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -48,6 +48,7 @@ static int extractColumnType(Type type) { case BOOL: return Types.BOOLEAN; case BYTES: + case PROTO: return Types.BINARY; case DATE: return Types.DATE; @@ -56,6 +57,7 @@ static int extractColumnType(Type type) { case FLOAT64: return Types.DOUBLE; case INT64: + case ENUM: return Types.BIGINT; case NUMERIC: case PG_NUMERIC: @@ -145,6 +147,7 @@ static String getClassName(Type type) { case BOOL: return Boolean.class.getName(); case BYTES: + case PROTO: return byte[].class.getName(); case DATE: return Date.class.getName(); @@ -153,6 +156,7 @@ static String getClassName(Type type) { case FLOAT64: return Double.class.getName(); case INT64: + case ENUM: return Long.class.getName(); case NUMERIC: case PG_NUMERIC: @@ -168,6 +172,7 @@ static String getClassName(Type type) { case BOOL: return Boolean[].class.getName(); case BYTES: + case PROTO: return byte[][].class.getName(); case DATE: return Date[].class.getName(); @@ -176,6 +181,7 @@ static String getClassName(Type type) { case FLOAT64: return Double[].class.getName(); case INT64: + case ENUM: return Long[].class.getName(); case NUMERIC: case PG_NUMERIC: diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index c161ee50a7db..6795054d99fc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -28,11 +28,14 @@ import com.google.cloud.spanner.connection.AutocommitDmlMode; import com.google.cloud.spanner.connection.SavepointSupport; import com.google.cloud.spanner.connection.TransactionMode; +import java.io.IOException; +import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Iterator; +import javax.annotation.Nonnull; /** * JDBC connection with a number of additional Cloud Spanner specific methods. JDBC connections that @@ -448,4 +451,35 @@ Iterator getTransactionR */ Iterator getTransactionRetryListenersFromConnection() throws SQLException; + + /** + * Sets the proto descriptors to use for the next DDL statement (single or batch) that will be + * executed. The proto descriptor is automatically cleared after the statement is executed. + * + * @param protoDescriptors The proto descriptors to use with the next DDL statement (single or + * batch) that will be executed on this connection. + */ + default void setProtoDescriptors(@Nonnull byte[] protoDescriptors) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the proto descriptors to use for the next DDL statement (single or batch) that will be + * executed. The proto descriptor is automatically cleared after the statement is executed. + * + * @param protoDescriptors The proto descriptors to use with the next DDL statement (single or + * batch) that will be executed on this connection. + */ + default void setProtoDescriptors(@Nonnull InputStream protoDescriptors) + throws SQLException, IOException { + throw new UnsupportedOperationException(); + } + + /** + * @return The proto descriptor that will be used with the next DDL statement (single or batch) + * that is executed on this connection. + */ + default byte[] getProtoDescriptors() throws SQLException { + throw new UnsupportedOperationException(); + } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 4ef2ac21538c..80bea84ebd95 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -24,6 +24,11 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.common.collect.ImmutableList; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Message; +import com.google.protobuf.ProtocolMessageEnum; import com.google.rpc.Code; import java.math.BigDecimal; import java.sql.Array; @@ -78,7 +83,16 @@ static JdbcArray createArray(JdbcDataType type, List elements) { private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException { this.type = type; if (elements != null) { - this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length); + if ((type.getCode() == Type.Code.PROTO + && AbstractMessage[].class.isAssignableFrom(elements.getClass())) + || (type.getCode() == Type.Code.ENUM + && ProtocolMessageEnum[].class.isAssignableFrom(elements.getClass()))) { + this.data = + java.lang.reflect.Array.newInstance( + elements.getClass().getComponentType(), elements.length); + } else { + this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length); + } try { System.arraycopy(elements, 0, this.data, 0, elements.length); } catch (Exception e) { @@ -138,9 +152,17 @@ public Object getArray(long index, int count) throws SQLException { @Override public Object getArray(long index, int count, Map> map) throws SQLException { checkFree(); - if (data != null) { - Object res = java.lang.reflect.Array.newInstance(type.getJavaClass(), count); - System.arraycopy(data, (int) index - 1, res, 0, count); + if (this.data != null) { + Object res; + if ((this.type.getCode() == Type.Code.PROTO + && AbstractMessage[].class.isAssignableFrom(this.data.getClass())) + || (this.type.getCode() == Type.Code.ENUM + && ProtocolMessageEnum[].class.isAssignableFrom(this.data.getClass()))) { + res = java.lang.reflect.Array.newInstance(this.data.getClass().getComponentType(), count); + } else { + res = java.lang.reflect.Array.newInstance(this.type.getJavaClass(), count); + } + System.arraycopy(this.data, (int) index - 1, res, 0, count); return res; } return null; @@ -167,24 +189,37 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { JdbcPreconditions.checkArgument(startIndex >= 1L, "Start index must be >= 1"); JdbcPreconditions.checkArgument(count >= 0, "Count must be >= 0"); checkFree(); + Type spannerTypeForProto = getSpannerTypeForProto(); + Type spannerType = + spannerTypeForProto == null ? this.type.getSpannerType() : spannerTypeForProto; + ImmutableList.Builder rows = ImmutableList.builder(); int added = 0; - if (data != null) { + if (this.data != null) { // Note that array index in JDBC is base-one. for (int index = (int) startIndex; - added < count && index <= ((Object[]) data).length; + added < count && index <= ((Object[]) this.data).length; index++) { - Object value = ((Object[]) data)[index - 1]; + Object value = ((Object[]) this.data)[index - 1]; ValueBinder binder = Struct.newBuilder().set("INDEX").to(index).set("VALUE"); Struct.Builder builder; - switch (type.getCode()) { + switch (this.type.getCode()) { case BOOL: builder = binder.to((Boolean) value); break; case BYTES: builder = binder.to(ByteArray.copyFrom((byte[]) value)); break; + case PROTO: + if (value == null && AbstractMessage[].class.isAssignableFrom(this.data.getClass())) { + builder = binder.to((ByteArray) null, spannerType.getProtoTypeFqn()); + } else if (value instanceof AbstractMessage) { + builder = binder.to((AbstractMessage) value); + } else { + builder = binder.to(value != null ? ByteArray.copyFrom((byte[]) value) : null); + } + break; case DATE: builder = binder.to(JdbcTypeConverter.toGoogleDate((Date) value)); break; @@ -197,6 +232,16 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { case INT64: builder = binder.to((Long) value); break; + case ENUM: + if (value == null + && ProtocolMessageEnum[].class.isAssignableFrom(this.data.getClass())) { + builder = binder.to((Long) null, spannerType.getProtoTypeFqn()); + } else if (value instanceof ProtocolMessageEnum) { + builder = binder.to((ProtocolMessageEnum) value); + } else { + builder = binder.to((Long) value); + } + break; case NUMERIC: builder = binder.to((BigDecimal) value); break; @@ -217,7 +262,8 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { default: throw new SQLFeatureNotSupportedException( String.format( - "Array of type %s cannot be converted to a ResultSet", type.getCode().name())); + "Array of type %s cannot be converted to a ResultSet", + this.type.getCode().name())); } rows.add(builder.build()); added++; @@ -226,14 +272,54 @@ public ResultSet getResultSet(long startIndex, int count) throws SQLException { } } } + return JdbcResultSet.of( ResultSets.forRows( Type.struct( - StructField.of("INDEX", Type.int64()), - StructField.of("VALUE", type.getSpannerType())), + StructField.of("INDEX", Type.int64()), StructField.of("VALUE", spannerType)), rows.build())); } + // Returns null if the type is not a PROTO or ENUM + private Type getSpannerTypeForProto() throws SQLException { + Type spannerType = null; + if (this.data != null) { + if (this.type.getCode() == Type.Code.PROTO + && AbstractMessage[].class.isAssignableFrom(this.data.getClass())) { + spannerType = createSpannerProtoType(); + } else if (this.type.getCode() == Type.Code.ENUM + && ProtocolMessageEnum[].class.isAssignableFrom(this.data.getClass())) { + spannerType = createSpannerProtoEnumType(); + } + } + return spannerType; + } + + private Type createSpannerProtoType() throws SQLException { + Class componentType = this.data.getClass().getComponentType(); + try { + Message.Builder builder = + (Message.Builder) componentType.getMethod("newBuilder").invoke(null); + Descriptor msgDescriptor = builder.getDescriptorForType(); + return Type.proto(msgDescriptor.getFullName()); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Error occurred when getting proto message descriptor from data", Code.UNKNOWN, e); + } + } + + private Type createSpannerProtoEnumType() throws SQLException { + Class componentType = this.data.getClass().getComponentType(); + try { + Descriptors.EnumDescriptor enumDescriptor = + (Descriptors.EnumDescriptor) componentType.getMethod("getDescriptor").invoke(null); + return Type.protoEnum(enumDescriptor.getFullName()); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Error occurred when getting proto enum descriptor from data", Code.UNKNOWN, e); + } + } + @Override public ResultSet getResultSet(long index, int count, Map> map) throws SQLException { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index bafdc6b09d19..3c61781415a9 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -20,6 +20,7 @@ import static com.google.cloud.spanner.jdbc.JdbcStatement.isNullOrEmpty; import com.google.api.client.util.Preconditions; +import com.google.cloud.ByteArray; import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Mutation; @@ -38,6 +39,8 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; +import java.io.IOException; +import java.io.InputStream; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; @@ -867,4 +870,34 @@ public Iterator getTransactionRetryListeners() throws checkClosed(); return getSpannerConnection().getTransactionRetryListeners(); } + + @Override + public void setProtoDescriptors(@Nonnull byte[] protoDescriptors) throws SQLException { + Preconditions.checkNotNull(protoDescriptors); + checkClosed(); + try { + getSpannerConnection().setProtoDescriptors(protoDescriptors); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public void setProtoDescriptors(@Nonnull InputStream protoDescriptors) + throws SQLException, IOException { + Preconditions.checkNotNull(protoDescriptors); + checkClosed(); + try { + getSpannerConnection() + .setProtoDescriptors(ByteArray.copyFrom(protoDescriptors).toByteArray()); + } catch (SpannerException e) { + throw JdbcSqlExceptionFactory.of(e); + } + } + + @Override + public byte[] getProtoDescriptors() throws SQLException { + checkClosed(); + return getSpannerConnection().getProtoDescriptors(); + } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index b920d3d55ecd..d73233c32369 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -404,6 +404,65 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.struct(); } + }, + PROTO { + @Override + public int getSqlType() { + return ProtoMessageType.VENDOR_TYPE_NUMBER; + } + + @Override + public Class getJavaClass() { + return byte[].class; + } + + @Override + public Code getCode() { + return Code.PROTO; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return JdbcTypeConverter.toJavaByteArrays(rs.getBytesList(columnIndex)); + } + + @Override + public Type getSpannerType() { + return Type.bytes(); + } + }, + ENUM { + private final Set> classes = new HashSet<>(Arrays.asList(Integer.class, Long.class)); + + @Override + public int getSqlType() { + return ProtoEnumType.VENDOR_TYPE_NUMBER; + } + + @Override + public Class getJavaClass() { + return Long.class; + } + + @Override + public Set> getSupportedJavaClasses() { + return classes; + } + + @Override + public Code getCode() { + return Code.ENUM; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getLongList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.int64(); + } }; public abstract int getSqlType(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index dabc9bfa0518..accb6323f5c0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -24,12 +24,18 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.ValueBinder; import com.google.common.io.CharStreams; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Message; import com.google.protobuf.NullValue; +import com.google.protobuf.ProtocolMessageEnum; import com.google.rpc.Code; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -279,6 +285,8 @@ private boolean isTypeSupported(int sqlType) { case Types.DECIMAL: case JsonType.VENDOR_TYPE_NUMBER: case PgJsonbType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.VENDOR_TYPE_NUMBER: return true; } return false; @@ -301,7 +309,7 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { case Types.DOUBLE: case Types.NUMERIC: case Types.DECIMAL: - return value instanceof Number; + return value instanceof Number || value instanceof ProtocolMessageEnum; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: @@ -328,7 +336,9 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: - return value instanceof byte[] || value instanceof InputStream; + return value instanceof byte[] + || value instanceof InputStream + || value instanceof AbstractMessage; case Types.ARRAY: return value instanceof Array; case Types.BLOB: @@ -348,6 +358,10 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { || value instanceof Reader || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.PG_JSONB); + case ProtoMessageType.VENDOR_TYPE_NUMBER: + return value instanceof AbstractMessage || value instanceof byte[]; + case ProtoEnumType.VENDOR_TYPE_NUMBER: + return value instanceof ProtocolMessageEnum || value instanceof Number; } return false; } @@ -450,6 +464,8 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, case Types.BIGINT: if (value instanceof Number) { return binder.to(((Number) value).longValue()); + } else if (value instanceof ProtocolMessageEnum) { + return binder.to((ProtocolMessageEnum) value); } throw JdbcSqlExceptionFactory.of(value + " is not a valid long", Code.INVALID_ARGUMENT); case Types.REAL: @@ -568,6 +584,8 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, Code.INVALID_ARGUMENT, e); } + } else if (value instanceof AbstractMessage) { + return binder.to((AbstractMessage) value); } throw JdbcSqlExceptionFactory.of( value + " is not a valid byte array", Code.INVALID_ARGUMENT); @@ -612,6 +630,23 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } } throw JdbcSqlExceptionFactory.of(value + " is not a valid clob", Code.INVALID_ARGUMENT); + case ProtoMessageType.VENDOR_TYPE_NUMBER: + if (value instanceof AbstractMessage) { + return binder.to((AbstractMessage) value); + } else if (value instanceof byte[]) { + return binder.to(ByteArray.copyFrom((byte[]) value)); + } else { + throw JdbcSqlExceptionFactory.of( + value + " is not a valid PROTO value", Code.INVALID_ARGUMENT); + } + case ProtoEnumType.VENDOR_TYPE_NUMBER: + if (value instanceof ProtocolMessageEnum) { + return binder.to((ProtocolMessageEnum) value); + } else if (value instanceof Number) { + return binder.to(((Number) value).longValue()); + } + throw JdbcSqlExceptionFactory.of( + value + " is not a valid ENUM value", Code.INVALID_ARGUMENT); } return null; } @@ -732,6 +767,10 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu throw new IllegalArgumentException( "Unsupported parameter type: " + value.getClass().getName() + " - " + value); } + } else if (AbstractMessage.class.isAssignableFrom(value.getClass())) { + return binder.to((AbstractMessage) value); + } else if (ProtocolMessageEnum.class.isAssignableFrom(value.getClass())) { + return binder.to((ProtocolMessageEnum) value); } return null; } @@ -785,6 +824,13 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.LONGVARBINARY: case Types.BLOB: return binder.toBytesArray(null); + case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.VENDOR_TYPE_NUMBER: + return binder.to( + Value.untyped( + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build())); default: return binder.to( Value.untyped( @@ -849,10 +895,69 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } } else if (byte[][].class.isAssignableFrom(value.getClass())) { return binder.toBytesArray(JdbcTypeConverter.toGoogleBytes((byte[][]) value)); + } else if (AbstractMessage[].class.isAssignableFrom(value.getClass())) { + return bindProtoMessageArray(binder, value); + } else if (ProtocolMessageEnum[].class.isAssignableFrom(value.getClass())) { + return bindProtoEnumArray(binder, value); } return null; } + private Builder bindProtoMessageArray(ValueBinder binder, Object value) + throws SQLException { + Class componentType = value.getClass().getComponentType(); + int length = java.lang.reflect.Array.getLength(value); + List convertedArray = new ArrayList<>(); + try { + Method method = componentType.getMethod("toByteArray"); + for (int i = 0; i < length; i++) { + Object element = java.lang.reflect.Array.get(value, i); + if (element != null) { + byte[] l = (byte[]) method.invoke(element); + convertedArray.add(ByteArray.copyFrom(l)); + } else { + convertedArray.add(null); + } + } + + Message.Builder builder = + (Message.Builder) componentType.getMethod("newBuilder").invoke(null); + Descriptor msgDescriptor = builder.getDescriptorForType(); + + return binder.toProtoMessageArray(convertedArray, msgDescriptor.getFullName()); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Error occurred when binding Array of Proto Message input", Code.UNKNOWN, e); + } + } + + private Builder bindProtoEnumArray(ValueBinder binder, Object value) + throws SQLException { + Class componentType = value.getClass().getComponentType(); + int length = java.lang.reflect.Array.getLength(value); + List convertedArray = new ArrayList<>(); + try { + Method method = componentType.getMethod("getNumber"); + for (int i = 0; i < length; i++) { + Object element = java.lang.reflect.Array.get(value, i); + if (element != null) { + int op = (int) method.invoke(element); + convertedArray.add((long) op); + } else { + convertedArray.add(null); + } + } + + Descriptors.EnumDescriptor enumDescriptor = + (Descriptors.EnumDescriptor) componentType.getMethod("getDescriptor").invoke(null); + + return binder.toProtoEnumArray(convertedArray, enumDescriptor.getFullName()); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Error occurred when binding Array of Proto Enum input", Code.UNKNOWN, e); + } + } + private List toLongList(Number[] input) { List res = new ArrayList<>(input.length); for (Number number : input) { @@ -891,6 +996,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { case Types.BIGINT: return binder.to((Long) null); case Types.BINARY: + case ProtoMessageType.VENDOR_TYPE_NUMBER: return binder.to((ByteArray) null); case Types.BLOB: return binder.to((ByteArray) null); @@ -914,6 +1020,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { case Types.DOUBLE: return binder.to((Double) null); case Types.INTEGER: + case ProtoEnumType.VENDOR_TYPE_NUMBER: return binder.to((Long) null); case Types.LONGNVARCHAR: return binder.to((String) null); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index dcb259857a70..054c1ed007ea 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -202,6 +202,7 @@ public String getString(int columnIndex) throws SQLException { case BOOL: return isNull ? null : String.valueOf(spanner.getBoolean(spannerIndex)); case BYTES: + case PROTO: return isNull ? null : spanner.getBytes(spannerIndex).toBase64(); case DATE: return isNull ? null : spanner.getDate(spannerIndex).toString(); @@ -210,6 +211,7 @@ public String getString(int columnIndex) throws SQLException { case FLOAT64: return isNull ? null : Double.toString(spanner.getDouble(spannerIndex)); case INT64: + case ENUM: return isNull ? null : Long.toString(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? null : spanner.getBigDecimal(spannerIndex).toString(); @@ -244,6 +246,7 @@ public boolean getBoolean(int columnIndex) throws SQLException { case FLOAT64: return !isNull && spanner.getDouble(spannerIndex) != 0D; case INT64: + case ENUM: return !isNull && spanner.getLong(spannerIndex) != 0L; case NUMERIC: return !isNull && !spanner.getBigDecimal(spannerIndex).equals(BigDecimal.ZERO); @@ -257,6 +260,7 @@ public boolean getBoolean(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("boolean", type); @@ -281,6 +285,7 @@ public byte getByte(int columnIndex) throws SQLException { ? (byte) 0 : checkedCastToByte(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: + case ENUM: return isNull ? (byte) 0 : checkedCastToByte(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? (byte) 0 : checkedCastToByte(spanner.getBigDecimal(spannerIndex)); @@ -296,6 +301,7 @@ public byte getByte(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("byte", type); @@ -320,6 +326,7 @@ public short getShort(int columnIndex) throws SQLException { ? 0 : checkedCastToShort(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: + case ENUM: return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : checkedCastToShort(spanner.getBigDecimal(spannerIndex)); @@ -335,6 +342,7 @@ public short getShort(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("short", type); @@ -359,6 +367,7 @@ public int getInt(int columnIndex) throws SQLException { ? 0 : checkedCastToInt(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: + case ENUM: return isNull ? 0 : checkedCastToInt(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : checkedCastToInt(spanner.getBigDecimal(spannerIndex)); @@ -374,6 +383,7 @@ public int getInt(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("int", type); @@ -394,6 +404,7 @@ public long getLong(int columnIndex) throws SQLException { case FLOAT64: return isNull ? 0L : Double.valueOf(spanner.getDouble(spannerIndex)).longValue(); case INT64: + case ENUM: return isNull ? 0L : spanner.getLong(spannerIndex); case NUMERIC: return isNull ? 0 : checkedCastToLong(parseBigDecimal(spanner.getString(spannerIndex))); @@ -409,6 +420,7 @@ public long getLong(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("long", type); @@ -429,6 +441,7 @@ public float getFloat(int columnIndex) throws SQLException { case FLOAT64: return isNull ? 0 : checkedCastToFloat(spanner.getDouble(spannerIndex)); case INT64: + case ENUM: return isNull ? 0 : checkedCastToFloat(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : spanner.getBigDecimal(spannerIndex).floatValue(); @@ -442,6 +455,7 @@ public float getFloat(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("float", type); @@ -462,6 +476,7 @@ public double getDouble(int columnIndex) throws SQLException { case FLOAT64: return isNull ? 0 : spanner.getDouble(spannerIndex); case INT64: + case ENUM: return isNull ? 0 : spanner.getLong(spannerIndex); case NUMERIC: return isNull ? 0 : spanner.getBigDecimal(spannerIndex).doubleValue(); @@ -475,6 +490,7 @@ public double getDouble(int columnIndex) throws SQLException { case DATE: case STRUCT: case TIMESTAMP: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("double", type); @@ -514,6 +530,8 @@ public Date getDate(int columnIndex) throws SQLException { case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("date", type); @@ -542,6 +560,8 @@ public Time getTime(int columnIndex) throws SQLException { case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("time", type); @@ -571,6 +591,8 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("timestamp", type); @@ -743,6 +765,8 @@ private Object getObject(Type type, int columnIndex) throws SQLException { return getString(columnIndex); } if (type == Type.timestamp()) return getTimestamp(columnIndex); + if (type.getCode() == Code.PROTO) return getBytes(columnIndex); + if (type.getCode() == Code.ENUM) return getLong(columnIndex); if (type.getCode() == Code.ARRAY) return getArray(columnIndex); throw JdbcSqlExceptionFactory.of("Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT); } @@ -816,6 +840,7 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) res = isNull ? null : BigDecimal.valueOf(spanner.getDouble(spannerIndex)); break; case INT64: + case ENUM: res = isNull ? null : BigDecimal.valueOf(spanner.getLong(spannerIndex)); break; case NUMERIC: @@ -840,6 +865,7 @@ private BigDecimal getBigDecimal(int columnIndex, boolean fixedScale, int scale) case DATE: case TIMESTAMP: case STRUCT: + case PROTO: case ARRAY: default: throw createInvalidToGetAs("BigDecimal", type); @@ -932,6 +958,8 @@ public Date getDate(int columnIndex, Calendar cal) throws SQLException { case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("date", type); @@ -964,6 +992,8 @@ public Time getTime(int columnIndex, Calendar cal) throws SQLException { case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("time", type); @@ -999,6 +1029,8 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException case JSON: case PG_JSONB: case STRUCT: + case PROTO: + case ENUM: case ARRAY: default: throw createInvalidToGetAs("timestamp", type); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 1733302c5b71..b98340332c88 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -23,6 +23,9 @@ import com.google.cloud.spanner.Type.Code; import com.google.cloud.spanner.Value; import com.google.common.base.Preconditions; +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.ProtocolMessageEnum; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; @@ -84,7 +87,8 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx return convertToSpannerValue(value, type); } if (targetType.equals(String.class)) { - if (type.getCode() == Code.BYTES) return new String((byte[]) value, UTF8); + if (type.getCode() == Code.BYTES || type.getCode() == Code.PROTO) + return new String((byte[]) value, UTF8); if (type.getCode() == Code.TIMESTAMP) { Timestamp timestamp = Timestamp.of((java.sql.Timestamp) value); return TIMESTAMP_FORMAT.format( @@ -95,14 +99,14 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx return value.toString(); } if (targetType.equals(byte[].class)) { - if (type.getCode() == Code.BYTES) return value; + if (type.getCode() == Code.BYTES || type.getCode() == Code.PROTO) return value; if (type.getCode() == Code.STRING || type.getCode() == Code.JSON || type.getCode() == Code.PG_JSONB) return ((String) value).getBytes(UTF8); } if (targetType.equals(Boolean.class)) { if (type.getCode() == Code.BOOL) return value; - if (type.getCode() == Code.INT64) return (Long) value != 0; + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return (Long) value != 0; if (type.getCode() == Code.FLOAT32) { return (Float) value != 0f; } @@ -111,38 +115,41 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx } if (targetType.equals(BigDecimal.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; - if (type.getCode() == Code.INT64) return BigDecimal.valueOf((Long) value); + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) + return BigDecimal.valueOf((Long) value); if (type.getCode() == Code.NUMERIC) return value; } if (targetType.equals(Long.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1L : 0L; - if (type.getCode() == Code.INT64) return value; + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return value; if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToLong((BigDecimal) value); } if (targetType.equals(Integer.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; - if (type.getCode() == Code.INT64) return AbstractJdbcWrapper.checkedCastToInt((Long) value); + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) + return AbstractJdbcWrapper.checkedCastToInt((Long) value); if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToInt((BigDecimal) value); } if (targetType.equals(Short.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; - if (type.getCode() == Code.INT64) + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return AbstractJdbcWrapper.checkedCastToShort((Long) value); if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToShort((BigDecimal) value); } if (targetType.equals(Byte.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; - if (type.getCode() == Code.INT64) + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return AbstractJdbcWrapper.checkedCastToByte((Long) value); if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToByte((BigDecimal) value); } if (targetType.equals(BigInteger.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; - if (type.getCode() == Code.INT64) return BigInteger.valueOf((Long) value); + if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) + return BigInteger.valueOf((Long) value); if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToBigInteger((BigDecimal) value); } @@ -183,9 +190,39 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx ZoneId.systemDefault()); } } + if (AbstractMessage.class.isAssignableFrom(targetType)) { + if (type.getCode() == Code.PROTO || type.getCode() == Code.BYTES) { + Method parseMethodParseFrom = targetType.getMethod("parseFrom", byte[].class); + return targetType.cast(parseMethodParseFrom.invoke(null, value)); + } + } + if (ProtocolMessageEnum.class.isAssignableFrom(targetType)) { + if (type.getCode() == Code.ENUM || type.getCode() == Code.INT64) { + Method parseMethodForNumber = targetType.getMethod("forNumber", int.class); + return targetType.cast( + parseMethodForNumber.invoke( + null, AbstractJdbcWrapper.checkedCastToInt((Long) value))); + } + } if (targetType.equals(java.sql.Array.class)) { if (type.getCode() == Code.ARRAY) return value; } + if (targetType.isArray() && type.getCode() == Code.ARRAY) { + if (type.getArrayElementType().getCode() == Code.PROTO + || type.getArrayElementType().getCode() == Code.BYTES) { + Object res = convertArrayOfProtoMessage(value, targetType); + if (res != null) { + return res; + } + } + if (type.getArrayElementType().getCode() == Code.ENUM + || type.getArrayElementType().getCode() == Code.INT64) { + Object res = convertArrayOfProtoEnum(value, targetType); + if (res != null) { + return res; + } + } + } } catch (SQLException e) { throw e; } catch (Exception e) { @@ -199,6 +236,52 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx com.google.rpc.Code.INVALID_ARGUMENT); } + /** + * Converts the given value to the Java {@link Class} type. The targetType {@link Class} must be + * an array of {@link AbstractMessage}. + */ + static Object convertArrayOfProtoMessage(Object value, Class targetType) throws Exception { + Class componentType = targetType.getComponentType(); + if (AbstractMessage.class.isAssignableFrom(componentType)) { + byte[][] result = (byte[][]) ((JdbcArray) value).getArray(); + Object obj = java.lang.reflect.Array.newInstance(componentType, result.length); + Method parseMethodParseFrom = componentType.getMethod("parseFrom", byte[].class); + for (int i = 0; i < result.length; i++) { + if (result[i] != null) { + java.lang.reflect.Array.set( + obj, i, componentType.cast(parseMethodParseFrom.invoke(null, result[i]))); + } + } + return obj; + } + return null; + } + + /** + * Converts the given value to the Java {@link Class} type. The targetType {@link Class} must be + * an array of {@link ProtocolMessageEnum}. + */ + static Object convertArrayOfProtoEnum(Object value, Class targetType) throws Exception { + Class componentType = targetType.getComponentType(); + if (ProtocolMessageEnum.class.isAssignableFrom(componentType)) { + Long[] result = (Long[]) ((JdbcArray) value).getArray(); + Object obj = java.lang.reflect.Array.newInstance(componentType, result.length); + Method parseMethodForNumber = componentType.getMethod("forNumber", int.class); + for (int i = 0; i < result.length; i++) { + if (result[i] != null) { + java.lang.reflect.Array.set( + obj, + i, + componentType.cast( + parseMethodForNumber.invoke( + null, AbstractJdbcWrapper.checkedCastToInt(result[i])))); + } + } + return obj; + } + return null; + } + private static Value convertToSpannerValue(Object value, Type type) throws SQLException { switch (type.getCode()) { case ARRAY: @@ -207,6 +290,10 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.boolArray(Arrays.asList((Boolean[]) ((java.sql.Array) value).getArray())); case BYTES: return Value.bytesArray(toGoogleBytes((byte[][]) ((java.sql.Array) value).getArray())); + case PROTO: + return Value.protoMessageArray( + toGoogleBytes((byte[][]) ((java.sql.Array) value).getArray()), + type.getArrayElementType().getProtoTypeFqn()); case DATE: return Value.dateArray( toGoogleDates((java.sql.Date[]) ((java.sql.Array) value).getArray())); @@ -217,6 +304,10 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx Arrays.asList((Double[]) ((java.sql.Array) value).getArray())); case INT64: return Value.int64Array(Arrays.asList((Long[]) ((java.sql.Array) value).getArray())); + case ENUM: + return Value.protoEnumArray( + Arrays.asList((Long[]) ((java.sql.Array) value).getArray()), + type.getArrayElementType().getProtoTypeFqn()); case PG_OID: return Value.pgOidArray(Arrays.asList((Long[]) ((java.sql.Array) value).getArray())); case NUMERIC: @@ -266,6 +357,10 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx return Value.json((String) value); case PG_JSONB: return Value.pgJsonb((String) value); + case PROTO: + return Value.protoMessage(ByteArray.copyFrom((byte[]) value), type.getProtoTypeFqn()); + case ENUM: + return Value.protoEnum((Long) value, type.getProtoTypeFqn()); case STRUCT: default: throw JdbcSqlExceptionFactory.of( @@ -306,6 +401,12 @@ private static void checkValidTypeAndValueForConvert(Type type, Object value) JdbcPreconditions.checkArgument( type.getCode() != Code.NUMERIC || value.getClass().equals(BigDecimal.class), "input type is numeric, but input value is not an instance of BigDecimal"); + JdbcPreconditions.checkArgument( + type.getCode() != Code.PROTO || value.getClass().equals(byte[].class), + "input type is proto, but input value is not an instance of byte[]"); + JdbcPreconditions.checkArgument( + type.getCode() != Code.ENUM || value.getClass().equals(Long.class), + "input type is enum, but input value is not an instance of Long"); } @SuppressWarnings("deprecation") diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java new file mode 100644 index 000000000000..478d082e9664 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java @@ -0,0 +1,55 @@ +/* + * 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.spanner.v1.TypeCode; +import java.sql.PreparedStatement; +import java.sql.SQLType; + +/** + * Custom SQL type for Spanner PROTO data type. This type (or the vendor type number) must be used + * when setting a PROTO parameter using {@link PreparedStatement#setObject(int, Object, SQLType)}. + */ +public class ProtoEnumType implements SQLType { + public static final ProtoEnumType INSTANCE = new ProtoEnumType(); + /** + * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid + * conflicts with the type numbers in java.sql.Types. + */ + public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.ENUM_VALUE; + + private ProtoEnumType() {} + + @Override + public String getName() { + return "ENUM"; + } + + @Override + public String getVendor() { + return ProtoEnumType.class.getPackage().getName(); + } + + @Override + public Integer getVendorTypeNumber() { + return VENDOR_TYPE_NUMBER; + } + + public String toString() { + return getName(); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java new file mode 100644 index 000000000000..5a813d66d7f0 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java @@ -0,0 +1,55 @@ +/* + * 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.spanner.v1.TypeCode; +import java.sql.PreparedStatement; +import java.sql.SQLType; + +/** + * Custom SQL type for Spanner PROTO data type. This type (or the vendor type number) must be used + * when setting a PROTO parameter using {@link PreparedStatement#setObject(int, Object, SQLType)}. + */ +public class ProtoMessageType implements SQLType { + public static final ProtoMessageType INSTANCE = new ProtoMessageType(); + /** + * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid + * conflicts with the type numbers in java.sql.Types. + */ + public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.PROTO_VALUE; + + private ProtoMessageType() {} + + @Override + public String getName() { + return "PROTO"; + } + + @Override + public String getVendor() { + return ProtoMessageType.class.getPackage().getName(); + } + + @Override + public Integer getVendorTypeNumber() { + return VENDOR_TYPE_NUMBER; + } + + public String toString() { + return getName(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index e39e28a74136..bfae4e556e0f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -18,6 +18,7 @@ import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlDate; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -27,7 +28,10 @@ import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type.Code; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; +import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; import java.math.BigDecimal; import java.sql.Date; import java.sql.ResultSet; @@ -36,6 +40,7 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.Timestamp; import java.sql.Types; +import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -221,6 +226,75 @@ public void testCreateArrayTypeName() throws SQLException { assertThat(rs.getTimestamp(2)).isEqualTo(new Timestamp(1000L)); assertThat(rs.next()).isFalse(); } + + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + array = + JdbcArray.createArray( + "PROTO", new SingerInfo[] {singerInfo, SingerInfo.getDefaultInstance(), null}); + assertEquals(ProtoMessageType.VENDOR_TYPE_NUMBER, array.getBaseType()); + assertEquals(singerInfo, ((SingerInfo[]) array.getArray(1, 1))[0]); + try (ResultSet rs = array.getResultSet()) { + assertTrue(rs.next()); + assertEquals(singerInfo, rs.getObject(2, SingerInfo.class)); + assertArrayEquals(singerInfo.toByteArray(), rs.getBytes(2)); + assertTrue(rs.next()); + assertEquals(SingerInfo.getDefaultInstance(), rs.getObject(2, SingerInfo.class)); + assertArrayEquals(SingerInfo.getDefaultInstance().toByteArray(), rs.getBytes(2)); + assertTrue(rs.next()); + assertNull(rs.getObject(2, SingerInfo.class)); + assertNull(rs.getBytes(2)); + assertFalse(rs.next()); + } + + array = JdbcArray.createArray("ENUM", new Genre[] {Genre.ROCK, Genre.FOLK, null}); + assertEquals(ProtoEnumType.VENDOR_TYPE_NUMBER, array.getBaseType()); + assertEquals(Genre.ROCK, ((Genre[]) array.getArray(1, 1))[0]); + try (ResultSet rs = array.getResultSet()) { + assertTrue(rs.next()); + assertEquals(Genre.ROCK, rs.getObject(2, Genre.class)); + assertEquals(Genre.ROCK.getNumber(), rs.getInt(2)); + assertTrue(rs.next()); + assertEquals(Genre.FOLK, rs.getObject(2, Genre.class)); + assertEquals(Genre.FOLK.getNumber(), rs.getInt(2)); + assertTrue(rs.next()); + assertNull(rs.getObject(2, Genre.class)); + assertEquals(0, rs.getInt(2)); + assertFalse(rs.next()); + } + + array = + JdbcArray.createArray( + JdbcDataType.getType(Code.PROTO), + Arrays.asList( + singerInfo.toByteArray(), SingerInfo.getDefaultInstance().toByteArray(), null)); + assertEquals(ProtoMessageType.VENDOR_TYPE_NUMBER, array.getBaseType()); + assertArrayEquals(singerInfo.toByteArray(), ((byte[][]) array.getArray(1, 1))[0]); + try (ResultSet rs = array.getResultSet()) { + assertTrue(rs.next()); + assertArrayEquals(singerInfo.toByteArray(), rs.getBytes(2)); + assertTrue(rs.next()); + assertArrayEquals(SingerInfo.getDefaultInstance().toByteArray(), rs.getBytes(2)); + assertTrue(rs.next()); + assertNull(rs.getBytes(2)); + assertFalse(rs.next()); + } + + array = + JdbcArray.createArray( + JdbcDataType.getType(Code.ENUM), + Arrays.asList((long) Genre.ROCK.getNumber(), (long) Genre.FOLK.getNumber(), null)); + assertEquals(ProtoEnumType.VENDOR_TYPE_NUMBER, array.getBaseType()); + assertEquals(Genre.ROCK.getNumber(), (long) ((Long[]) array.getArray(1, 1))[0]); + try (ResultSet rs = array.getResultSet()) { + assertTrue(rs.next()); + assertEquals(Genre.ROCK.getNumber(), rs.getInt(2)); + assertTrue(rs.next()); + assertEquals(Genre.FOLK.getNumber(), rs.getInt(2)); + assertTrue(rs.next()); + assertEquals(0, rs.getInt(2)); + assertFalse(rs.next()); + } } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index ba674b2552e5..eb8237c0b608 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -30,7 +30,10 @@ import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; +import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; import com.google.common.io.CharStreams; +import com.google.protobuf.NullValue; import com.google.rpc.Code; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -241,8 +244,51 @@ public void testSetParameterWithType() throws SQLException, IOException { verifyParameter(params, Value.numeric(BigDecimal.ONE)); } + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + params.setParameter(1, singerInfo, ProtoMessageType.VENDOR_TYPE_NUMBER); + assertEquals(singerInfo, params.getParameter(1)); + verifyParameter(params, Value.protoMessage(singerInfo)); + + params.setParameter(1, singerInfo, ProtoMessageType.INSTANCE); + assertEquals(singerInfo, params.getParameter(1)); + verifyParameter(params, Value.protoMessage(singerInfo)); + + // Tests inter compatibility between bytes and proto message + params.setParameter(1, singerInfo.toByteArray(), ProtoMessageType.VENDOR_TYPE_NUMBER); + assertArrayEquals(singerInfo.toByteArray(), (byte[]) params.getParameter(1)); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(singerInfo.toByteArray()))); + + params.setParameter(1, singerInfo, Types.BINARY); + assertEquals(singerInfo, params.getParameter(1)); + verifyParameter(params, Value.protoMessage(singerInfo)); + + params.setParameter(1, Genre.ROCK, ProtoEnumType.VENDOR_TYPE_NUMBER); + assertEquals(Genre.ROCK, params.getParameter(1)); + verifyParameter(params, Value.protoEnum(Genre.ROCK)); + + params.setParameter(1, Genre.ROCK, ProtoEnumType.INSTANCE); + assertEquals(Genre.ROCK, params.getParameter(1)); + verifyParameter(params, Value.protoEnum(Genre.ROCK)); + + // Tests inter compatibility between int and proto enum + params.setParameter(1, Genre.ROCK.getNumber(), ProtoEnumType.VENDOR_TYPE_NUMBER); + assertEquals(Genre.ROCK.getNumber(), params.getParameter(1)); + verifyParameter(params, Value.int64(Genre.ROCK.getNumber())); + + params.setParameter(1, Genre.ROCK, Types.INTEGER); + assertEquals(Genre.ROCK, params.getParameter(1)); + verifyParameter(params, Value.protoEnum(Genre.ROCK)); + // types that should lead to int64 - for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { + for (int type : + new int[] { + Types.TINYINT, + Types.SMALLINT, + Types.INTEGER, + Types.BIGINT, + ProtoEnumType.VENDOR_TYPE_NUMBER + }) { params.setParameter(1, (byte) 1, type); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); verifyParameter(params, Value.int64(1)); @@ -349,7 +395,10 @@ public void testSetParameterWithType() throws SQLException, IOException { } // types that should lead to bytes (except BLOB which is handled separately) - for (int type : new int[] {Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY}) { + for (int type : + new int[] { + Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY, ProtoMessageType.VENDOR_TYPE_NUMBER + }) { params.setParameter(1, new byte[] {1, 2, 3}, type); assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(new byte[] {1, 2, 3}))); @@ -457,7 +506,14 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { JdbcParameterStore params = new JdbcParameterStore(dialect); // types that should lead to int64, but with invalid values. - for (int type : new int[] {Types.TINYINT, Types.SMALLINT, Types.INTEGER, Types.BIGINT}) { + for (int type : + new int[] { + Types.TINYINT, + Types.SMALLINT, + Types.INTEGER, + Types.BIGINT, + ProtoEnumType.VENDOR_TYPE_NUMBER + }) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); @@ -499,7 +555,10 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { } // types that should lead to bytes (except BLOB which is handled separately) - for (int type : new int[] {Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY}) { + for (int type : + new int[] { + Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY, ProtoMessageType.VENDOR_TYPE_NUMBER + }) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); @@ -641,6 +700,16 @@ public void testSetParameterWithoutType() throws SQLException { params.setParameter(1, Value.pgJsonb(jsonString), (Integer) null); assertEquals(Value.pgJsonb(jsonString), params.getParameter(1)); verifyParameter(params, Value.pgJsonb(jsonString)); + + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + params.setParameter(1, singerInfo, (Integer) null); + assertEquals(singerInfo, params.getParameter(1)); + verifyParameter(params, Value.protoMessage(singerInfo)); + + params.setParameter(1, Genre.ROCK, (Integer) null); + assertEquals(Genre.ROCK, params.getParameter(1)); + verifyParameter(params, Value.protoEnum(Genre.ROCK)); } private boolean stringReadersEqual(StringReader r1, StringReader r2) throws IOException { @@ -837,6 +906,68 @@ public void testSetArrayParameter() throws SQLException { assertEquals( Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null)), params.getParameter(1)); verifyParameter(params, Value.pgJsonbArray(Arrays.asList(jsonString1, jsonString2, null))); + + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + params.setParameter( + 1, + JdbcArray.createArray( + "PROTO", new SingerInfo[] {singerInfo, SingerInfo.getDefaultInstance()}), + Types.ARRAY); + assertEquals( + JdbcArray.createArray( + "PROTO", new SingerInfo[] {singerInfo, SingerInfo.getDefaultInstance()}), + params.getParameter(1)); + verifyParameter( + params, + Value.protoMessageArray( + Arrays.asList(singerInfo, SingerInfo.getDefaultInstance()), + SingerInfo.getDescriptor())); + + params.setParameter( + 1, + JdbcArray.createArray( + "PROTO", new SingerInfo[] {singerInfo, SingerInfo.getDefaultInstance(), null}), + Types.ARRAY); + assertEquals( + JdbcArray.createArray( + "PROTO", new SingerInfo[] {singerInfo, SingerInfo.getDefaultInstance(), null}), + params.getParameter(1)); + verifyParameter( + params, + Value.protoMessageArray( + Arrays.asList(singerInfo, SingerInfo.getDefaultInstance(), null), + SingerInfo.getDescriptor())); + + params.setParameter(1, JdbcArray.createArray("PROTO", null), Types.ARRAY); + assertEquals(JdbcArray.createArray("PROTO", null), params.getParameter(1)); + verifyParameter( + params, + Value.untyped( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build())); + + params.setParameter( + 1, JdbcArray.createArray("ENUM", new Genre[] {Genre.ROCK, Genre.POP}), Types.ARRAY); + assertEquals( + JdbcArray.createArray("ENUM", new Genre[] {Genre.ROCK, Genre.POP}), params.getParameter(1)); + verifyParameter( + params, Value.protoEnumArray(Arrays.asList(Genre.ROCK, Genre.POP), Genre.getDescriptor())); + + params.setParameter( + 1, JdbcArray.createArray("ENUM", new Genre[] {Genre.ROCK, Genre.POP, null}), Types.ARRAY); + assertEquals( + JdbcArray.createArray("ENUM", new Genre[] {Genre.ROCK, Genre.POP, null}), + params.getParameter(1)); + verifyParameter( + params, + Value.protoEnumArray(Arrays.asList(Genre.ROCK, Genre.POP, null), Genre.getDescriptor())); + + params.setParameter(1, JdbcArray.createArray("ENUM", null), Types.ARRAY); + assertEquals(JdbcArray.createArray("ENUM", null), params.getParameter(1)); + verifyParameter( + params, + Value.untyped( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build())); } private void verifyParameter(JdbcParameterStore params, Value value) throws SQLException { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 476c40492d80..08bc7e060f17 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -37,6 +37,8 @@ import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; +import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; import com.google.common.collect.ImmutableList; import com.google.rpc.Code; import java.io.IOException; @@ -145,6 +147,18 @@ public class JdbcResultSetTest { private static final int JSON_COLINDEX_NOT_NULL = 28; private static final String JSON_VALUE = "{\"name\":\"John\", \"age\":30, \"car\":null}"; + private static final String PROTO_MSG_COL_NULL = "PROTO_MSG_COL_NULL"; + private static final String PROTO_MSG_COL_NOT_NULL = "PROTO_MSG_COL_NOT_NULL"; + private static final int PROTO_MSG_COLINDEX_NULL = 29; + private static final int PROTO_MSG_COLINDEX_NOT_NULL = 30; + private static final ByteArray PROTO_MSG_VALUE = + ByteArray.copyFrom(SingerInfo.newBuilder().setSingerId(1).build().toByteArray()); + private static final String PROTO_ENUM_COL_NULL = "PROTO_ENUM_COL_NULL"; + private static final String PROTO_ENUM_COL_NOT_NULL = "PROTO_ENUM_COL_NOT_NULL"; + private static final int PROTO_ENUM_COLINDEX_NULL = 31; + private static final int PROTO_ENUM_COLINDEX_NOT_NULL = 32; + private static final long PROTO_ENUM_VALUE = Genre.ROCK.getNumber(); + private static final String BOOL_ARRAY_COL = "BOOL_ARRAY"; private static final List BOOL_ARRAY_VALUE = Arrays.asList(true, null, false); private static final String BYTES_ARRAY_COL = "BYTES_ARRAY"; @@ -163,6 +177,10 @@ public class JdbcResultSetTest { private static final List TIMESTAMP_ARRAY_VALUE = Arrays.asList(TIMESTAMP_VALUE, null); private static final String JSON_ARRAY_COL = "JSON_ARRAY"; private static final List JSON_ARRAY_VALUE = Arrays.asList(JSON_VALUE, null); + private static final String PROTO_MSG_ARRAY_COL = "PROTO_MSG_ARRAY"; + private static final List PROTO_MSG_ARRAY_VALUE = Arrays.asList(PROTO_MSG_VALUE, null); + private static final String PROTO_ENUM_ARRAY_COL = "PROTO_ENUM_ARRAY"; + private static final List PROTO_ENUM_ARRAY_VALUE = Arrays.asList(PROTO_ENUM_VALUE, null); private final JdbcResultSet subject; @@ -197,6 +215,14 @@ static ResultSet getMockResultSet() { StructField.of(NUMERIC_COL_NOT_NULL, Type.numeric()), StructField.of(JSON_COL_NULL, Type.json()), StructField.of(JSON_COL_NOT_NULL, Type.json()), + StructField.of( + PROTO_MSG_COL_NULL, Type.proto(SingerInfo.getDescriptor().getFullName())), + StructField.of( + PROTO_MSG_COL_NOT_NULL, Type.proto(SingerInfo.getDescriptor().getFullName())), + StructField.of( + PROTO_ENUM_COL_NULL, Type.protoEnum(Genre.getDescriptor().getFullName())), + StructField.of( + PROTO_ENUM_COL_NOT_NULL, Type.protoEnum(Genre.getDescriptor().getFullName())), StructField.of(BOOL_ARRAY_COL, Type.array(Type.bool())), StructField.of(BYTES_ARRAY_COL, Type.array(Type.bytes())), StructField.of(DATE_ARRAY_COL, Type.array(Type.date())), @@ -205,7 +231,13 @@ static ResultSet getMockResultSet() { StructField.of(NUMERIC_ARRAY_COL, Type.array(Type.numeric())), StructField.of(JSON_ARRAY_COL, Type.array(Type.json())), StructField.of(STRING_ARRAY_COL, Type.array(Type.string())), - StructField.of(TIMESTAMP_ARRAY_COL, Type.array(Type.timestamp()))), + StructField.of(TIMESTAMP_ARRAY_COL, Type.array(Type.timestamp())), + StructField.of( + PROTO_MSG_ARRAY_COL, + Type.array(Type.proto(SingerInfo.getDescriptor().getFullName()))), + StructField.of( + PROTO_ENUM_ARRAY_COL, + Type.array(Type.protoEnum(Genre.getDescriptor().getFullName())))), Collections.singletonList( Struct.newBuilder() .set(STRING_COL_NULL) @@ -264,6 +296,14 @@ static ResultSet getMockResultSet() { .to(Value.json(null)) .set(JSON_COL_NOT_NULL) .to(Value.json(JSON_VALUE)) + .set(PROTO_MSG_COL_NULL) + .to((ByteArray) null, SingerInfo.getDescriptor().getFullName()) + .set(PROTO_MSG_COL_NOT_NULL) + .to(PROTO_MSG_VALUE, SingerInfo.getDescriptor().getFullName()) + .set(PROTO_ENUM_COL_NULL) + .to((Long) null, Genre.getDescriptor().getFullName()) + .set(PROTO_ENUM_COL_NOT_NULL) + .to(PROTO_ENUM_VALUE, Genre.getDescriptor().getFullName()) .set(BOOL_ARRAY_COL) .toBoolArray(BOOL_ARRAY_VALUE) .set(BYTES_ARRAY_COL) @@ -282,6 +322,11 @@ static ResultSet getMockResultSet() { .toStringArray(STRING_ARRAY_VALUE) .set(TIMESTAMP_ARRAY_COL) .toTimestampArray(TIMESTAMP_ARRAY_VALUE) + .set(PROTO_MSG_ARRAY_COL) + .toProtoMessageArray( + PROTO_MSG_ARRAY_VALUE, SingerInfo.getDescriptor().getFullName()) + .set(PROTO_ENUM_ARRAY_COL) + .toProtoEnumArray(PROTO_ENUM_ARRAY_VALUE, Genre.getDescriptor().getFullName()) .build())); } @@ -653,6 +698,77 @@ public void testGetBytesIndex() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetBytesIndexFromProtoMessage() throws SQLException { + assertNotNull(subject.getBytes(PROTO_MSG_COLINDEX_NOT_NULL)); + assertArrayEquals(PROTO_MSG_VALUE.toByteArray(), subject.getBytes(PROTO_MSG_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getBytes(PROTO_MSG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetProtoMessage() throws SQLException { + SingerInfo singerInfo = subject.getObject(PROTO_MSG_COLINDEX_NOT_NULL, SingerInfo.class); + assertEquals(SingerInfo.newBuilder().setSingerId(1).build(), singerInfo); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(PROTO_MSG_COLINDEX_NULL, SingerInfo.class)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetBytesAsObjectIndexFromProtoMessage() throws SQLException { + assertNotNull(subject.getObject(PROTO_MSG_COLINDEX_NOT_NULL)); + assertArrayEquals( + PROTO_MSG_VALUE.toByteArray(), (byte[]) subject.getObject(PROTO_MSG_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(PROTO_MSG_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetProtoMessageArrayAsObject() throws SQLException { + assertNotNull(subject.getObject(PROTO_MSG_ARRAY_COL, SingerInfo[].class)); + assertArrayEquals( + new SingerInfo[] {SingerInfo.newBuilder().setSingerId(1).build(), null}, + subject.getObject(PROTO_MSG_ARRAY_COL, SingerInfo[].class)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntIndexFromProtoEnum() throws SQLException { + assertEquals(PROTO_ENUM_VALUE, subject.getInt(PROTO_ENUM_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertEquals(0, subject.getInt(PROTO_ENUM_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetEnum() throws SQLException { + Genre singerGenre = subject.getObject(PROTO_ENUM_COLINDEX_NOT_NULL, Genre.class); + assertEquals(Genre.ROCK, singerGenre); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(PROTO_ENUM_COLINDEX_NULL, Genre.class)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetIntAsObjectIndexFromProtoEnum() throws SQLException { + assertNotNull(subject.getObject(PROTO_ENUM_COLINDEX_NOT_NULL)); + assertEquals(PROTO_ENUM_VALUE, subject.getObject(PROTO_ENUM_COLINDEX_NOT_NULL)); + assertFalse(subject.wasNull()); + assertNull(subject.getObject(PROTO_ENUM_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + } + + @Test + public void testGetProtoEnumArrayAsObject() throws SQLException { + assertNotNull(subject.getObject(PROTO_ENUM_ARRAY_COL, Genre[].class)); + assertArrayEquals( + new Genre[] {Genre.ROCK, null}, subject.getObject(PROTO_ENUM_ARRAY_COL, Genre[].class)); + assertFalse(subject.wasNull()); + } + @SuppressWarnings("deprecation") @Test public void testGetDateIndex() throws SQLException { @@ -1719,6 +1835,12 @@ public void testGetObjectAsValue() throws SQLException { assertEquals( Value.timestamp(TIMESTAMP_VALUE), subject.getObject(TIMESTAMP_COLINDEX_NOTNULL, Value.class)); + assertEquals( + Value.protoMessage(PROTO_MSG_VALUE, SingerInfo.getDescriptor()), + subject.getObject(PROTO_MSG_COLINDEX_NOT_NULL, Value.class)); + assertEquals( + Value.protoEnum(PROTO_ENUM_VALUE, Genre.getDescriptor()), + subject.getObject(PROTO_ENUM_COLINDEX_NOT_NULL, Value.class)); assertEquals(Value.boolArray(BOOL_ARRAY_VALUE), subject.getObject(BOOL_ARRAY_COL, Value.class)); assertEquals( @@ -1735,6 +1857,12 @@ public void testGetObjectAsValue() throws SQLException { assertEquals( Value.timestampArray(TIMESTAMP_ARRAY_VALUE), subject.getObject(TIMESTAMP_ARRAY_COL, Value.class)); + assertEquals( + Value.protoMessageArray(PROTO_MSG_ARRAY_VALUE, SingerInfo.getDescriptor().getFullName()), + subject.getObject(PROTO_MSG_ARRAY_COL, Value.class)); + assertEquals( + Value.protoEnumArray(PROTO_ENUM_ARRAY_VALUE, Genre.getDescriptor().getFullName()), + subject.getObject(PROTO_ENUM_ARRAY_COL, Value.class)); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index f1ed83303e98..26eaffe2d9a4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -30,12 +30,16 @@ import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlTimestamp; import static com.google.cloud.spanner.jdbc.JdbcTypeConverter.toSqlTimestamps; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import com.google.cloud.ByteArray; import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.ReadOnlyStalenessUtil; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; +import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; import com.google.rpc.Code; import java.math.BigDecimal; import java.math.BigInteger; @@ -73,7 +77,7 @@ public void testConvertArray() throws SQLException { Type.string(), Type.json(), Type.timestamp(), - Type.numeric() + Type.numeric(), }) { assertConvertThrows(testValue, Type.array(t), Boolean.class, Code.INVALID_ARGUMENT); assertConvertThrows(testValue, Type.array(t), Byte.class, Code.INVALID_ARGUMENT); @@ -126,6 +130,123 @@ public void testConvertBytes() throws SQLException { assertThat(convert(testValues, Type.bytes(), String.class)).isEqualTo("test"); } + @Test + public void testConvertProtoMessage() throws SQLException { + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + byte[] testValues = singerInfo.toByteArray(); + String protoTypeFqn = SingerInfo.getDescriptor().getFullName(); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Boolean.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Byte.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Short.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Float.class, Code.INVALID_ARGUMENT); + assertConvertThrows(testValues, Type.proto(protoTypeFqn), Double.class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.proto(protoTypeFqn), BigInteger.class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.proto(protoTypeFqn), BigDecimal.class, Code.INVALID_ARGUMENT); + + assertEquals(testValues, convert(testValues, Type.proto(protoTypeFqn), byte[].class)); + assertEquals(singerInfo, convert(testValues, Type.proto(protoTypeFqn), SingerInfo.class)); + } + + @Test + public void testConvertProtoMessageArray() throws SQLException { + SingerInfo singerInfo = + SingerInfo.newBuilder().setSingerId(1).setNationality("Country1").build(); + Array testValues = + JdbcArray.createArray("PROTO", new byte[][] {singerInfo.toByteArray(), null}); + String protoTypeFqn = SingerInfo.getDescriptor().getFullName(); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Boolean[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Byte[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Short[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Integer[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Long[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Float[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.proto(protoTypeFqn)), Double[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.proto(protoTypeFqn)), + BigInteger[].class, + Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.proto(protoTypeFqn)), + BigDecimal[].class, + Code.INVALID_ARGUMENT); + + assertEquals( + testValues, convert(testValues, Type.array(Type.proto(protoTypeFqn)), Array.class)); + assertArrayEquals( + new SingerInfo[] {singerInfo, null}, + (Object[]) convert(testValues, Type.array(Type.proto(protoTypeFqn)), SingerInfo[].class)); + } + + @Test + public void testConvertProtoEnumArray() throws SQLException { + Array testValues = + JdbcArray.createArray("ENUM", new Long[] {(long) Genre.ROCK.getNumber(), null}); + String protoTypeFqn = Genre.getDescriptor().getFullName(); + assertConvertThrows( + testValues, + Type.array(Type.protoEnum(protoTypeFqn)), + Boolean[].class, + Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.protoEnum(protoTypeFqn)), Byte[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.protoEnum(protoTypeFqn)), Short[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.protoEnum(protoTypeFqn)), + Integer[].class, + Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.protoEnum(protoTypeFqn)), Long[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, Type.array(Type.protoEnum(protoTypeFqn)), Float[].class, Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.protoEnum(protoTypeFqn)), + Double[].class, + Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.protoEnum(protoTypeFqn)), + BigInteger[].class, + Code.INVALID_ARGUMENT); + assertConvertThrows( + testValues, + Type.array(Type.protoEnum(protoTypeFqn)), + BigDecimal[].class, + Code.INVALID_ARGUMENT); + + assertEquals( + testValues, convert(testValues, Type.array(Type.protoEnum(protoTypeFqn)), Array.class)); + assertArrayEquals( + new Genre[] {Genre.ROCK, null}, + (Object[]) convert(testValues, Type.array(Type.protoEnum(protoTypeFqn)), Genre[].class)); + } + + @Test + public void testConvertProtoEnum() throws SQLException { + long testValue = Genre.ROCK.getNumber(); + String protoTypeFqn = Genre.getDescriptor().getFullName(); + + assertEquals((int) testValue, convert(testValue, Type.protoEnum(protoTypeFqn), Integer.class)); + assertEquals(testValue, convert(testValue, Type.protoEnum(protoTypeFqn), Long.class)); + assertEquals(Genre.ROCK, convert(testValue, Type.protoEnum(protoTypeFqn), Genre.class)); + } + @Test public void testConvertJson() throws SQLException { String testValue = "{\"test\": foo}"; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java new file mode 100644 index 000000000000..a5ecf5bba534 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java @@ -0,0 +1,273 @@ +/* + * 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.it; + +import static org.junit.Assert.assertArrayEquals; +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.assertTrue; +import static org.junit.Assume.assumeFalse; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.jdbc.ProtoEnumType; +import com.google.cloud.spanner.jdbc.ProtoMessageType; +import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; +import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import com.google.cloud.spanner.testing.RemoteSpannerHelper; +import java.io.InputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.time.Duration; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITProtoColumnsTest { + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(10); + private static Database database; + private static String url; + + public static boolean isUsingGraalVm() { + String jobType = System.getenv("JOB_TYPE"); + return jobType != null && jobType.contains("graalvm"); + } + + @BeforeClass + public static void setup() throws Exception { + assumeFalse( + "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); + RemoteSpannerHelper testHelper = env.getTestHelper(); + final String projectId = testHelper.getInstanceId().getProject(); + final String instanceId = testHelper.getInstanceId().getInstance(); + final String databaseId = testHelper.getUniqueDatabaseId(); + final DatabaseAdminClient databaseAdminClient = testHelper.getClient().getDatabaseAdminClient(); + InputStream in = + ITProtoColumnsTest.class + .getClassLoader() + .getResourceAsStream("com/google/cloud/spanner/jdbc/it/descriptors.pb"); + assertNotNull(in); + final Database databaseToCreate = + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) + .setProtoDescriptors(in) + .build(); + final String host = SpannerTestHost.getHost(); + + database = + databaseAdminClient + .createDatabase( + databaseToCreate, + Arrays.asList( + "CREATE PROTO BUNDLE (" + + "examples.spanner.music.SingerInfo," + + "examples.spanner.music.Genre," + + ")", + "CREATE TABLE Types (" + + " RowID INT64 NOT NULL," + + " ProtoMessage examples.spanner.music.SingerInfo," + + " ProtoEnum examples.spanner.music.Genre," + + " ProtoMessageArray ARRAY," + + " ProtoEnumArray ARRAY," + + " ) PRIMARY KEY (RowID)")) + .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + + in.close(); + url = "jdbc:cloudspanner://" + host + "/" + database.getId(); + } + + @AfterClass + public static void teardown() { + if (database != null) { + database.drop(); + } + ConnectionOptions.closeSpanner(); + } + + @Test + public void testNonNullElements() throws Exception { + assumeFalse( + "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); + SingerInfo singerInfo = + SingerInfo.newBuilder() + .setSingerId(1) + .setNationality("Country1") + .setGenre(Genre.ROCK) + .build(); + Genre singerGenre = Genre.ROCK; + SingerInfo[] singerInfoArray = new SingerInfo[] {singerInfo, null}; + Genre[] singerGenreArray = new Genre[] {Genre.ROCK, null}; + try (Connection connection = DriverManager.getConnection(url); + PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Types" + + " (RowID, ProtoMessage, ProtoEnum, ProtoMessageArray, ProtoEnumArray) VALUES (?, ?, ?, ?, ?)")) { + ps.setInt(1, 1); + ps.setObject(2, singerInfo, ProtoMessageType.INSTANCE); + ps.setObject(3, singerGenre, ProtoEnumType.INSTANCE); + ps.setArray(4, connection.createArrayOf("PROTO", singerInfoArray)); + ps.setArray(5, connection.createArrayOf("ENUM", singerGenreArray)); + + final int updateCount = ps.executeUpdate(); + assertEquals(1, updateCount); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM Types WHERE RowID = 1")) { + + assertTrue(resultSet.next()); + assertEquals(1, resultSet.getInt("RowID")); + assertEquals(singerInfo, resultSet.getObject("ProtoMessage", SingerInfo.class)); + assertEquals(singerGenre, resultSet.getObject("ProtoEnum", Genre.class)); + assertArrayEquals( + singerInfoArray, resultSet.getObject("ProtoMessageArray", SingerInfo[].class)); + assertArrayEquals(singerGenreArray, resultSet.getObject("ProtoEnumArray", Genre[].class)); + + assertFalse(resultSet.next()); + } + } + + @Test + public void testNullElements() throws Exception { + assumeFalse( + "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); + try (Connection connection = DriverManager.getConnection(url); + PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Types" + + " (RowID, ProtoMessage, ProtoEnum, ProtoMessageArray, ProtoEnumArray) VALUES (?, ?, ?, ?, ?)")) { + ps.setInt(1, 2); + ps.setObject(2, null, ProtoMessageType.INSTANCE); + ps.setObject(3, null, ProtoEnumType.INSTANCE); + ps.setArray(4, connection.createArrayOf("PROTO", null)); + ps.setArray(5, connection.createArrayOf("ENUM", null)); + + final int updateCount = ps.executeUpdate(); + assertEquals(1, updateCount); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM Types WHERE RowID = 2")) { + + assertTrue(resultSet.next()); + assertEquals(2, resultSet.getInt("RowID")); + assertNull(resultSet.getObject("ProtoMessage", SingerInfo.class)); + assertNull(resultSet.getObject("ProtoEnum", Genre.class)); + assertNull(resultSet.getObject("ProtoMessageArray", SingerInfo[].class)); + assertNull(resultSet.getObject("ProtoEnumArray", Genre[].class)); + + assertFalse(resultSet.next()); + } + } + + @Test + public void testUntypedNullElements() throws Exception { + assumeFalse( + "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); + try (Connection connection = DriverManager.getConnection(url); + PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Types" + " (RowID, ProtoMessage, ProtoEnum) VALUES (?, ?, ?)")) { + ps.setInt(1, 3); + ps.setObject(2, null); + ps.setObject(3, null); + + final int updateCount = ps.executeUpdate(); + assertEquals(1, updateCount); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM Types WHERE RowID = 3")) { + + resultSet.next(); + assertEquals(3, resultSet.getInt("RowID")); + assertNull(resultSet.getObject("ProtoMessage", SingerInfo.class)); + assertNull(resultSet.getObject("ProtoEnum", Genre.class)); + + assertFalse(resultSet.next()); + } + } + + @Test + public void testInterCompatibility() throws Exception { + assumeFalse( + "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); + SingerInfo singerInfo = + SingerInfo.newBuilder() + .setSingerId(1) + .setNationality("Country1") + .setGenre(Genre.ROCK) + .build(); + Genre singerGenre = Genre.ROCK; + byte[] singerInfoBytes = singerInfo.toByteArray(); + long singerGenreConst = singerGenre.getNumber(); + try (Connection connection = DriverManager.getConnection(url); + PreparedStatement ps = + connection.prepareStatement( + "INSERT INTO Types" + " (RowID, ProtoMessage, ProtoEnum) VALUES (?, ?, ?)")) { + ps.setInt(1, 4); + ps.setObject(2, singerInfoBytes); + ps.setObject(3, singerGenreConst); + + final int updateCount = ps.executeUpdate(); + assertEquals(1, updateCount); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM Types WHERE RowID = 4")) { + + resultSet.next(); + assertEquals(4, resultSet.getInt("RowID")); + assertEquals(singerInfo, resultSet.getObject("ProtoMessage", SingerInfo.class)); + assertEquals(singerGenre, resultSet.getObject("ProtoEnum", Genre.class)); + assertArrayEquals(singerInfoBytes, resultSet.getBytes("ProtoMessage")); + assertEquals(singerGenreConst, resultSet.getInt("ProtoEnum")); + + assertFalse(resultSet.next()); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java new file mode 100644 index 000000000000..00e44bb30873 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java @@ -0,0 +1,1191 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/test/resources/com/google/cloud/spanner/jdbc/it/singer.proto + +// Protobuf Java Version: 3.25.1 +package com.google.cloud.spanner.jdbc.it; + +public final class SingerProto { + private SingerProto() {} + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {} + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); + } + /** Protobuf enum {@code examples.spanner.music.Genre} */ + public enum Genre implements com.google.protobuf.ProtocolMessageEnum { + /** POP = 0; */ + POP(0), + /** JAZZ = 1; */ + JAZZ(1), + /** FOLK = 2; */ + FOLK(2), + /** ROCK = 3; */ + ROCK(3), + UNRECOGNIZED(-1), + ; + + /** POP = 0; */ + public static final int POP_VALUE = 0; + /** JAZZ = 1; */ + public static final int JAZZ_VALUE = 1; + /** FOLK = 2; */ + public static final int FOLK_VALUE = 2; + /** ROCK = 3; */ + public static final int ROCK_VALUE = 3; + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new IllegalArgumentException("Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @Deprecated + public static Genre valueOf(int value) { + return forNumber(value); + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + */ + public static Genre forNumber(int value) { + switch (value) { + case 0: + return POP; + case 1: + return JAZZ; + case 2: + return FOLK; + case 3: + return ROCK; + default: + return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap internalGetValueMap() { + return internalValueMap; + } + + private static final com.google.protobuf.Internal.EnumLiteMap internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Genre findValueByNumber(int number) { + return Genre.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() { + if (this == UNRECOGNIZED) { + throw new IllegalStateException("Can't get the descriptor of an unrecognized enum value."); + } + return getDescriptor().getValues().get(ordinal()); + } + + public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() { + return getDescriptor(); + } + + public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { + return SingerProto.getDescriptor().getEnumTypes().get(0); + } + + private static final Genre[] VALUES = values(); + + public static Genre valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new IllegalArgumentException("EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private Genre(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:examples.spanner.music.Genre) + } + + public interface SingerInfoOrBuilder + extends + // @@protoc_insertion_point(interface_extends:examples.spanner.music.SingerInfo) + com.google.protobuf.MessageOrBuilder { + + /** + * optional int64 singer_id = 1; + * + * @return Whether the singerId field is set. + */ + boolean hasSingerId(); + /** + * optional int64 singer_id = 1; + * + * @return The singerId. + */ + long getSingerId(); + + /** + * optional string birth_date = 2; + * + * @return Whether the birthDate field is set. + */ + boolean hasBirthDate(); + /** + * optional string birth_date = 2; + * + * @return The birthDate. + */ + String getBirthDate(); + /** + * optional string birth_date = 2; + * + * @return The bytes for birthDate. + */ + com.google.protobuf.ByteString getBirthDateBytes(); + + /** + * optional string nationality = 3; + * + * @return Whether the nationality field is set. + */ + boolean hasNationality(); + /** + * optional string nationality = 3; + * + * @return The nationality. + */ + String getNationality(); + /** + * optional string nationality = 3; + * + * @return The bytes for nationality. + */ + com.google.protobuf.ByteString getNationalityBytes(); + + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return Whether the genre field is set. + */ + boolean hasGenre(); + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The enum numeric value on the wire for genre. + */ + int getGenreValue(); + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The genre. + */ + Genre getGenre(); + } + /** Protobuf type {@code examples.spanner.music.SingerInfo} */ + public static final class SingerInfo extends com.google.protobuf.GeneratedMessageV3 + implements + // @@protoc_insertion_point(message_implements:examples.spanner.music.SingerInfo) + SingerInfoOrBuilder { + private static final long serialVersionUID = 0L; + // Use SingerInfo.newBuilder() to construct. + private SingerInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private SingerInfo() { + birthDate_ = ""; + nationality_ = ""; + genre_ = 0; + } + + @Override + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + return new SingerInfo(); + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + return SingerProto.internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized(SingerInfo.class, Builder.class); + } + + private int bitField0_; + public static final int SINGER_ID_FIELD_NUMBER = 1; + private long singerId_ = 0L; + /** + * optional int64 singer_id = 1; + * + * @return Whether the singerId field is set. + */ + @Override + public boolean hasSingerId() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int64 singer_id = 1; + * + * @return The singerId. + */ + @Override + public long getSingerId() { + return singerId_; + } + + public static final int BIRTH_DATE_FIELD_NUMBER = 2; + + @SuppressWarnings("serial") + private volatile Object birthDate_ = ""; + /** + * optional string birth_date = 2; + * + * @return Whether the birthDate field is set. + */ + @Override + public boolean hasBirthDate() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string birth_date = 2; + * + * @return The birthDate. + */ + @Override + public String getBirthDate() { + Object ref = birthDate_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + birthDate_ = s; + return s; + } + } + /** + * optional string birth_date = 2; + * + * @return The bytes for birthDate. + */ + @Override + public com.google.protobuf.ByteString getBirthDateBytes() { + Object ref = birthDate_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + birthDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NATIONALITY_FIELD_NUMBER = 3; + + @SuppressWarnings("serial") + private volatile Object nationality_ = ""; + /** + * optional string nationality = 3; + * + * @return Whether the nationality field is set. + */ + @Override + public boolean hasNationality() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional string nationality = 3; + * + * @return The nationality. + */ + @Override + public String getNationality() { + Object ref = nationality_; + if (ref instanceof String) { + return (String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + nationality_ = s; + return s; + } + } + /** + * optional string nationality = 3; + * + * @return The bytes for nationality. + */ + @Override + public com.google.protobuf.ByteString getNationalityBytes() { + Object ref = nationality_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + nationality_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int GENRE_FIELD_NUMBER = 4; + private int genre_ = 0; + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return Whether the genre field is set. + */ + @Override + public boolean hasGenre() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The enum numeric value on the wire for genre. + */ + @Override + public int getGenreValue() { + return genre_; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The genre. + */ + @Override + public Genre getGenre() { + Genre result = Genre.forNumber(genre_); + return result == null ? Genre.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + + @Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeInt64(1, singerId_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, birthDate_); + } + if (((bitField0_ & 0x00000004) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, nationality_); + } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeEnum(4, genre_); + } + getUnknownFields().writeTo(output); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream.computeInt64Size(1, singerId_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, birthDate_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, nationality_); + } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream.computeEnumSize(4, genre_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof SingerInfo)) { + return super.equals(obj); + } + SingerInfo other = (SingerInfo) obj; + + if (hasSingerId() != other.hasSingerId()) return false; + if (hasSingerId()) { + if (getSingerId() != other.getSingerId()) return false; + } + if (hasBirthDate() != other.hasBirthDate()) return false; + if (hasBirthDate()) { + if (!getBirthDate().equals(other.getBirthDate())) return false; + } + if (hasNationality() != other.hasNationality()) return false; + if (hasNationality()) { + if (!getNationality().equals(other.getNationality())) return false; + } + if (hasGenre() != other.hasGenre()) return false; + if (hasGenre()) { + if (genre_ != other.genre_) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasSingerId()) { + hash = (37 * hash) + SINGER_ID_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getSingerId()); + } + if (hasBirthDate()) { + hash = (37 * hash) + BIRTH_DATE_FIELD_NUMBER; + hash = (53 * hash) + getBirthDate().hashCode(); + } + if (hasNationality()) { + hash = (37 * hash) + NATIONALITY_FIELD_NUMBER; + hash = (53 * hash) + getNationality().hashCode(); + } + if (hasGenre()) { + hash = (37 * hash) + GENRE_FIELD_NUMBER; + hash = (53 * hash) + genre_; + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static SingerInfo parseFrom(java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SingerInfo parseFrom( + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SingerInfo parseFrom(com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SingerInfo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SingerInfo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static SingerInfo parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static SingerInfo parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static SingerInfo parseFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + public static SingerInfo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); + } + + public static SingerInfo parseDelimitedFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); + } + + public static SingerInfo parseFrom(com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static SingerInfo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + @Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(SingerInfo prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @Override + protected Builder newBuilderForType(BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** Protobuf type {@code examples.spanner.music.SingerInfo} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements + // @@protoc_insertion_point(builder_implements:examples.spanner.music.SingerInfo) + SingerInfoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + return SingerProto.internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized(SingerInfo.class, Builder.class); + } + + // Construct using com.google.cloud.spanner.SingerProto.SingerInfo.newBuilder() + private Builder() {} + + private Builder(BuilderParent parent) { + super(parent); + } + + @Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + singerId_ = 0L; + birthDate_ = ""; + nationality_ = ""; + genre_ = 0; + return this; + } + + @Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @Override + public SingerInfo getDefaultInstanceForType() { + return SingerInfo.getDefaultInstance(); + } + + @Override + public SingerInfo build() { + SingerInfo result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @Override + public SingerInfo buildPartial() { + SingerInfo result = new SingerInfo(this); + if (bitField0_ != 0) { + buildPartial0(result); + } + onBuilt(); + return result; + } + + private void buildPartial0(SingerInfo result) { + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.singerId_ = singerId_; + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.birthDate_ = birthDate_; + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.nationality_ = nationality_; + to_bitField0_ |= 0x00000004; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.genre_ = genre_; + to_bitField0_ |= 0x00000008; + } + result.bitField0_ |= to_bitField0_; + } + + @Override + public Builder clone() { + return super.clone(); + } + + @Override + public Builder setField(com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { + return super.setField(field, value); + } + + @Override + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @Override + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, int index, Object value) { + return super.setRepeatedField(field, index, value); + } + + @Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, Object value) { + return super.addRepeatedField(field, value); + } + + @Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof SingerInfo) { + return mergeFrom((SingerInfo) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(SingerInfo other) { + if (other == SingerInfo.getDefaultInstance()) return this; + if (other.hasSingerId()) { + setSingerId(other.getSingerId()); + } + if (other.hasBirthDate()) { + birthDate_ = other.birthDate_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasNationality()) { + nationality_ = other.nationality_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (other.hasGenre()) { + setGenre(other.getGenre()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @Override + public final boolean isInitialized() { + return true; + } + + @Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: + { + singerId_ = input.readInt64(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 18: + { + birthDate_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: + { + nationality_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 32: + { + genre_ = input.readEnum(); + bitField0_ |= 0x00000008; + break; + } // case 32 + default: + { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + private int bitField0_; + + private long singerId_; + /** + * optional int64 singer_id = 1; + * + * @return Whether the singerId field is set. + */ + @Override + public boolean hasSingerId() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int64 singer_id = 1; + * + * @return The singerId. + */ + @Override + public long getSingerId() { + return singerId_; + } + /** + * optional int64 singer_id = 1; + * + * @param value The singerId to set. + * @return This builder for chaining. + */ + public Builder setSingerId(long value) { + + singerId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * optional int64 singer_id = 1; + * + * @return This builder for chaining. + */ + public Builder clearSingerId() { + bitField0_ = (bitField0_ & ~0x00000001); + singerId_ = 0L; + onChanged(); + return this; + } + + private Object birthDate_ = ""; + /** + * optional string birth_date = 2; + * + * @return Whether the birthDate field is set. + */ + public boolean hasBirthDate() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string birth_date = 2; + * + * @return The birthDate. + */ + public String getBirthDate() { + Object ref = birthDate_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + birthDate_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * optional string birth_date = 2; + * + * @return The bytes for birthDate. + */ + public com.google.protobuf.ByteString getBirthDateBytes() { + Object ref = birthDate_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + birthDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string birth_date = 2; + * + * @param value The birthDate to set. + * @return This builder for chaining. + */ + public Builder setBirthDate(String value) { + if (value == null) { + throw new NullPointerException(); + } + birthDate_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * optional string birth_date = 2; + * + * @return This builder for chaining. + */ + public Builder clearBirthDate() { + birthDate_ = getDefaultInstance().getBirthDate(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * optional string birth_date = 2; + * + * @param value The bytes for birthDate to set. + * @return This builder for chaining. + */ + public Builder setBirthDateBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + birthDate_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private Object nationality_ = ""; + /** + * optional string nationality = 3; + * + * @return Whether the nationality field is set. + */ + public boolean hasNationality() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional string nationality = 3; + * + * @return The nationality. + */ + public String getNationality() { + Object ref = nationality_; + if (!(ref instanceof String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + String s = bs.toStringUtf8(); + nationality_ = s; + return s; + } else { + return (String) ref; + } + } + /** + * optional string nationality = 3; + * + * @return The bytes for nationality. + */ + public com.google.protobuf.ByteString getNationalityBytes() { + Object ref = nationality_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((String) ref); + nationality_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string nationality = 3; + * + * @param value The nationality to set. + * @return This builder for chaining. + */ + public Builder setNationality(String value) { + if (value == null) { + throw new NullPointerException(); + } + nationality_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * optional string nationality = 3; + * + * @return This builder for chaining. + */ + public Builder clearNationality() { + nationality_ = getDefaultInstance().getNationality(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * optional string nationality = 3; + * + * @param value The bytes for nationality to set. + * @return This builder for chaining. + */ + public Builder setNationalityBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + nationality_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private int genre_ = 0; + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return Whether the genre field is set. + */ + @Override + public boolean hasGenre() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The enum numeric value on the wire for genre. + */ + @Override + public int getGenreValue() { + return genre_; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @param value The enum numeric value on the wire for genre to set. + * @return This builder for chaining. + */ + public Builder setGenreValue(int value) { + genre_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return The genre. + */ + @Override + public Genre getGenre() { + Genre result = Genre.forNumber(genre_); + return result == null ? Genre.UNRECOGNIZED : result; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @param value The genre to set. + * @return This builder for chaining. + */ + public Builder setGenre(Genre value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + genre_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * + * @return This builder for chaining. + */ + public Builder clearGenre() { + bitField0_ = (bitField0_ & ~0x00000008); + genre_ = 0; + onChanged(); + return this; + } + + @Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + // @@protoc_insertion_point(builder_scope:examples.spanner.music.SingerInfo) + } + + // @@protoc_insertion_point(class_scope:examples.spanner.music.SingerInfo) + private static final SingerInfo DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new SingerInfo(); + } + + public static SingerInfo getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @Override + public SingerInfo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException() + .setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @Override + public SingerInfo getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_examples_spanner_music_SingerInfo_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + return descriptor; + } + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + + static { + String[] descriptorData = { + "\n\014singer.proto\022\026examples.spanner.music\"\301" + + "\001\n\nSingerInfo\022\026\n\tsinger_id\030\001 \001(\003H\000\210\001\001\022\027\n" + + "\nbirth_date\030\002 \001(\tH\001\210\001\001\022\030\n\013nationality\030\003 " + + "\001(\tH\002\210\001\001\0221\n\005genre\030\004 \001(\0162\035.examples.spann" + + "er.music.GenreH\003\210\001\001B\014\n\n_singer_idB\r\n\013_bi" + + "rth_dateB\016\n\014_nationalityB\010\n\006_genre*.\n\005Ge" + + "nre\022\007\n\003POP\020\000\022\010\n\004JAZZ\020\001\022\010\n\004FOLK\020\002\022\010\n\004ROCK" + + "\020\003B)\n\030com.google.cloud.spannerB\013SingerPr" + + "otoP\000b\006proto3" + }; + descriptor = + com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( + descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}); + internal_static_examples_spanner_music_SingerInfo_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_examples_spanner_music_SingerInfo_descriptor, + new String[] { + "SingerId", "BirthDate", "Nationality", "Genre", + }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql index 2dea04231515..8fd7ca88c2cf 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ITDdlTest.sql @@ -127,7 +127,7 @@ WHERE TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_1' OR TABLE_NAME='VALID_MULTIP NEW_CONNECTION; -/* +/* * Do a test that shows that a DDL batch might only execute some of the statements, * for example if data in a table prevents a unique index from being created. */ @@ -187,3 +187,42 @@ RUN BATCH; START BATCH DDL; ABORT BATCH; + +NEW_CONNECTION; +-- Set proto descriptors using relative path to the descriptors.pb file. This gets applied for next DDL statement +SET PROTO_DESCRIPTORS_FILE_PATH = 'src/test/resources/com/google/cloud/spanner/jdbc/it/descriptors.pb'; +-- Check if Proto descriptors is set +@EXPECT RESULT_SET 'PROTO_DESCRIPTORS' +SHOW VARIABLE PROTO_DESCRIPTORS; + +CREATE PROTO BUNDLE (examples.spanner.music.Genre); +-- Check if Proto descriptors is reset to null +@EXPECT RESULT_SET 'PROTO_DESCRIPTORS',null +SHOW VARIABLE PROTO_DESCRIPTORS; + +-- Set Proto Descriptor as base64 string. This gets applied to all statements in next DDL batch +SET PROTO_DESCRIPTORS = 'CvYCCgxzaW5nZXIucHJvdG8SFmV4YW1wbGVzLnNwYW5uZXIubXVzaWMi6gEKClNpbmdlckluZm8SIAoJc2luZ2VyX2lkGAEgASgDSABSCHNpbmdlcklkiAEBEiIKCmJpcnRoX2RhdGUYAiABKAlIAVIJYmlydGhEYXRliAEBEiUKC25hdGlvbmFsaXR5GAMgASgJSAJSC25hdGlvbmFsaXR5iAEBEjgKBWdlbnJlGAQgASgOMh0uZXhhbXBsZXMuc3Bhbm5lci5tdXNpYy5HZW5yZUgDUgVnZW5yZYgBAUIMCgpfc2luZ2VyX2lkQg0KC19iaXJ0aF9kYXRlQg4KDF9uYXRpb25hbGl0eUIICgZfZ2VucmUqLgoFR2VucmUSBwoDUE9QEAASCAoESkFaWhABEggKBEZPTEsQAhIICgRST0NLEANCKQoYY29tLmdvb2dsZS5jbG91ZC5zcGFubmVyQgtTaW5nZXJQcm90b1AAYgZwcm90bzM='; + +@EXPECT RESULT_SET 'PROTO_DESCRIPTORS' +SHOW VARIABLE PROTO_DESCRIPTORS; + +START BATCH DDL; +ALTER PROTO BUNDLE INSERT (examples.spanner.music.SingerInfo); +CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + SingerInfo examples.spanner.music.SingerInfo, + SingerGenre examples.spanner.music.Genre +) PRIMARY KEY (SingerId); +-- Run the batch +RUN BATCH; + +-- Check if Proto descriptors is reset to null +@EXPECT RESULT_SET 'PROTO_DESCRIPTORS',null +SHOW VARIABLE PROTO_DESCRIPTORS; +-- Check that the table is created +@EXPECT RESULT_SET +SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME='Singers'; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/descriptors.pb b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/descriptors.pb new file mode 100644 index 0000000000000000000000000000000000000000..115e5fccbb555082b7202c1bc0f18395755c9fcd GIT binary patch literal 377 zcmZvY!A^rf5QbT3D-75W4u*?K)5JtQ>_IPHU5!#}0>N7^8wx9K0=oogQs2O5^#MG~ zE>U~%Hu>_+%%2~=Oz=7`O4j10mAwp3*gmV9igmbaG9de3@KM}x-7FXg`1`BY; zHOh++Ezr3Y8L2&@Rq=sPumsrhwtu5V*0azY6emKdquKp{lye5I$a*eCR`LElw6tWV zhfrxZFfEyASvVPl`PC`@KO=rrQe>s0J!}#Wfd1wr$KcYxOk@roJ$O%Sm{I-b62nyA z3XZ@^;>0%s8zxV;n~jgu^bkL Date: Tue, 28 May 2024 15:11:35 +0200 Subject: [PATCH 1294/1979] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.7.0 (#1621) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 89194028a307..31285be61f93 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -47,7 +47,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.13 + 1.7.0 true From fa42d457d10195aa42ffb8a97388e03e5d496756 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 30 May 2024 15:55:33 +0200 Subject: [PATCH 1295/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.1 (#1624) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 56d86ef7ee10..fc39cf7f1633 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.68.0 + 6.68.1 pom import From 900b04d0a190ebb1ca795c4d6a3f9faad6171af7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 31 May 2024 20:03:43 +0200 Subject: [PATCH 1296/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.0 (#1625) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fc39cf7f1633..58854dc94420 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -266,7 +266,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.3 + 3.6.0 From fd63dbb313c9b782b3ef63b4a6ce11aa0fb64a01 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 21:52:04 +0200 Subject: [PATCH 1297/1979] chore(main): release 2.19.0 (#1618) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6e731ee2b327..a4644d019855 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [2.19.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.18.1...v2.19.0) (2024-05-31) + + +### Features + +* Add Proto Columns support in JDBC ([#1252](https://github.com/googleapis/java-spanner-jdbc/issues/1252)) ([3efa9ac](https://github.com/googleapis/java-spanner-jdbc/commit/3efa9ac7906bab35d72f2951b9945a873f48f013)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.0 ([#1620](https://github.com/googleapis/java-spanner-jdbc/issues/1620)) ([255eeef](https://github.com/googleapis/java-spanner-jdbc/commit/255eeefa1ce682a46a4d0467ce297acfb40b0d25)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.1 ([#1624](https://github.com/googleapis/java-spanner-jdbc/issues/1624)) ([f4a83ba](https://github.com/googleapis/java-spanner-jdbc/commit/f4a83ba0d4702caa433a8390ff75c955d7669b17)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.0 ([#1616](https://github.com/googleapis/java-spanner-jdbc/issues/1616)) ([6912711](https://github.com/googleapis/java-spanner-jdbc/commit/691271199bed294f5ba272285282be975e8bbead)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.0 ([#1617](https://github.com/googleapis/java-spanner-jdbc/issues/1617)) ([155d6c6](https://github.com/googleapis/java-spanner-jdbc/commit/155d6c65c4ae3c9306ce86864bb4a4b4c9569473)) + ## [2.18.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.18.0...v2.18.1) (2024-05-22) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 58854dc94420..125cbc14bed3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.18.2-SNAPSHOT + 2.19.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 46e0fc60d9a4..9a8527edd84c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.2-SNAPSHOT + 2.19.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index de4db31cf7d5..1291d8c34939 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.18.1:2.18.2-SNAPSHOT +google-cloud-spanner-jdbc:2.19.0:2.19.0 From a3e02dfabda9ca367b0217144c5d59452083dfb4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 1 Jun 2024 13:06:18 +0200 Subject: [PATCH 1298/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.0 (#1629) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9509c6bae55f..f4d92d4a476c 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.18.1 + 2.19.0 From 0664d5b6b477dde65f795073a4f16533e1b7ba2c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 13:06:34 +0200 Subject: [PATCH 1299/1979] chore(main): release 2.19.1-SNAPSHOT (#1627) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 125cbc14bed3..3f1977dee286 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.0 + 2.19.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9a8527edd84c..56ab26ba7f0c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.0 + 2.19.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1291d8c34939..173e609b3c6f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.0:2.19.0 +google-cloud-spanner-jdbc:2.19.0:2.19.1-SNAPSHOT From 5ddb32c3b2e75fc0574e52a74896599767f0d534 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 1 Jun 2024 13:07:34 +0200 Subject: [PATCH 1300/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.31.0 (#1630) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index fdecc15b402a..3c0da512919c 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.30.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.31.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 532f888ecbb9..aeafc31812f2 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.30.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.31.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 1292cf163b17..047ec1b678bd 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.30.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.31.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3f1977dee286..ac2a9aa1a601 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.30.1 + 3.31.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index efd50fa3d1b5..f2d16336ba87 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.30.1 + 3.31.0 From 2c22aa0965522fb70fdbf2770cc7caffb37189f4 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 12:32:17 +0000 Subject: [PATCH 1301/1979] chore(main): release 2.19.1-SNAPSHOT (#1631) :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). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a4644d019855..e27c86d671b6 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.19.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.0...v2.19.1) (2024-06-01) + + +### Dependencies + +* Update dependency com.google.cloud:sdk-platform-java-config to v3.31.0 ([#1630](https://github.com/googleapis/java-spanner-jdbc/issues/1630)) ([98b530d](https://github.com/googleapis/java-spanner-jdbc/commit/98b530dce7a6131a562afdfca6b8b7c73fb83d7a)) + ## [2.19.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.18.1...v2.19.0) (2024-05-31) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ac2a9aa1a601..a58dd0bdf79f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.1-SNAPSHOT + 2.19.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 56ab26ba7f0c..096f4ec7c0a0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.1-SNAPSHOT + 2.19.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 173e609b3c6f..13a1fd8d0183 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.0:2.19.1-SNAPSHOT +google-cloud-spanner-jdbc:2.19.1:2.19.1 From 705aca440be1cd003453cae54a7ab6fd1418f617 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 5 Jun 2024 07:22:46 +0200 Subject: [PATCH 1302/1979] deps: update dependency org.mybatis.dynamic-sql:mybatis-dynamic-sql to v1.5.2 (#1633) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b8834866656a..495ba6dc1112 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -51,7 +51,7 @@ org.mybatis.dynamic-sql mybatis-dynamic-sql - 1.5.1 + 1.5.2 From db217f4bfabf98ad283d196682afba11f1abbaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 5 Jun 2024 07:25:17 +0200 Subject: [PATCH 1303/1979] chore: run emulator on random port (#1626) --- .../test/java/com/example/spanner/jdbc/JdbcSampleTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java index 9365ad9bfee2..1b0328de91e9 100644 --- a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java +++ b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java @@ -96,11 +96,8 @@ public static void setup() throws Exception { emulator = new GenericContainer<>( DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) - // .withExposedPorts(9010) + .withExposedPorts(9010) .waitingFor(Wait.forListeningPort()); - // TODO: Remove and replace with dynamic port binding when Spanner client library 6.64.0 has - // been released. - emulator.setPortBindings(ImmutableList.of("9010:9010")); emulator.start(); try (InstanceAdminClient client = InstanceAdminClient.create( From 785123987a4f452dc7765fbf81ff036882bb30f3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 07:57:45 +0200 Subject: [PATCH 1304/1979] chore(main): release 2.19.1-SNAPSHOT (#1636) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a58dd0bdf79f..bf49531c16c9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.1 + 2.19.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 096f4ec7c0a0..983ad18614df 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.1 + 2.19.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 13a1fd8d0183..a430b2700753 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.1:2.19.1 +google-cloud-spanner-jdbc:2.19.1:2.19.2-SNAPSHOT From c7253eeaa09925d489eaa52b90b5392564cda96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 5 Jun 2024 08:09:10 +0200 Subject: [PATCH 1305/1979] chore: remove workaround for non-public method (#1634) * chore: remove workaround for non-public method * chore: add ignored diff to clirr --- .../clirr-ignored-differences.xml | 5 ++- .../spanner/connection/ConnectionHelper.java | 31 ------------------- .../spanner/jdbc/AbstractJdbcConnection.java | 3 +- .../ConcurrentTransactionOnEmulatorTest.java | 2 +- 4 files changed, 6 insertions(+), 35 deletions(-) delete mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index 368e9ed99c36..431f54069b84 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -72,5 +72,8 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setProtoDescriptors(java.io.InputStream) - + + 8001 + com/google/cloud/spanner/connection/ConnectionHelper + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java deleted file mode 100644 index 5f71ec605b6a..000000000000 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionHelper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.spanner.connection; - -import com.google.cloud.spanner.Spanner; - -/** Static helper class to get the {@link Spanner} instance from the underlying connection. */ -public class ConnectionHelper { - - /** Private constructor to prevent instantiation. */ - private ConnectionHelper() {} - - public static Spanner getSpanner(Connection connection) { - // TODO: Remove once getSpanner() has been added to the public interface. - return ((ConnectionImpl) connection).getSpanner(); - } -} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 340b6d40964f..d790cf855c16 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -20,7 +20,6 @@ import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.AbstractStatementParser; -import com.google.cloud.spanner.connection.ConnectionHelper; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; @@ -81,7 +80,7 @@ ConnectionOptions getConnectionOptions() { } Spanner getSpanner() { - return ConnectionHelper.getSpanner(this.spanner); + return this.spanner.getSpanner(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java index e9931e604350..8874120484cd 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java @@ -51,7 +51,7 @@ public static void startEmulator() { new GenericContainer<>( DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) .withExposedPorts(9010) - .waitingFor(Wait.forListeningPort()); + .waitingFor(Wait.forListeningPorts(9010)); emulator.start(); properties = new Properties(); properties.setProperty("autoConfigEmulator", "true"); From 17af1de3b2d5fc6484b8a0e21d4366e0b7f7d1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 5 Jun 2024 08:10:01 +0200 Subject: [PATCH 1306/1979] fix: cleanup unused methods (#1635) --- .../jdbc/AbstractJdbcPreparedStatement.java | 1 + .../spanner/jdbc/AbstractJdbcStatement.java | 25 ------------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 2a9ba067df4b..9c58a5239167 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -170,6 +170,7 @@ public void setAsciiStream(int parameterIndex, InputStream value, int length) parameters.setParameter(parameterIndex, value, Types.VARCHAR, length); } + @SuppressWarnings("DeprecatedIsStillUsed") @Override @Deprecated public void setUnicodeStream(int parameterIndex, InputStream value, int length) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index d12678bf2915..f3a1539b88bb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -243,19 +243,6 @@ private T doWithStatementTimeout( } } - /** - * 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. @@ -268,18 +255,6 @@ int checkedCast(long updateCount) throws SQLException { 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)); - } - /** * 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. From 52ec694ca104b5b4f1b97969d44a0138d807dba7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:43:43 +0200 Subject: [PATCH 1307/1979] chore(main): release 2.19.1 (#1637) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e27c86d671b6..c7927bb50de1 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.19.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.0...v2.19.1) (2024-06-05) + + +### Bug Fixes + +* Cleanup unused methods ([#1635](https://github.com/googleapis/java-spanner-jdbc/issues/1635)) ([ad0a35c](https://github.com/googleapis/java-spanner-jdbc/commit/ad0a35c82fd880ce5b705f4cb749c35664ccc604)) + + +### Dependencies + +* Update dependency com.google.cloud:sdk-platform-java-config to v3.31.0 ([#1630](https://github.com/googleapis/java-spanner-jdbc/issues/1630)) ([98b530d](https://github.com/googleapis/java-spanner-jdbc/commit/98b530dce7a6131a562afdfca6b8b7c73fb83d7a)) +* Update dependency org.mybatis.dynamic-sql:mybatis-dynamic-sql to v1.5.2 ([#1633](https://github.com/googleapis/java-spanner-jdbc/issues/1633)) ([7c62ee3](https://github.com/googleapis/java-spanner-jdbc/commit/7c62ee30e81a29654934d1f77f36816e92b3470d)) + ## [2.19.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.0...v2.19.1) (2024-06-01) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index bf49531c16c9..4925b5732588 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.2-SNAPSHOT + 2.19.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 983ad18614df..598f147e26f3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.2-SNAPSHOT + 2.19.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a430b2700753..91250e51bc10 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.1:2.19.2-SNAPSHOT +google-cloud-spanner-jdbc:2.19.2:2.19.2 From e6ae90d270427fe9558974ca4568ee27ecafc639 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:10:40 +0200 Subject: [PATCH 1308/1979] chore(main): release 2.19.2-SNAPSHOT (#1638) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4925b5732588..e37580c0719c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.2 + 2.19.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 598f147e26f3..3a8b374035b5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.2 + 2.19.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 91250e51bc10..01f88de117a9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.2:2.19.2 +google-cloud-spanner-jdbc:2.19.2:2.19.3-SNAPSHOT From 3de5af62df739b12886f004ac54f1a073de0531b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 5 Jun 2024 11:43:52 +0200 Subject: [PATCH 1309/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.2 (#1639) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index f4d92d4a476c..0e55880495ba 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.0 + 2.19.2 From 674c2a40560c51dcdd1f5d9e4d26d4dc9dc9d25a Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:19:08 +0200 Subject: [PATCH 1310/1979] ci: [java] automatic kokoro label in and /gcbrun comment (#1965) (#1640) Source-Link: https://github.com/googleapis/synthtool/commit/bd2bae89f70bad380da47fab9ec25985dfb87d67 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:72f0d373307d128b2cb720c5cb4d90b31f0e86529dd138c632710ae0c69efae3 Co-authored-by: Owl Bot --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 4 ++-- java-spanner-jdbc/.github/trusted-contribution.yml | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml index 5db36a5f7d8e..359fe71c1964 100644 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ b/java-spanner-jdbc/.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:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e -# created: 2024-05-09T16:31:37.168667071Z + digest: sha256:72f0d373307d128b2cb720c5cb4d90b31f0e86529dd138c632710ae0c69efae3 +# created: 2024-06-05T18:32:21.724930324Z diff --git a/java-spanner-jdbc/.github/trusted-contribution.yml b/java-spanner-jdbc/.github/trusted-contribution.yml index a0ba1f7d9078..88d3ac9bf1a7 100644 --- a/java-spanner-jdbc/.github/trusted-contribution.yml +++ b/java-spanner-jdbc/.github/trusted-contribution.yml @@ -1,3 +1,9 @@ trustedContributors: - renovate-bot - gcf-owl-bot[bot] + +annotations: +- type: comment + text: "/gcbrun" +- type: label + text: "kokoro:force-run" From 3dcc9facdce06581d1b1c8638fa25794674c7ca9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 13 Jun 2024 08:33:12 +0200 Subject: [PATCH 1311/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.69.0 (#1641) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e37580c0719c..2acd359afcbd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.68.1 + 6.69.0 pom import From ecf56b59c395697a133a7feed814698dd45717ad Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:54:29 +0200 Subject: [PATCH 1312/1979] chore(main): release 2.19.2 (#1642) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index c7927bb50de1..713ae805f353 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.19.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.1...v2.19.2) (2024-06-13) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.69.0 ([#1641](https://github.com/googleapis/java-spanner-jdbc/issues/1641)) ([55f86df](https://github.com/googleapis/java-spanner-jdbc/commit/55f86dfa217de2e2da280fbbd33d32aa7a0daa41)) + ## [2.19.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.0...v2.19.1) (2024-06-05) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2acd359afcbd..5a3f77925c97 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.3-SNAPSHOT + 2.19.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3a8b374035b5..33297370c473 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.3-SNAPSHOT + 2.19.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 01f88de117a9..408461dfe5e1 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.2:2.19.3-SNAPSHOT +google-cloud-spanner-jdbc:2.19.3:2.19.3 From 128d30f38261a5c463886a60fd53961e59947379 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:06:11 +0000 Subject: [PATCH 1313/1979] chore(main): release 2.19.3-SNAPSHOT (#1643) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5a3f77925c97..6839f2a0ce2e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.3 + 2.19.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 33297370c473..a610eea3f046 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.3 + 2.19.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 408461dfe5e1..0b003ad0958b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.3:2.19.3 +google-cloud-spanner-jdbc:2.19.3:2.19.4-SNAPSHOT From bac0520c902f51be7d2cec0798dae0ff9c7708cc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Jun 2024 15:44:29 +0200 Subject: [PATCH 1314/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.3 (#1644) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0e55880495ba..3ba40e024ef9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.2 + 2.19.3 From 58afe250e554f7252316070c6aa3376186156770 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Jun 2024 07:31:37 +0200 Subject: [PATCH 1315/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.0 (#1646) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6839f2a0ce2e..786a2ce8cca7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -403,7 +403,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.6.0 From b76e435538a6faf3f38da463ca05f5c5e9238705 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Jun 2024 08:27:57 +0200 Subject: [PATCH 1316/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.1 (#1645) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5aa23101ffc3..e96da2af2d3c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.0 + 2024.0.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 495ba6dc1112..846a256b9fd6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.0 + 2024.0.1 import pom From 5c71992325b038b1015ea7a125f73bc2045471ca Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 19 Jun 2024 11:24:20 +0200 Subject: [PATCH 1317/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.42.0 (#1623) 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.39.0` -> `26.42.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.39.0/26.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.39.0/26.42.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.42.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26420-2024-06-17) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.41.0...v26.42.0) ##### Dependencies - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.3 ([#​6645](https://togithub.com/googleapis/java-cloud-bom/issues/6645)) ([baf9c12](https://togithub.com/googleapis/java-cloud-bom/commit/baf9c12ff6c94bd1e300ae1b636cdc63e7281695)) ### [`v26.41.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26410-2024-06-12) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.31.0 ([#​6624](https://togithub.com/googleapis/java-cloud-bom/issues/6624)) ([6b74d3e](https://togithub.com/googleapis/java-cloud-bom/commit/6b74d3e9081eb895b991cf09e4a9a06b7498df4e)) - update dependency com.google.cloud:gapic-libraries-bom to v1.39.0 ([#​6638](https://togithub.com/googleapis/java-cloud-bom/issues/6638)) ([67320ae](https://togithub.com/googleapis/java-cloud-bom/commit/67320aed8cf903d6fb851d08c0e7222e37527258)) - update dependency com.google.cloud:google-cloud-bigquery to v2.40.3 ([#​6633](https://togithub.com/googleapis/java-cloud-bom/issues/6633)) ([e9574c2](https://togithub.com/googleapis/java-cloud-bom/commit/e9574c2493abcd53a68dc657147112961db664b4)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.6.0 ([#​6639](https://togithub.com/googleapis/java-cloud-bom/issues/6639)) ([8dca9b0](https://togithub.com/googleapis/java-cloud-bom/commit/8dca9b071cde8108e87d9db4b6d61bcd8e544eb7)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.39.5 ([#​6631](https://togithub.com/googleapis/java-cloud-bom/issues/6631)) ([23f5ad6](https://togithub.com/googleapis/java-cloud-bom/commit/23f5ad6f054524d511da963311402b243943375f)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.20.1 ([#​6628](https://togithub.com/googleapis/java-cloud-bom/issues/6628)) ([4206ac8](https://togithub.com/googleapis/java-cloud-bom/commit/4206ac831c6269569a7d98906287398b18cb9869)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.21.4 ([#​6634](https://togithub.com/googleapis/java-cloud-bom/issues/6634)) ([6b0e366](https://togithub.com/googleapis/java-cloud-bom/commit/6b0e3660a4fca4cd0685efb00e9f6a5102366522)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.18.0 ([#​6627](https://togithub.com/googleapis/java-cloud-bom/issues/6627)) ([678a51c](https://togithub.com/googleapis/java-cloud-bom/commit/678a51c5c112c1206c319d4f6f4cc4b19f901eca)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.8-alpha ([#​6635](https://togithub.com/googleapis/java-cloud-bom/issues/6635)) ([922b901](https://togithub.com/googleapis/java-cloud-bom/commit/922b901c40236b2c79d8f8ecd0618296b54fdf70)) - update dependency com.google.cloud:google-cloud-nio to v0.127.19 ([#​6636](https://togithub.com/googleapis/java-cloud-bom/issues/6636)) ([7533d4c](https://togithub.com/googleapis/java-cloud-bom/commit/7533d4c92b265b89ecb2cc39d0acdc0fcd51782f)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.130.0 ([#​6621](https://togithub.com/googleapis/java-cloud-bom/issues/6621)) ([e1242c3](https://togithub.com/googleapis/java-cloud-bom/commit/e1242c396bf2356c6a12cadfe273cfb7997f8b58)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.13.7 ([#​6637](https://togithub.com/googleapis/java-cloud-bom/issues/6637)) ([2914fb9](https://togithub.com/googleapis/java-cloud-bom/commit/2914fb9e8b615ae4aa7854cf14643208c9d7cfac)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.1 ([#​6622](https://togithub.com/googleapis/java-cloud-bom/issues/6622)) ([c62eac0](https://togithub.com/googleapis/java-cloud-bom/commit/c62eac081cd85d570d01e2ef29ea8bc188390f9d)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.69.0 ([#​6641](https://togithub.com/googleapis/java-cloud-bom/issues/6641)) ([78651d7](https://togithub.com/googleapis/java-cloud-bom/commit/78651d7f52f95ab602a9d69b47c5f3d969239638)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.2 ([#​6625](https://togithub.com/googleapis/java-cloud-bom/issues/6625)) ([45533f7](https://togithub.com/googleapis/java-cloud-bom/commit/45533f7ce7df401f0b9e60955d5a5d7d9880673c)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.40.0 ([#​6629](https://togithub.com/googleapis/java-cloud-bom/issues/6629)) ([e90e761](https://togithub.com/googleapis/java-cloud-bom/commit/e90e7618b5f1a9b18f723d53f8afb3889fdeaefb)) - update dependency org.freemarker:freemarker to v2.3.33 ([#​6626](https://togithub.com/googleapis/java-cloud-bom/issues/6626)) ([d5c3bdf](https://togithub.com/googleapis/java-cloud-bom/commit/d5c3bdf469891aac62a2c20fbe5adf1d685f66f3)) ### [`v26.40.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26400-2024-05-29) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.39.0...v26.40.0) ##### Features - \[java] allow passing libraries_bom_version from env ([#​1967](https://togithub.com/googleapis/java-cloud-bom/issues/1967)) ([#​6596](https://togithub.com/googleapis/java-cloud-bom/issues/6596)) ([42dc9c7](https://togithub.com/googleapis/java-cloud-bom/commit/42dc9c7e9d5ff2185e4ecc62aae61cc1632466b2)) ##### Dependencies - update actions/checkout action to v4 ([#​6585](https://togithub.com/googleapis/java-cloud-bom/issues/6585)) ([0820cf4](https://togithub.com/googleapis/java-cloud-bom/commit/0820cf4e8d2a44899cb2878a83ba56b3ca9fbcfa)) - update actions/checkout action to v4 ([#​6607](https://togithub.com/googleapis/java-cloud-bom/issues/6607)) ([9e6bc83](https://togithub.com/googleapis/java-cloud-bom/commit/9e6bc83f2e1954984f34ece12f5ed55ddb775fa9)) - update actions/github-script action to v7 ([#​6586](https://togithub.com/googleapis/java-cloud-bom/issues/6586)) ([1b0d93b](https://togithub.com/googleapis/java-cloud-bom/commit/1b0d93be6176576cd7de295f94d360635c63be2a)) - update actions/github-script action to v7 ([#​6608](https://togithub.com/googleapis/java-cloud-bom/issues/6608)) ([ca4eab4](https://togithub.com/googleapis/java-cloud-bom/commit/ca4eab47453e9bce9fff4960adac203bed4afbeb)) - update actions/setup-java action to v4 ([#​6588](https://togithub.com/googleapis/java-cloud-bom/issues/6588)) ([bc1631b](https://togithub.com/googleapis/java-cloud-bom/commit/bc1631b66ffbea46f2c6b9c74dada219d342a8d2)) - update actions/setup-java action to v4 ([#​6609](https://togithub.com/googleapis/java-cloud-bom/issues/6609)) ([6d5d132](https://togithub.com/googleapis/java-cloud-bom/commit/6d5d132dbafb30c072d4266f990a0982765b4172)) - update actions/setup-node action to v4 ([#​6589](https://togithub.com/googleapis/java-cloud-bom/issues/6589)) ([28c11fc](https://togithub.com/googleapis/java-cloud-bom/commit/28c11fcc55ad9cd856cd812ff84844df98b5e346)) - update actions/setup-node action to v4 ([#​6610](https://togithub.com/googleapis/java-cloud-bom/issues/6610)) ([9212351](https://togithub.com/googleapis/java-cloud-bom/commit/9212351192a830cbe496eabb49b2c8c2129b4ce7)) - update dependency com.google.cloud:first-party-dependencies to v3.30.1 ([#​6592](https://togithub.com/googleapis/java-cloud-bom/issues/6592)) ([08e4163](https://togithub.com/googleapis/java-cloud-bom/commit/08e4163e9cf0193271cbe9c1af38e159871088bc)) - update dependency com.google.cloud:gapic-libraries-bom to v1.38.0 ([#​6603](https://togithub.com/googleapis/java-cloud-bom/issues/6603)) ([8e7bce4](https://togithub.com/googleapis/java-cloud-bom/commit/8e7bce4d3ec6b78fe425c77011521bbc70ed8e45)) - update dependency com.google.cloud:google-cloud-bigquery to v2.40.2 ([#​6614](https://togithub.com/googleapis/java-cloud-bom/issues/6614)) ([c44894a](https://togithub.com/googleapis/java-cloud-bom/commit/c44894a4eeb8812c7cd407f3d13fb9149a934506)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.5.2 ([#​6611](https://togithub.com/googleapis/java-cloud-bom/issues/6611)) ([f3651c6](https://togithub.com/googleapis/java-cloud-bom/commit/f3651c689f89795090d331282752b34ad79b8cd6)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.39.3 ([#​6598](https://togithub.com/googleapis/java-cloud-bom/issues/6598)) ([d6518be](https://togithub.com/googleapis/java-cloud-bom/commit/d6518be6abdc16b5867b40cf0ef790c5cb0c76d3)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.39.4 ([#​6618](https://togithub.com/googleapis/java-cloud-bom/issues/6618)) ([1a7c94e](https://togithub.com/googleapis/java-cloud-bom/commit/1a7c94e9bee2258d9b66674ae66bb1c48f0ab3c8)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.19.3 ([#​6593](https://togithub.com/googleapis/java-cloud-bom/issues/6593)) ([6af567b](https://togithub.com/googleapis/java-cloud-bom/commit/6af567b889d07f144876405975ec48ef07c5584a)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.20.0 ([#​6617](https://togithub.com/googleapis/java-cloud-bom/issues/6617)) ([6abbddf](https://togithub.com/googleapis/java-cloud-bom/commit/6abbddfce32177104bee93d28315b051c57c1be3)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.21.3 ([#​6594](https://togithub.com/googleapis/java-cloud-bom/issues/6594)) ([3ee6bf0](https://togithub.com/googleapis/java-cloud-bom/commit/3ee6bf060d413bb1dd52566c9b7c2886c3fc0bfe)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.17.2 ([#​6595](https://togithub.com/googleapis/java-cloud-bom/issues/6595)) ([5e57c2d](https://togithub.com/googleapis/java-cloud-bom/commit/5e57c2d76f441f312d02982edd4f91d5e2553321)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.7-alpha ([#​6599](https://togithub.com/googleapis/java-cloud-bom/issues/6599)) ([ab4572e](https://togithub.com/googleapis/java-cloud-bom/commit/ab4572e10940c443c0e9bf6b12d3b7d663257c11)) - update dependency com.google.cloud:google-cloud-nio to v0.127.18 ([#​6600](https://togithub.com/googleapis/java-cloud-bom/issues/6600)) ([e4c7415](https://togithub.com/googleapis/java-cloud-bom/commit/e4c7415b26d0ac1fe6fda95acc137f16de63afe6)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.129.6 ([#​6590](https://togithub.com/googleapis/java-cloud-bom/issues/6590)) ([cddf911](https://togithub.com/googleapis/java-cloud-bom/commit/cddf91189ce26293c633ada8c2406e829b84162e)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.13.6 ([#​6601](https://togithub.com/googleapis/java-cloud-bom/issues/6601)) ([e2907a0](https://togithub.com/googleapis/java-cloud-bom/commit/e2907a0fed5c426ae32b4d0cd1d229d8bafa417c)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.67.0 ([#​6604](https://togithub.com/googleapis/java-cloud-bom/issues/6604)) ([3596bdc](https://togithub.com/googleapis/java-cloud-bom/commit/3596bdca42ef81b25291cd7150f8e6d40a93a584)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.68.0 ([#​6615](https://togithub.com/googleapis/java-cloud-bom/issues/6615)) ([b931bc5](https://togithub.com/googleapis/java-cloud-bom/commit/b931bc5db05b805d76a7f767a9799ee65bbae7da)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.18.1 ([#​6602](https://togithub.com/googleapis/java-cloud-bom/issues/6602)) ([0352c3c](https://togithub.com/googleapis/java-cloud-bom/commit/0352c3c62d1440c6ffe141bde1f9b9fa75716bfd)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.39.0 ([#​6605](https://togithub.com/googleapis/java-cloud-bom/issues/6605)) ([fac0a62](https://togithub.com/googleapis/java-cloud-bom/commit/fac0a62bf76c0d18985c17c3009438118623a065)) - update dependency commons-cli:commons-cli to v1.8.0 ([#​6606](https://togithub.com/googleapis/java-cloud-bom/issues/6606)) ([12c8d45](https://togithub.com/googleapis/java-cloud-bom/commit/12c8d45126c6f1f97b6ba1986159e858f1a4cbde))
    --- ### 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). --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f2d16336ba87..ceeb6fea7752 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.39.0 + 26.42.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e96da2af2d3c..48c870e16ce2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.39.0 + 26.42.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 846a256b9fd6..bb531c99ffa5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.39.0 + 26.42.0 import pom From fbe3dc14c1c4cf7ba000402fd65a61cb009aaeb1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:52:44 -0400 Subject: [PATCH 1318/1979] chore(main): release 2.19.3 (#1647) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 713ae805f353..1dba9adc6589 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.19.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.2...v2.19.3) (2024-06-19) + + +### Dependencies + +* Update dependency org.springframework.data:spring-data-bom to v2024.0.1 ([#1645](https://github.com/googleapis/java-spanner-jdbc/issues/1645)) ([58122ba](https://github.com/googleapis/java-spanner-jdbc/commit/58122ba6a32e97038bc49aea35c947853b05f576)) + ## [2.19.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.1...v2.19.2) (2024-06-13) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 786a2ce8cca7..f84606eb229e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.4-SNAPSHOT + 2.19.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a610eea3f046..b5d13a73a733 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.4-SNAPSHOT + 2.19.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0b003ad0958b..8e525fb691a4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.3:2.19.4-SNAPSHOT +google-cloud-spanner-jdbc:2.19.4:2.19.4 From e80178324a2c89cb2ab10c239e5b5c6ab03127ba Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:57:00 +0200 Subject: [PATCH 1319/1979] chore(main): release 2.19.4-SNAPSHOT (#1650) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f84606eb229e..7ed9299bb3ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.4 + 2.19.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b5d13a73a733..5b2f09c631e4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.4 + 2.19.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8e525fb691a4..384d1c7daecc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.4:2.19.4 +google-cloud-spanner-jdbc:2.19.4:2.19.5-SNAPSHOT From ebb51981e39aab0d5c295ac933c29391eeda39fe Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Jun 2024 13:59:46 +0200 Subject: [PATCH 1320/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.1 (#1648) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 48c870e16ce2..1f3326c86e25 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.0 + 3.3.1 From b45a34137fa6aa670f0e1e44d2062b4890ed0f4a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Jun 2024 13:59:58 +0200 Subject: [PATCH 1321/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.1 (#1649) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index bb531c99ffa5..f2adc315e796 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.0 + 3.3.1 From 1c8ee70969a5551662c8e6e8aec6b638e0650253 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Jun 2024 14:00:14 +0200 Subject: [PATCH 1322/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.4 (#1651) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3ba40e024ef9..e5186696709e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.3 + 2.19.4 From 928d26058a06d13e78277c44c316fe10e5db8e92 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 25 Jun 2024 20:22:52 +0200 Subject: [PATCH 1323/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.32.0 (#1654) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 3c0da512919c..8eb9dfbd6e81 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.31.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.32.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index aeafc31812f2..7d5ab3a25c4c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.31.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.32.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 047ec1b678bd..519c2e3ce370 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.31.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.32.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7ed9299bb3ef..e417744f4e2d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.31.0 + 3.32.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ceeb6fea7752..a7c189c45a5f 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.31.0 + 3.32.0 From 2997015feb8ebda8841d6d47b915d95a9412ce56 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jun 2024 10:01:43 +0200 Subject: [PATCH 1324/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.1 (#1656) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e417744f4e2d..2bf47ebe4b8c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -403,7 +403,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.6.0 + 3.6.1 From 438074dc7682aca23e3b451c71fbf5eff1148af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 27 Jun 2024 12:17:09 +0200 Subject: [PATCH 1325/1979] feat: add OpenTelemetry tracing (#1568) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add OpenTelemetry tracing * chore: add copyright headers * chore: add deps + reset tracing for test * fix: ClassCastException in Spring Data JDBC sample * docs: add sample for OpenTelemetry * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * docs: update sample for OpenTelemetry * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * test: check for credentials before setting up tracing * chore: cleanup * chore: add enable flag for otel to sample app * chore: add clirr diff * fix: add tracing prefix + more samples * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * chore: remove whitespace * docs: update sample to use non-snapshot versions * docs: update sample + add debugging guide * chore: cleanup * chore: actually use properties in example * docs: add link to tag sample * docs: improve documentation based on review comments * docs: clearify the names of the Spanner generated traces --------- Co-authored-by: Owl Bot --- java-spanner-jdbc/.readme-partials.yaml | 86 +++++- .../img/example-aborted-transaction.png | Bin 0 -> 486601 bytes .../documentation/img/example-api-tracing.png | Bin 0 -> 367693 bytes .../documentation/img/example-gfe-latency.png | Bin 0 -> 480367 bytes ...xample-search-for-aborted-transactions.png | Bin 0 -> 398774 bytes .../img/example-search-for-tag.png | Bin 0 -> 355299 bytes .../documentation/img/example-tracing.png | Bin 0 -> 353352 bytes .../documentation/latency-debugging-guide.md | 258 ++++++++++++++++ java-spanner-jdbc/pom.xml | 36 +++ .../samples/spring-data-jdbc/pom.xml | 32 ++ .../cloud/spanner/sample/Application.java | 144 ++++++++- .../cloud/spanner/sample/DatabaseSeeder.java | 130 +++++--- .../spanner/sample/JdbcConfiguration.java | 5 + .../sample/OpenTelemetryConfiguration.java | 99 ++++++ .../main/resources/application-cs.properties | 6 +- .../src/main/resources/application.properties | 4 + .../sample/ApplicationEmulatorTest.java | 72 +++++ .../cloud/spanner/sample/ApplicationTest.java | 69 ++++- .../test/resources/application-cs.properties | 2 +- .../src/test/resources/application.properties | 2 + .../cloud/spanner/jdbc/JdbcConnection.java | 19 +- .../google/cloud/spanner/jdbc/JdbcDriver.java | 23 +- .../cloud/spanner/SpannerOptionsHelper.java | 30 ++ .../JdbcConnectionGeneratedSqlScriptTest.java | 7 + .../spanner/jdbc/JdbcConnectionTest.java | 27 ++ .../spanner/jdbc/it/ITAbstractJdbcTest.java | 9 +- .../spanner/jdbc/it/ITOpenTelemetryTest.java | 281 ++++++++++++++++++ 27 files changed, 1267 insertions(+), 74 deletions(-) create mode 100644 java-spanner-jdbc/documentation/img/example-aborted-transaction.png create mode 100644 java-spanner-jdbc/documentation/img/example-api-tracing.png create mode 100644 java-spanner-jdbc/documentation/img/example-gfe-latency.png create mode 100644 java-spanner-jdbc/documentation/img/example-search-for-aborted-transactions.png create mode 100644 java-spanner-jdbc/documentation/img/example-search-for-tag.png create mode 100644 java-spanner-jdbc/documentation/img/example-tracing.png create mode 100644 java-spanner-jdbc/documentation/latency-debugging-guide.md create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/SpannerOptionsHelper.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml index 6fcc2f61ae2b..1ae28a88f135 100644 --- a/java-spanner-jdbc/.readme-partials.yaml +++ b/java-spanner-jdbc/.readme-partials.yaml @@ -26,7 +26,7 @@ custom_content: | ### Connection URL Properties - The Cloud Spanner JDBC driver supports the following connection URL properties. Note that all of + The Spanner JDBC driver supports the following connection URL properties. Note that all of these can also be supplied in a Properties instance that is passed to the `DriverManager#getConnection(String url, Properties properties)` method. @@ -37,6 +37,8 @@ custom_content: | - autoConfigEmulator (boolean): Automatically configure the connection to try to connect to the Cloud Spanner emulator. You do not need to specify any host or port in the connection string as long as the emulator is running on the default host/port (localhost:9010). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. This means that you do not need to execute any `gcloud` commands on the emulator to create the instance and database before you can connect to it. Example: `jdbc:cloudspanner:/projects/test-project/instances/test-instance/databases/test-db;autoConfigEmulator=true` - usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to a (local) server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. Example: `jdbc:cloudspanner://localhost:9010/projects/test-project/instances/test-instance/databases/test-db;usePlainText=true` - optimizerVersion (String): Sets the default query optimizer version to use for this connection. See also https://cloud.google.com/spanner/docs/query-optimizer/query-optimizer-versions. + - enableExtendedTracing (boolean): Enables extended OpenTelemetry tracing of queries that are executed by a JDBC connection. When enabled, the SQL string of the query that is executed is added as a property to the trace. + - enableApiTracing (boolean): Enables API OpenTelemetry tracing of all RPCs that are executed by the JDBC driver. When enabled, a trace will be created for each RPC invocation that is executed by the JDBC driver. Enable this to investigate latency problems and/or RPCs that are being retried. #### Advanced Properties - minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. @@ -46,6 +48,88 @@ custom_content: | - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. + ### OpenTelemetry Tracing + The Spanner JDBC driver supports OpenTelemetry tracing. You can configure the OpenTelemetry instance + that should be used in two ways: + 1. Register a global OpenTelemetry instance. This instance will automatically be picked up by the Spanner JDBC driver. + 2. Add an OpenTelemetry instance with the key `openTelemetry` to the `java.util.Properties` instance that is used to create the JDBC connection. + + By default, the traces that are generated by the Spanner JDBC driver do not include the SQL + statement. You can include the SQL statement with the traces by adding the property `enableExtendedTracing=true` + to the JDBC connection URL. + + #### Example Using Global OpenTelemetry + Create and register a global OpenTelemetry object before creating a JDBC connection. + See also the [Spring Data JDBC Sample](samples/spring-data-jdbc) for an example for how to + configure OpenTelemetry in combination with Spring Data. + + See [Latency Debugging Guide](documentation/latency-debugging-guide.md) for more information on how to use these traces. + + ```java + TraceConfiguration traceConfiguration = TraceConfiguration.builder().setProjectId("my-project").build(); + SpanExporter traceExporter = TraceExporter.createWithConfiguration(traceConfiguration); + OpenTelemetry openTelemetry = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .setSampler(Sampler.traceIdRatioBased(0.05)) + .setResource( + Resource.builder() + .put("service.name", "my-unique-service-name") + .build()) + .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) + .build()) + .buildAndRegisterGlobal(); + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + // Setting this to true instructs the JDBC driver to include the SQL statement with the traces. + boolean enableExtendedTracing = true; + // Enabling API tracing includes traces for each individual RPC invocation, including retries. + boolean enableApiTracing = true; + + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?enableExtendedTracing=%s;enableApiTracing=%s", + projectId, instanceId, databaseId, enableExtendedTracing, enableApiTracing))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } + } + ``` + + #### Example Using an OpenTelemetry instance in Properties + Instead of registering a global `OpenTelemetry` object, you can also provide a specific instance + in the properties for a JDBC connection: + + ```java + Properties info = new Properties(); + info.put(JdbcDriver.OPEN_TELEMETRY_PROPERTY_KEY, openTelemetry); + info.put("enableExtendedTracing", String.valueOf(enableExtendedTracing)); + info.put("enableApiTracing", String.valueOf(enableApiTracing)); + + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + projectId, instanceId, databaseId))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } + } + ``` + ### Jar with Dependencies A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). diff --git a/java-spanner-jdbc/documentation/img/example-aborted-transaction.png b/java-spanner-jdbc/documentation/img/example-aborted-transaction.png new file mode 100644 index 0000000000000000000000000000000000000000..92a5c002f0b992690fb8f07866c2b9fa656e1481 GIT binary patch literal 486601 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

    cBeC5a8kIWsiKFRd>5G*Hbx|k6 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%0D*w4WO!_+;;WL&>(b&_1*6 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

    a^~Erovrih(;DK*rSYB*R9bW&WM#8`D$ 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 literal 0 HcmV?d00001 diff --git a/java-spanner-jdbc/documentation/img/example-gfe-latency.png b/java-spanner-jdbc/documentation/img/example-gfe-latency.png new file mode 100644 index 0000000000000000000000000000000000000000..62f24b48567a890ea5fff3d09c858fdd3e4981d9 GIT binary patch literal 480367 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

    GFUP#GP`#`XVfd3u5r*z;*Y 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 z ziro~aH+Qxwn|nW3I#PAA*d$S;rQ(o{lp>&XX&_hU@;zEA5-Abj)L$*fK{G@c8nzAH zUu5l{@&X}l3sbZ;tUbVSb+XYTKDOsD`o#XcQhnTA{zrBm0Nzf_$|BA%{hW`w_(+~i zu@SI5-mAzYgbd%gi8C8?P+nswUj)F`W>AV^R=Pnr(e66vVF%7WR7D*dv`;eu8E!mN z$u&t4!+#bE!jnwHFlJDP(bD$noTd2Dq{N{1HIL3a+{K@rCGei@dDusyj8&P3t*|LM zkIBrQ+{ie1b4O@&s&Xv}$PYlS~qtR}cAJOy3-sO@o?~ zSS*dX)|CmwjWhAN1gtL*dT)Dy?2jk--z3UJtJ*}( z1(-9U{YaN&MOqPGuJCM>+5>8~7JuHR(6?An-!$aKb~T=c@1y~;%kuWfGPoVvk4)D$ zhSqVouDs$U55{An8~`J_Ht^NyC z7dBqo9#l+f7B2<(c#&(}KiL1Fo5Hd&s09(~O9LW)ETstfrL7xe+0hJSTC()VMnGiN zh1v!n$G_~wR#JiTqy%vv1Wp7ITW{(?KxqDU!Icn)SS%xSXdO*x!P#nMt;eeGp|UZp zM;#owa%T&dTie-^7YDX(R1ZDxD%wi9QzAqT>(j9_#f&cA-w zMq1bd#xzLjRHSBwlX`~fiBP2t;B}qPi{GNyp|1mt6fWy-oSFL{g!ds-*Ha`xKpZzT@~^j!M(@w8U--(*qN}$@EE(KPc$* zbmk~`Q@I{p-PmR}m&i!yiSeE0oSPI>Fgf*lKJ62L_EWBfn2^;0_xURxQo1;KyUJ&u zxEm=DoUUlRZ{9v=%P41lag;I%=Ot=kJDWyuvqm}6FzA0(4p2=Nktto05Nm0VSdCi*BB+_N|{cg4R-Cu*Nf`?|6iY_?RZ6{*xHT{Wh-RMhn z*VO(1i9yksuLb$1#JZ!GUd_$h9eh7{zI=*7$AW@%O?umbE>(dqOW9j-{#B9!2@GZQ z2H2@u+yp?f;{vOT1)WnxAC_r<(2YO+oFyLdfYbU_jV1ucls=1>djx-AZ{cy>4qUi{ zt>^Wv7~GNqRHYm6)~kQ|{J&1Q9~33gXgLs_?iMKeEg3@kk@GU zE8B%G1LET3E6!WTN2EFvauHPJvF#zY=gV+SvpM^xwkVQ8WxIOo^~m89 z0s*lvonBw47Vusvjz0%bYa=#u1uA#|>!NdFGwb^e$9w)c!CS7_(kE6^pe*0tFhxqg z*Ks01fO8P2vMyR7Q#P+8L5P63R)RD@(4HDe#)dp zcACdoV}mE!TuqNoqL)TMA-pKC8>DRP6bje}=Rpy8U_S(EI^hkuKUx#_p}90RGnp)F zYyOXrkP|DvbtSjlMWYe_nZ#zm-pR~%(RvnN(1^Y=?3LxTf%fdotM99VJ6ORk$|y@X zo@C3C#&2eTnlZnmiNn!&pJ}!vwt~1To)sCEHlp01uayXsJIZ>6(`rjOO8F?^R=h<7 zmXfRo^ck5zl=)Dn^}Yq{DyV|!Ou=Znp^BF_r+$If`xCw#tT{;MsoZXooQcpS$qPWo zNT+%-f`()z!tt&Go8%?(ez7=*7iuv{UuX!cmTAyZ);R{;`p+^D&nSseHeo-rtl{hp z14)w95^7KNHSVN~cmf?2+v!fXtP0%^`E&>cH&8%u^%eCvA~U`MWF!_Y-BT=mQ33$F zc3_w}Q6#y%I-9m1iR?|?Nvu!v8>O_*a~$iHL&llwzMrU$spxl>Zeg#aF_AWmAyC`d zF-jFGmVpH32>Kd7Ap%v*(>w*Hf#{M|*7fq0?UpVa?TF76`|2#6f8gQ?m8_UkFJNm2 z9=|W(A7$kdVdtX2qCuE&F_C@X7P4S!^?b?WqK7pm2eDh22$Baahz9wExfR?jN*mqU zxZ0>qIA)nOTa4Jz!(cE(cu}U3^n_kpO|su4=t>N&Dz%Z1KPQUR44kNUmTdZw8DK4oi(@*s zF%Ks^^k=>WMoUcp73%kHUc@q=+3K)k;tXh?#vxUt>7Pwj`VVsxSkEs_-s5y?bOgNv zdV_z#0b24^6|$l+ZL-7O@7W+RptB6l`?uE;gJYI2u_qKPZM)ds&d2RnOs~_s&z3S( z3{xI|+@rIH8FaMXp0Rm6)AyvbJcRxv_w4(JVWPbkjHCPzilCYp(|iu}v~I2ro-~bC z7`76)nGop8w0NNiOglg74>8)ZF1`0OROj}w+326KUqC~3Y{BfM!AqVMy-|ul$|c)! zsitxMZ+D~|?Atxdw2wBBd9FI!l1qO7#xlzGrIP)J_flGUs7AIm4XHMT-YJ&NgUxWe zyuA{rIJNByliC|{wsiK_4NceHaN-P_>V-?;*Xfm`45rEFlC$uLgd z!e0kuW{$+M<^$TR4cAX?X=uEie$U<2ew}%PVV-k|X>DmK{M>4BXvKuK`qayoY_)V% ztA}sp#qa-cYfDZ)uh3gOmY$=^JBpoY00nGb>%I^u`X5;-G2K!dz-ro(dgWOAik=P+ zdY5LwrNtNV^daPrf<;}*W$qOoJJ^ZWl}W^g#oMabg}UW91UX~wDvbm>eU}<5JohSf4*ZZ)Aib3 z);_M%yR+#3qU$Z7qJG!)Z-qeyM3|wwOB7JLbLbkBlx`Ii5Tv_1r6dKV8w5eR1q2j{ zp?j1L>3SdbIcM+Rd)EJ~HOn>P(lyTai94?QbCE@EW;_cSiM%JG{&<J*}Bj%$qoDf%iSpRAd#y|2k%Wv7|5ldYq2ClB7m0 zp!{2Rh3W^=W1p(~@}e)c<)89fJoRi!J_@dpy`R_obM4uvvRnWo z-7irpWu;$J#9#ieS}SP#Y&oj17x0p$H(%sIFaX(fD^9J$^61Wcn<#$WmWesNO_ ze|5V3btmS$5(H1B`=wzRzSuad4w+`xy{tB3+x%ISH-^@GJj7;v2(LLw8v-L z`OiE}W_a7~Q~8kP7?CEf$ib<5^HGDmjxt;%Z=1O8n&yMEw~=||mt#c(BRln=zJXj* zK$U!thxRjDslU=6@3k~P9>)*=J=o|OVL5cnbNsP$RR|LOd2RFA!;Rxo+r4|=1x4rQ zXA%*gHfwgbvfe^8emLq8pl^x%MC)(*n|>UoY$sHC_ybv>MBMfMc4$Yu&k-%xph$NC z)&0At7M!=1r?Xl=*>uo9SW_A{^Nwlu(>juQfu^Fi#hdA5P(aD*>UG+PC-C2WIFNLR zjezNaWPFEd9M7!tO!&Iz2i<^z%%c4-Y}+krk(B-c@y$pxp>3yICM-SYab7j*8ne|E zx4$}9QiQfu;lF=a70BiZuf>GG{-6x&L6f*k{DUP*QLmO{U4UXksy0{#BgvWWG*{L4 za>K-e_Jz%T-&*&hyDt*Inf4k#5y^@9+kh>-RT@CR-=c9%B;O;?Iu0!b(Tv zVQp;~cZ#BU*XY}VZg1V6N23JSOb0C0XnFxOHI*tsBWu`AiS{Rh%H~&1UCsu{Bu0YA zv^>el)qqUP&X%E1v_{`!?gBaxUCqh}AL{xwPTq{VK zBmF%`cAL#Z9{F9ag-YdpV|5{IE;Zl(LrNqi3@Q)r>2o=-`L9K(u)t_eZ45}G5*HO?WyK4+tM-zjh`zvnJM`0~Q<1M)1Y%c7)y=FVj^2h-&;wBXeGxni zZc@vd5NJg3h0M^&!=40!Qc6vXyQqhAjH>3C929SRibBGkRTmg(UPCb^iB*PGh6YbP zV3w{ELtyWO5mx@9BuP)_m(ixj6cgLJ&P&wemY<%uM!Me(V~!sjh|iUv zj`5epFn0c`cTr#|z|RcF9Ybut2vEuKMPvPyqb5pVz-!D-8AB7nx!-ecetc*=GTi0 z(9NP7@EemC&FIM*v*veiea82NM_4@F$p0`rT+R_fU|b|;1w;ML7EBAhAel0&%BR-D zA+-r@oSsO^a~g+^>P^LLe)TT#%^ghzXlx&^r@;$xNkH1%2|EgtioKNlxq1dL5?LzE zqg?Q;_&cv+n=!wzevs#&JEx?+kUx90dP{Vh?FnA!B!f^Va6z#e%~MMVmH7iWneQmt z?`*|gvhMeZZ+=7ihH0997twQ};|o{bm%-nk{>2yh8U3<1HeXBZu zdW7B)1>SxYF#nX!RE#n9m*DxcKMT3}F&5njWRx5_+tJ}YF6tY=yV4OG1W>NZa*fEFQf+e7ad4c8Ccvg6w zjv8W;?=>l55vh6qqDigQ6rub)x>->|pKanFX~;j{ju1koK(i#8iIhrM4$o0O;!ekX zd3Q}|VPr-J*u*^;j0N*mu&_YkfXw7a0vs@B7;t$V@0F(J$7x66$1Xct2j0z1Geanwt2Hzk@!v%1ez#RHwps)sdHg zf;r0|@n{yix;OR{y&MuEg3bFh{u6->P5Qd@9;x>}Ngi~w*IlknY&l0+bHt$q=B$z9 ztEbHr!-51hS=QcO*7q@r7fFa0PL38eBr8=BI6?-ec9j?uxy%A%6ta3&JYCXI@4{`r zQ&a1V6loh)?@u&qjQ&G|+8K04jn3bQ{zmuR#zqI0bpDSP09RefgdaCq2(JM@N_?*G zZ^&rs=@PH3N7d5{;foESxydF1$_XMfilMNa$43<{XZ^xCj_Z}DF;bSGmEnrw4-ELQ zfF=yjaS$8Hs&HPE>=g0Cyj6gQnrQ-0#>-btcpN)0F%6D>JCe$+MXF3ppS>w@z{sAV zERBsdgu@g4CR?+tH@%e%#>$Aqdrub89chSbPQ!uo>WvX>WKY$UcEQq$22I-*A6-~p z$(aQ0k0ib@9I$Lws?~w?_MHVDL=O6tK8Daj(AK$VZ;gcm$hS)Tg+h5La(l76jz}iOm9J{Mr|Hi*=}+zy z)RO5iIJ13;xWy4P0U>cSbNG=)vK|f%^ZV}?u`h;Z_pNT<6-s|-SX-Sk{d!}H35XTG zY!dY9Dldvu3J&>hK3$eQVW{m7d<`mrMz_(sMg^w0dnB5%+By)=_A8|Hu zoaM_ChDnuUCHqPAU+r2rdmG1d+q;X(FAQCDu)vQ5{q%wC%|cOF=}yO@#Kl1qBF zYZ}-0Lvt;oKACSM~(-Y zs`s?enUt@%nh68fGu!(T$S+Xg7=dEN-t6&j8{bjC3Zd z69;YL#lqyP&i#Jz>}R%R#~p!O_?rdQ18wbuLvcNKT(*1o0Xco&e8=y8bl_X6#ibmg zSYt#jG%@j{K_fPL^Bb~VTR1t4k{2Cof<0fX#TQW~0$Hc2jgw^j zX#_ubHpYn1%2Lp8Yj}@CB>l-Vn+1H^?!?^CzsDFc&v(cVGZ_rnhKe37D%DM7Eltr5 zQI1ROh$#u+^UTJ7NW`nO{QbA*LjIvt$cP0 z*OAM@P(ka;*4K=H~-Ey72jezZg`-$i1(UbCW5urbNUQC&S3# zh%VW^9$E&^x6AVGBsinn~%auOarWEwqiYRV?q+X%EDn2*%@ z6Rsi9_xJ=K)&(g!M;P^XtdURLYNa7{@!oszC>CaRv@<_HD+rxmigs^rjNddq$TquY z!FiW5S7yAzd3>gjk^O=yOg=DRL-!zDpSj3(d!a_BK zjmedLVb)8!-LABJ#j^1^JbL`G$4Z00iFz3YIt16S>P}){p4B_57nnP2yv163cx`OG zHJqCKWm?C$PGO#y*|gfFdM2>3YeG($9yJ{pQZ?sf%G$M?q)XfKJsvMlfuopw z&tncnH#WUpH|{uPfvP~647>0gA-b4kpga}6qt(%-FXN)R#tS}yoPa8In58rxFEy(r zT!lGcKdI2`@VzOO8DpXIPK_OKIP(AuiMvC$Nya`P7b3@W#BQSu7m2v9R0~ufgl-C? z9g^cno|>h>f&5Q|(s1%N5d}HkjAtmA^l7mLL~^027p|VHl#y@Q`#lyKu?J%(&gTUhtt2^8!dF7_Y!MV84 zaHgN5&ju6TVm<#k-lob>wxlEzocQ*NF@4}p@6LPyIISWW+l!^H_>W?We2DEKWi@n) z-LRc>MHgBVe&!aMBlf~ZV%7k2ZbAm)mixt-T?Sxw$h)^SP!k>+!PN3hml6Ktq5(Bv z_{G7jJS8xfgWG)h7I}NTa8Mk5=@ZprTSNjC$2ZdxqSR0DtKtl4a?W?%7ah85CCqYQt09m+`0*KgeN3@<%`G$2C%^TG;KGXqF@k3bgawwz z@2~NkZdK8~S|l^GPjDZ&{C;I$$)l$i3XWF2yifwV*II)X-|u-!jJS?Jg&6IT#8hkI zL_oq$9uQG1JwWI|$>6_2aLAkKC`<@E`?OdscgU{?KPn~8@P>Ov@DEZ=+-;%WAhO3g zm+BVaaAG0EKDU4yRb3qn+K%Q&pL4g$8vxiw22p`o7a|CU^T3nV+xY*z-w>wL%*YjR z?-^Q)nu?EoI!fYtLX$FdZuy3BnUJc)tjC&#%BSUtCcsZddvwtQl~L{C`q%?qUQ2WH z&M!i`0p?5@%Hl$qUh>t>lV=uQhY4Wrs4u)TAh{gculvN*Ni21B0Q+h=V;4W7a=}{Q zgL|{f)>QdR{gI})*y~vG#~sZ{U_VLm`Tx**)#krC41jOFU-9(6;jv+*!BNi%O5S%< zccn?^yln!JE+nlR7IvZ<12&5L9wR=V{olmW5X<`I_lvjGng1no&A{9ODtp(lDnflm z_&YjG?VMB#=}0nZt2fzJfP?qw&IbY~Mu|WJ)?;ZUvE=jMV)s3r3S)6}W&7zs6Fs}X zU6zo}ay0*KwD)eaWzuS{gDPu4$7z?C{K6mJ6zl3a=4THG#SJ>vtQj3SZSmASx4H2O z_EH~P%n_=g}&*^_M&B0 znF4B2On;MO-2CPzA-}OpIQIU7OFt zv^Z?}$|ylE7-SV(ky+kH`Y9`TaJkeShGOW;t*Osk?6e2wRRCTy{rAtP>;u8z$Dj); zm@&fme3JsZ#JWl$5=PIy(8eA52&5e{D>Z zpu)$v!UXs-h&N=sdL?Kk;L;Q`@DIC!IPSaYRvZESAOCA#1}^goOZM7xg4kGu6dV?k z3Bs8%npR@Qe}%1%;o5YzNrws3ZQBm z!ltSPA&jqg(G23r&quPv;n`R|oCbAx;yotV{PkYS23Kv-*^^1l7rsi1QMlZ#KXc6cQN}L?MP7g{n0c9<65}{Wv>~r zdVR9VMAi@4gwCI2HGBV^*8HzGA7yj;B6FI)Fl4q{Zje*kXf1yWIbArZ%y~-fXKBxL zK#jtF%smLjWt`0Eat{s+mol^$Vsn7;zxc@v*l6v2VOY=*H7m2;gob;M@hPsGWH}{n zP1L8qW?_#x9?KA78&a_kv*;s~A8$p3Bu1(k>w&Q<+6H_TUC1F2e}CEZw)1h_oP0cf zC+0B(13V=!zk7f0Kg}1~d*Xmevk0delxBz_u+A5`myVtTJp(kgIy9-#`Oi}I8l3w3 zHBQD61(R@=GJJQ>BEKSx1{Tw013SRDA284y$d$!bv3!9@?PB#1Kp?|1Qwv(ueAU;LdOyHz!_>b8Yk51QDLT+ zVUBuBg3C}icodiIkyD5irFLyHTly)1i%q{0`YB;2_rN7WPrnwC<@<8&z3!rnLI}P_5ad-j{l@8uNucwjQolq zNHX|-K<*Pf&(_T!jMR5)+~8U~@>+y!k98`iv@Z6{oH8NFK#`q2eb8~-JpyYKvLRq)vkoH zbj2)SbX9_p8j^z-4PSJkm>Y)AYxbDo|y6Ed0qu93+ z{1@NFs5*n56s=(m-{;ubqqAkysj*f=_gZC(l#1vU3mmrmrvmZ6wkk6dJzNW#2@Xma zHC%Owm5GrRq9K%57$A%C?7DAf?ePPT#HR}PMgQIHF0c!ff`RrB~iv$F{R$y)-`tTel_AG-rU)T z&Bf~@P>Bk%kN|#1 zJp!)Vh7+zCcN}(yEUU8}%O*|PA{m_gPSphDdQ|*`P-{YKpf~A)qWA884^G{lKMyA3 z%wo<%qb#6>eZNBkhp*CCJ@iNgJc4S;`qSbG-fR}r)7kEF@h$d+i}d6OT| z-7E^q5{9AhUu|Cfb?*L<4ZLH{1JZcL7`7l-DQ7#LUs|bPI089SGE-A2E!HRUE!F#w zf9^Qq~*l21LhS*%OG+l*m&d% zh&Z-P=Y)Z!0b4J!#jou1+$ZJq{|TvY!~5v`3(fs5GPScwL6q%Zrf^fuQiE$b{M~G2 zn8`WAx=M)TYV2#yyzv}h%%0)QNQ<4I1s^Z06Q0Ry8*VZaX=#cpwxRDn9OpT6 z_6ZR*j2sC~Rjm;@eiCH)P}~prEuuq_dO^ijd&$72)Z4CHc+25lM;8IeX@GG4$0;RT zaN%iWJ^M{D$y!8#uV2JRP!lbnGn*5Itzs()S9AndzC7Iko{uv17%d zh-+*~uB(1_bCxw)3^kK7_y@Ab@WJ4P)1Rvq%l}u#iJ+&!Ae0V9_UA(*)*SPZv!OXU z0p^bdE@6l&2C6|kxo%js>Ef>r2ZyQ`{j4k`K9iL_eTZ%woY!daYCeWqC6<6(BLpv` zgORUYKcTN9hLatnENv*6u}^8dHa(3Hs(|oBE1{JIpmd*c+$Z_$g=sg*D5PlF&S7YY zkQKT`h3BvJ)n&^LNQ_^AJ_ug=FjNSJJl&Wn)_#yO``}B_PGDM*Sa*Ki4wJfW7p;WT zr=4Rka+~=y<(_L)v`Y}d>{nOU4n`C0s5bN?GpgGY)I=un_xpky6!>x1umZ}!HhoS9 zCrj&tb{wg~cptlvd&;H;9l&hbz)AQjEca2yh?dgQ6$2ARh+jlM(o&!^Aw0*8&XHnB zg+tv8@?n`;!IG?$F=5*~nG^o5B00aG+IJYiJ-Jr_!NP1mjrbkfk07@-(L0jh_B+Uy zbq+HPU#@wvr(FW$dsN>*rZ3w;?eV8vFg%E0rlRy*>wRZc5K#<0l$)?CzHcfJT(?2t zInN`{13d427oTU2=FKlMtfx z*B3_%^xxi}B+`x#o7`VN3I9R$YH#M=U74^B*=+cK65m&uQd*DO>W0*o$-w2@0?94+ zJcUbF6$GbZ<~`Byau9CyMA3EXE?r_6Ly`(#hE{k4`UUsPZWetaOj3Q%_l*U|e1~@N zU42I}q}%8Ib^Na&X5&5SlfT$H?c&2)GFg_qk5wVvZ$HY2N&npx?YY}M*|`^f7NBkH zC8>zf*Mex$Obf>4ly)Rh`n5Y6w-D^jlJFiYTHNf&B5*?dhubdyVtQw20Kxq^mb)ZNd2f2ica$}mXHgL=zMI3~w#fVUaiTI(a~hAz5i6x8(clUg~`k}!~(YC{vq@T`WK{ZN+SIPXgrSgpXYGEnu=( zSdv;K}-4`?_L5{!qS!sUxAppQbVUPF3Ate!9H z37Es9V2Z;%FGgU$7wn`83D-82(PuRjO?D_ASy8m8QDIk+UV3Q93xpiRMEL#~ z8ro+Qm>p#Zfhq70XALiFMZNzJ@z|kk(hlE(8qeCgCi}a?nr!hp-arbsE7iB!fs5S` zr#m0sxgz9ge5HMcjx!r#WmyIt?zC}kUYX7e8n`W4e*ZhQ;I`aiuHHSbyXXC_$2%Ec zC4(tUuWybNFG2%d!?H(Sz5}$UYvYPhZ5Y&gW(O?n$&6pJmpky-@b#~n7T?`->Uec8 z3#Di8fZR6>Hz8W;P26lC6mTiOeSCL=kg;5Kr@pNHDf;1i2u~4&gjk8Cu{UiXEU2kF zGUG{ewu$l|uar)ltq1)3n@h$^4T--|vf1wP``23Ym^^=4uemyo#l?aJyAh&{u)D=BC+hY3JGL}~oHR^6=lU>9r9@D{W zAi-i;G@d^NJZ%C+<^7_bG5!GNtp{^*`9t#QGlj^Y;YMs+O{KWFgO3#|JA{gyP#lVHnL)JPydW!WNF>T{&9OePaGB>r%uR~4l7*=MeQ zLj)*Z7?OL|OGr~)ueH$dzkJ8wV9E7}EkPe_Koemu&7?-H%cGt1LouJ0J3IAfhZ|qd zF?DtODB4N`C=e)MUNYIN;>LB>*ot;Ye$$KC5)JhcfrIssUM;eLkts;3%` zH1_`rp8xY(sXLH}Oek)sf;2hRSj*WH5cJ~a&cEahy@g)_2Bm&Z2DPjgmqdsqBS>g+ zT{3Vrg(3rzl5*=l4U^#C&LFVdX702+KiayB{wN2$h3lIGlU1{XvO0>{A4la#VPH>y z{x4AsSIZM3v~FuRGC{{BN!`Nvy$auDW8E1V(sj0FEpyCax4$ zmfo*2a9y66Q@T|8mT>P=@qPodo7yvpOqS2tixe?je4nP1S}@_OP^@vj!hyvQAhROX zCOHvc>V9Nw8 z*CpAGa17tp4-yG8cmz>9iA$x@a*%H7lHk+M_1bN*>7|x&le#t?GCTpoJehODNk(=; z3kD&EB64%=6Z$E0i4n4Lg{ChLQSaqFwf?l*z{hEG31V;}auf% z5Xg?lunq&EeZh&C^F$k38BT7u!!5>rxlM@831dirxOWiIa1^b$M;AidII0h=Kc9e; z1CzUxm|)ef(;N9e&FTLv=YRc#_#Q@=A(2Y7B(o+%qO*sH$KU4`+_3EKajtUYCIU&x zO6L7PS^!Jf1E_^;Lc(q;0*NL4Wnr4RW(K&=o8LrpY3C8uRt6C5cfG|et1Nz_{tXca zfD7**U(%SwTqjiLDB!sPU`RAz3IZoIH5`iDs{ud`nWNaU&OIUw|6c1wL!_SwwTcB; z0+i(xcmDaA5e%SU2wOG0;?)wi-btW8HkAv$s4W_f0RIcA#(y2%B+@@55fWN03^~-A z5rV~iPt7nN#|Ux<$S`-#F~$gGdj(rS`PhEYN^eN#&4v@PO})GS)UZt`BrLFBT8nRw z1gvnK5*^NCA5iBLqDx99CurY=bX!0siQ+WmKIT;B(1Tnrc0*~O;^<8?{G&!NoV=Y2 zxQ%|nVCVsrZgcbdXX>BW&S*=YFHN&7WN*aieKT=A8oe1qtZz+^xz%4Ed@Cm6ak~!_ ztDg~iDAVaX_AtICH22OLB!FgEv~)NaOwe&>I00V(b@DYdra6`ykH&%mMqM(eLH^tH zn$V%o_v(7RWjvX=mJf5F5%O@xj>v1z<+){#&MlzDc0m`=Nv8|EdM`@mgkhlpW6<@P zQswJY9gk&4b1TBN@;CGt;l#`P$8_cz+3mK;G=o8l*J}C7CO#NkAjl@i9)=GEKOd}6@VWOv#H6Xx7RCVBqmw3(Jr`ce+b zSa_lSDR=L*=xISCovnro-ZW|OOrD(4 zrd+utv5ON3V0(KEr^o{Ob$$W?lc<-cw&SEruSG5v2}`$JrsGnUaQ?xmIxNA z-PfCSdeaJ6XBJ}YOE>lDqBT3e27^oheKMm^lq`El!Qu81x2<4{MI~8C6UYD1Y$>Bm z{4VSfG9Cilm_pcN`YkQm>H`+m|Biw{r{yfad7>(?Kr(S?_h`wd`>W_FegTKAjoW~yFvQ3tpS zSZH_td^KIK@b)oB*GCH|Vxhl9^w?TN{*d9z8#*VG9?|~1+O*9kP$Fv|wmHA}^JuSk z#g#_Ig=<`39O2d`F}snZbS+HkqxEXpXVrLM*gO4C!`*$iFYf+i#|k30dcUqJd*0Yv zlpf9`{?Xf|xa~Qvp7xJ#_1|Zdl+f)rYHDd!J=RzDugWoB>O8PzqivDh{2Wh|yz0^F z)$nAz(aLJN!KEQ;MB-$h=iFY1vLdIEwai;OuyanmD} ztZv+`Q#L5p90Pnn&@z+tujF8*YGE*c`f;7U>bt@uc}k@TWGW!uI%KQi7N>~<*#2}`Sj1WeT4@suq$ znUv~htfPB{s?st9t*)SWSzMBP3<4M21gT$dxzj<@x`&LFRuSzavSyE=F}KY+@^kJ2aDiu#*k2Ph|!_%=ch*-KXg-2vK0^SiI*FuZEZF>t?Ty&7O%Nqf4bj_ zdSyX6mCWfI;!~$RsvM))z5mI4r^2uq#npngIrq7092wRsM^0_GeEjhFWu14w4_Pm! z;PYhN3h%V_x6`}NFMU(qMt=Ra~&+UF&kQq8i zt8Tty7ovp|$57eV&--|m+BG4NngwwZY&T-3Q#Kf}_+rK^IAaq9C=JozntBw6^%G<{C#3W@{e42QU?b}aNLYHHMaqr@CdL2 zzbbcYz1)>2yj^Tx={RVAV@*EZ%mV*aCo;|V8qQ96bKnw6lSFT%yykWYO0bK#HUZ3$ zs;3)r?Q?O`Tedr=S-VJE{BuLrdDEFw>Lc+IOIRQ zw7d-AR9~pIz9bd3jOB2dw-Pqb&r!=f4K;eBp)U7HMWfVeb{ef^tHBbm{-Y{?Ynson zZL~?+efop>3)@-yy0ZB%-5zg?UywQX7jeXjpU){%oeeS`yUtRsZYE8?@0!c&fAaPA z{8wKSUv=?~H?R>QIG%C1Oth|%n! zJ;V6hSk6j8iSzGu(?g}M==bAme#JT;?Cz)UjXwK|Zs@KvU6q%eJo;ItR{A8kwfkvN z`3px6$#~d0n0!@wHj-C}n`6oi|Hbw7i!eJ}%dwGUOc#8Y35W#{Lwvq5kqJTM_fzsG zq;y6x#(e?B^;c_yY1?8p8IB>D&Oen{aPoQ>F<2s`-g!15ZjYG$vsN0x2lDz`lI%X| z+n{4O-sJ9-&Tp%eRW+0;I-z(X9gLlQi^CWqH&z&Ym+Tqvizzejj!<%ED1BD@JbtXq zV4_%iAYHpW$IO1J_FLhIsy1$qReJd;!z8TMrEC>{bLKH?SiEp)bEBu&5){I=IW>!>IsK z!jycg6x14Cw~CJ)2QGO;D|@uE1aSP()m#2&(f;4dlbr(slV-?B6Jh)eUGELvC_6Ti zoZcTx-y9JynN*lBSHF*oONG9dM><*Z)VGG`Q(cW>^c>0*lJYbSkt?m2r{qn6&>6Epd>c-H&HZsW1>y17I{lJOPJCCKxHF ze+w(poF$+`QvxtACiyKB>1-s&8=P!x$BL8AJ*R449D$gxv2|mj!XDuE9DEb44gp&% z+&fE|UI?=i5O!Zp*STDsqS3D9zYqRP*YExuJFU*ap zBh|bvTr3zB#~?dnyatdqGtC(}~^&O*6MVKxnb_9pExgxG_+iv@v5~9 zwaM||yMEvCGMZZk#q z)BnGA*nj^T7XW%4e)h>yRuE(u<{fKuS?4f#3n+6m0rIQ&j<5fHx} z0QKAU?otmcXwv)?;b(iL^2@$QarXrL*tX1|-i0I$rG*xhY;T4Z!Ct!`Eax>6DwRBm z=EftHKDX<0GWI!sy7&T^iuPRbVB~+04Q-5d#Or->A2*p<2?YZ2EdXA3J--vRQ&Q3L zrot=?6B<&`-y=t6v_j~(HwBotTM%^sRjeb@z?!zE4r@{zl0%9}A68014?#%V12KiR zl8b7$D^7L`!~MJgM#N=A8oOcRo%-s-*;S1*|-=&6*Wv2BxiJt3u-ek zi+P1QhJkN&F*b7Zv0oUYvgL!dXAo6p(xq^%WpUG zCn9J2bePcdY-_cgavZxe-Jqemp~URR(G1qcR#dvLLqWp_1Mdy5=i2G}hm>D0DvGtj zyPk$~^{{lJQNMP4>Yso+?W$nB?&&jKaK9z8H}W(Vckh^bWdSXi3VRSEin>L|>kfH~ z)y0PsuE+!>$l=6T9JH8SP37=L+hV{dRkv!Y%^DE4KK}ibFsTnJa0Y;JGt-uG5&$Cd zl#!`qe-l+R>!@{}x1Rl9>lpm?=f-4*%Ktde=|jPym5QT7eFmH{H?~~qFT*?L0*T<2YG_Cm5ki@y2E(^wod*feS z?R9SlSrCZrwq-n?b51Nl1Q`JW`3;6(@|04*?l%IVm8WbO7JFg{c+#7I9T64oGpQxH z5+|F{_Ztvm!ox#(C`=}W!Jn>^Bdx;Mb&Q2--S*7cZppq29x1UyRX+x7cv8-czOZP| zC|nI_AuuuYW^>5(ARY&;v9ADk_pii?k=;Hlsjx#Xf#j;EsV#zo4_a&*?C4YMM1SiX z*x_Z4;7)^p+|akd<#1!dwPFz|1gfN&dJ!*;!Nuq%GvtwHNf^c$#G!cmodHn@-e;=v z1`dk_LTRfgRl0wNF#pdt>=2Bw9OJC&pZPI;N|faGP)9E6BS~GBKOZ|wrgLi6zbGqe zg;4TXS7naohtSly?pt1)ZOt8C5K;Kwa#T#cg&XLfVMB?REa;$Y;i=iyUnNB z!;9REb)DX^%2E5P_Vsagn~It7F7NzVkO+c6t8`fD^X80;C~GqZSjy#|Ad1;T+3S3L zrtf)pMD45JRHk3w{mevSpxH|)<(Z3dD9x)2g;vye4Niv&ai`hx@mlHNTAObgk>duj zAA~0er;A=v*w$R*k8jgyzuM{fQ=fQ*6WQ(`9)tuBrCjB8_&jlmURAD2s{Sts@~;|W zVJqu1v&b9=muvvl-QI+dct(1xWRT1b`C@*pd>2OB#(}NwcIF zzEOG@`TCbce&;)+k_{T}+MeL?+*Ijo;~gPGS!H-7*%x zS5{jxqUZ8wi??U*J*LD*)K;fV4gfZW0s(-h594q-6#BG_&^`JP|D8<)<=GEyX zNN6hoZkwo^wi&O@kn?SQEN!bQsaqvKUIj>Ll1hI%m<@f{Zs2M5|p?Nl{nl^Vf|ChKyJ{XusSx%`H7CTwb9lb|7Sa00Dfy2I@P7wcIU`W!5{MjD;oY5!?8~!W>kYRN ze3z%k9_qJ}?j3+EWaH>A<&@*Ou1m+qp}@7t+$5^9?>^eE`htbS51PQJ0?WFtms}C= z>$4wgT!uEY(_5A)Sz4oKl0w6C*Xyod4=?VFZ?|!bo3&9JG``G>rknYtoWdjOGeSM_ zH&1u_<+*?w7pbx?K3+%+Uut4 zl359t51w0+AZsyNUtx|yygQot`rx2;bhUDQylHX%y}#Um;8f-?XWemr#n4;3nlqBk z1R`71A}0@7t(Ap@-FJbGAY}Vhj$B)Xz7~-HsV&fr`D0q(pWHZD=-@EVwxMn!BdcfK z;6|6rx!n#SZ^sO?stYO8tLm^KmHR?u?S1yQ3Y4J*Ck%v6vOzD7%qupK_A5}3f$qA% zS*R2i6FFlh6^=BafA8Pewm6WPGz=3#3Gw_EKC>^!(lME*#?Xj1KCw5G*O>=8JC@|V zWDA}@7LBUk5)-L+EQagx-r2b{5ZP2 z$T8Tf)!6zQ)ha0{nwKY<8l2D~KWK;P?b&N3L43*HIc|fXci_bSHMSs!*kZrtl0kgwGjwFoKT|#?3KJ%bNwL@qg_wBAfOoqxQ zvAXpT@Q9~@r^9BkBm<>+D-Hu3{pUwsDA>ULq@2%IIJko;<^$mt@fl2;g5??sHQ;Lz zy$wtLc0%a5@>L*!=g9Lky;wc!o9_4hY!x6SzmB`-UCeXZ|Ln?XlSZ@obZ zJej}Y25>*rpJt8=xSv!7OnMQnO%Uba>5iCI%NDW?mSg5?9OE>!Bk%L>_mY-&GfaWL9L(XdR)14^xR$>VkDdQ!e6=h1b#>lXJD{Fu1_Mb$DQjT@OxLzL zn@W8++z7|Ec!6OitEt4#yt~Ijv&{-Letvv9=<-wJT1k^Bn?y~b;#rsoraq~ z6W^x(OmWDs7K*27iFrNVelEE|RKd*hMUu=$w`aio8@npSocCgD z7HBiFS+fshd zr`221AeSiBU`R_g>q+3on^Ow`6aCAT!~zqaC`KBxb^~_uH8;QaRxYpXTpk()j>0?m z`KvEYUV|ep+Jfb*CyTrks>_C!oirJ_O8gS2m4q+e-VWOPfaP4Kn&1uU$#SB`CS<7V zponJlxiF0Y9GsbB;-F3WwU>V6X3EldZh z%KqXNLxt(sw*4F^oW$F`SB1qZ9snK85U911t({78AX$`0CupDuX;6BlKRZ>au4FTj6Rh>{X`@oDS^jM;LZfON*D9>!D+&mkNTEi@iM>)fEc?N#HRezjE75zM zPi8IH!oTZya?LZ-8Gw~%^B>O0X}9y^v}=a;%D}Z@>hxafw&V?fEIVRcCK?-#Z+72d zzr|V8!#KxY;8}H+ae)JCfl3gr&VAtvD*)PG&K>&5I$*K?0xs= z!%Z#7oHtF#+LKXk9t2Ij^P6OG?c+yX*a@&7TYe~W6NF>gc)@De2y*i+ohp8;-LEn3 zAN6$B@mRU-RI)X}ewJSn0FkxI=Xw2EKXT#-g0xT2-oH`GbH|U{Sv#zOdNU+<`EmmH zrqp?OYoco)EdAWOG{OMx#g+Kmp%XFmw2>HXa1L_GEoSN%Fl1Yc7&l`UR!1?qM00Ak zixFjRt+IpVc0KD%RX4u>R_)Mn@DXwpXU6+&Z+$m?5B|S3dZ#)4c1oyVG}khP>flM&d;m=ZhHtUv9RZ-m)WivMUlN=@J2yu;8={$PG05M_2ZA-Ui1z1mAw@0{?u35J<20uI4bGl zQ{JQXnsJ7C;x&NiG_vM);<8CIp#e^oHltpTQzEsn0Y54R#J-hTcrsV`wW~-6>BI=l zdyX0IbZIaOuQhd0!t>ie7lZA7kq1717+ana(=f zxNWtWdr$9i6$<7nz}7BYtCeOu582&AgiMakqgJ*Q0~2C{(Ex_2LpF+6>pI^tf5owx zB9EC4fy5(-+hPeynRhVf;3}>4y6L;K4f3Um1y_npuQ#?*Vaa7b@EYjcqGgO}v06E7 zxV7Wy%M_!9qwbPbAINMB+&xtscf-#K1q7be#wiOIVLVa$3aZbO@rOZpeA@R_a=F+yw{!&XHABzl}OP+cf9z% z8_CudOCv^a&0m}@UMx4@B1E8G6CC>Jdm=6!p4VxKV!|z=ee7yj?yKYKpb+^|ENJZ8 z1X`Qni|b3fY#ePCg>tAR(EQ%ySGgHaHXzur@!Mh$PtT1Y{u67_8Ba3kD9h~28j0p? zp7s&RKD_6>2IXFKmbF7li&oU_AZT&|PiGveYesXTvteOKB6u%^nB`lTE*cy7Q)%$3 z5eLQ}$crV&s??Nn9yDu<)K9ZcvqAZ@_gOE+G&%g}(MhKZ@gq>agi84Cl^mJmJMRB{ zsk}#ESz7+>o=6S2%gegMUjF(sEZZK7pt7uI0{j+vR(CHPh%1?4g&+XqlsqNO$@8?cJH}wcNPOQt&S<#lP zB|mt|^tv}abRzo&xQ{>~022CPb^4RTfk_-mj+CMSMcpuWn0feKP={smkg@x{q7BiqAK5$(u(PpDxTw zVIKt__KlM-dXRMy#yuB_(enEWOAT*p|_4|FJ3SQF8NQex}JbH9-{Fc0Le)5?QTcI4e zVlE>_u`Dv@T{yC5UP0K(`y=G-$N6Ei5qll1RveSW_!|^ld4teIbkSODsG~2@+2}a= zVTBCo;Qmx;@!zU+P_p_GtzEz72~E~Qqru#o#WKQy2M&u!%zIwnu##kr!WpfWQBK{m z6@8Smg3tPt5!=;Eogg>6A1M27JC7wSE@l#iQ@qb$kVzr8=k9w>MWQ&*!uI z`=T5}EuGFU-{j<9VF_5A!U>?Cz!K5&WEyZ)=?72|-j<1?E`Ic-Q9X>9`P?0rN!2HP?amC+|T$0R;y z=?|gGl2mx{Von7S6d!s7l*x1D!k1AAeW{7#!YE%VbjQ`(Wp{+ruMhPVIBS=*r^ufp zNUZnxj47jis%%V0;UYwQif{i*qb$U|n?2See4=Yi8Gpiy2Fo?mzW1`Hq5oHh zRQIW7uWS&TFDKCzu74R~Ugja_syTTpW>Pq;eXP2rxditmuc}&;K%Y^GiQXQI4Y-B4 zW(^Xzr5E@2s5O6%shm|yc)qRfl0x@R3Y-19t$SxFT~_c4Z=Z3>;mS|v>~@F^T^ZD`-xPBllc;9B0W?D$Ukg?d({6s2@$+K;PJbC| zdm4JeW+zZ>{Y=y0eSB5PSz3#n#0L7!2jA#+1p#08(uBkMm1cQ0Fom>de7OG;uo`22 z^u(s{m=S>j9a{(j-w^U>9D%6CJJADi$xBh&4R0FrN}eQWSbpVKZ-8}6T2JptgiQ=D ziUfg5t<2VJ;}vTZhR-CS{P;oNTL#i6M-+H_51TUj>73<|=33v%{B-K&e=6llY-R*V z?1gMHRN><*hfaze0@11EQ(9ja+gmgh>f+Q<-aR|yh2A|);TkO}7?FfC`;Q~P9nzhs z{T081h_c4m{}@LHU>rTH>uN93p40DI-<)NBQ=~F5W}RKCb@TU$H`d@$q+GGWrzKPG zqJJ@XHPv}a1KBfLS8}Y+n3OqHe3o{N(A@rFxWzIv?{1l3B!d5VbK=JX_J*ntiFfkSl;NY%MBhhs!Morh3TmzNTB;UJChw@;bjB3OR@#3)33`y};hp8$ zr}50=94R(ZUfB}NG!{oAIfQ6{aVM(}*Cy8>zFc9V*ca{jYa6yD+3S;T%)t)e?9UUrY3II|eh}t}i#&2P z`r?m&8CUZ6Z;WgI9GeZ|sF0b+fgV96cwa`@;{Svtv_C+|Blj1LBNqZB(7wYKQ@->H zjGGVDM$TKch7FtRJOePQ1TzxXj8hWSx3OluyHdebVKwvQ%LVL@R>m;N#Z1(_{Dr*^ zisiY}bvL8Kozxfk%hQ$12{xZ?%Umj_<_nX9kbpAo^UM}|wRwr{X_S{})RdHH{exy& zsZX|aYqdo7+`7}Cw;7<;7%p^Nm_F-Fd8(BxgAO2GW3sHB@3}8BIFyn)gMDLUlQw<0 zBJ^C-+@})j*fN!Sr#7JzY!4cx>#tL85IFOPAS>Y^Lx#scR9n3KYmU-NWgWcd2<7&; z7--?xFJB4gO+fQ~N~ryHI6rbt)gX%b{A_B1&(M#kv8F9I^Vckm(<`k^^_zop1xrs< zz4&;RObhB8+`Vp=)q&})P;l#~i|yS-j0W=Vi;jB55(PVg<~uc=<_7`q z1w#5$l(z~_)U5fyf)FVSCtYdWO&pC3m<;6h^E--hYbNqDLdPAb3~GOrqO_Jd`xYa)Y)ea&pHW0=SUV_#61 zAzBwr-&}PE&G%rf(<^iSSdw!C)scOGQ@);Z*mL-eP>;tNLOWL&aVWl8op<3*lCPC? zVBo5tvJAz99XT<38N!hj*ihIYR}W3Shz#_IRm+A78)b-qzB%dDXEvlZGb_i+X?G*7 zP)|f2=gNjRhuQGX%_mBlRrWId%9@oh;;64ctqQXq~()pyue8EDHR4DMB z8G7**smwHSTm{;4`j^g*Kth@8TIts(0g5lwekQb*!r}X+G$3qIc_s->Di*;v^=~Fr zyv;A3y7f%CiH+?`73c0#a?Zm-JSuHnPu|GXf}YFhHZAVnqzL^_aRO1kx9q(SBbo=< zFohdR1L`k$qT`LX*rj3;`)5cit<1l)vuJydCt&2t zo_9Cp1%)#sR;DfCR&F;_#$w_oL3)}F*<%W)8xJ2i-}Mry(oojnI+IB%wi~*rY_(`o z=HLw?-fz{uQZ$;KCrH8GlcuB-?&*Jn`k#O%3^)t-uJ>B+_J5(>d`la=8}|O%^qex| z;^4dEzvHiSik`Q$b&C!|e=P2o1o^TCuRY@)TrJ60SzCg1nx7zZE*f2ue2o#DH~nyv zsY$Q+LlG!TM<^1P+SF1hitWXHN|Fax0Sb7>wj_55n#J8d(&TDq#YLt!^M<8fBg>A= zlO;84*!gZ>fO=gX7HkP3jj%y#$?m^ij&n`~*s{@L-z25zTc; z6{T!55$pC*pE7=;_7Q3It+A<6XnqoX{RcpaHwg1nVc+6*u|spfAZ4U;AynJtuzPh zNW$o4>j`^U1tNBz(e8s|z}N1CD@{RxhC9`z_heZ4F0Yw9e5wZ9iO#$gC=LDrR7qW= zq19Xz9bXx1gidH65&h}&o6YpZOGL`QeWEAhI7@wF%00uyBAk!WrGT8Oi|CKX{!>PY z*ndS@|9?_Z9#yV6S(#U`n4UeW>gqH0Mzc`2$TME9gz`Z1$kaghK(h05C%Yo2_Oa<4 z+mu1KVe8|D&NuEZ8dVk=T$-s!7CXFl`HE|~=z`cNMMAex(LCWo^;z{HNsS}Q7v(Np zcvT47D3M7j7gfq}ijQm*VzA9BQ}h)g_cn8QBQwxXRzBBNGoJdSnYZzvI}5cd2b-w} z8v=ZJc-g-l^}rZ-yW^=(ltBWCZby1FC4(i^^|K~by_i9EAJPg)Ge9)XX4!zl)3 zFL)O?a3x4Yg!cnM3cN`}JXH#*EBz0VpaZ>~$X%*376o3Vr)x*;#weLO_b&}DXOzhz zYZkP=-Nn;npDXu{1!|0>pq~9U7o%TkxrtTzK&?^+B#Gqe|AhE#sduv=Bzv@wwYE6x zuPUG2A68Pp_vblh@AuTkruav_EIb8+`sY;(btB{t{*d2x%LP>aT^8pbKaUF}(1-Ms zf(e(+dT$2N#?L^x7Xq2_Hh}D zxC>ztcuDog0;vff_F%|VA!H$2BQ(&c*Gv|BL)dApPbT%FSHx^mT7mqmxe*mvoNCx_ zMOQ^H>;Jsl?{Jlb)QTEghrU`2+pK|Cb-YS;o_rHtO)8!2EN-nSf1A=((&;^2j(UEcZ!(%m^1VUGrA|=8xdE2r@GTR~ zitI?g@x&vGo$oc*`Q_uwB+;b0JSpzDI=T1EG}bXnv&uTJ!yMMqe{%4KY3p~lT6T&u zia96#K9VWTQqog;HRtl4F%4Dx{?8 z;N^^hXhjCQlah1qRSjwEjHDPOM{TiMT=ipZ)UQ^&c!ma~w6|}!-?(?b@RmdOvz(i* zTT7!ufw9@tT*lL(9bTJ&Nq8z;EwAtS^JNgpgWN{bk|Xzru1933kBbiANz*_@s?Cv$ zYZCiECa=FigSf!4a^&miaT*0=H}NK*Xf6iq`ViboJ9I6=5tnfznp6f^2HCWB%27@2*OY!?0mKL6U=8%U?;a|;VrL%9J(G3VjQ{LgGpE)Bt_oGxUgP>4eh zlwJjOnDoFPP>l|IH`2O!p-5H1_U?W{8DesFOwM#`K6ZNsTDZGr$4|xzVbM4|K$H^k z3Lv;NGvLXWK}2Dhj~|kX;OCtN^1t$_qylP!$d>Q2^hjWe+8GTbA*@n#>wN1o(A?HJ zIl+?k1Vq`p?48e}yVk?V!QFRPm?tqfDVhX(g`)?O9e2JJ^vSF?AM=5IwJ)7a0J4m- ziTuzQwEruntRyiho|YiPn+i+v^s^WWGbyKT|usE+IHpX+snjZk&ppCzZf^#NkL zR;kvUtzBjZrn;BiqA*j&B%CuD#5nsY9wD@8i%i1Xaaw=uRLbb0R{J^jOu+_FtFeZc zj_)|OqJIuTw$binDCL-MCIH-YpM>*m{tREfMvNu+>+jgWYxJ&$VqSR-$+QAyz|YL# z=bw$#|EroPW!O?lzyM{|LS1-kXI;QG{mXh1y~nFtcebsgjcg-hFnaZs8XUOPkB~i7A&9V>`3&;E+-$YYaB4;nTY?e9NyF1Duc5dq z_vnqfjz$M~WI7BoIljq$Shr0g+HHcibFj+AL_7v0A49)3zRw)Y*5fTPIKpG0c?VxZ zf88Zxu!i-_z272pNcH<}?4{pYkD%dYJE?H%_L_JCt|l|@(KP=p;VW%~_>p1|OVvTj zkiu?Ser#{-)T_Ir&||pFrFdz*U*jpDIJt@C>(Y5gNJSm>M7;Qz0wjyk0;IyFGq>iWU)HROUT|>gN zfKn3R(_y#Ym^PWME%~DIlNXh6kb}C9UyY3n%3H((|k|nBR6XGogTZ^j4o$#`y^8*ES8JnPh>4=&834vee z$j^f@%_qW*rhrg(ge!w>@*U0Sp6v8JykTjISbpDydCD(R(>8&EAcPo<{TuIr;b31~1QsDh_lbzyk~2_nqFKW5*g@@4`9TPDk?kkLOjwh`~7h9^uD|8e6Gn5MBGNAJCv{{TF{kFPt*QQAJsTeyeU_!@S%({%7)5weu%yB&+HkqqqPO z*%S?d@$#9$;AOf&y8I1YLehZ^xbNp<=4z3M)0!s#DmF(_5hX2T40ZEpA_t+u{=L;W zFLya>uq(s{LTcxgGHc}_@y6WM)8RgOrg~6(vtP1XpKUY7GX+}QXjis0;f$NFC6Arl zl54DEbD9e{O28Wy0}E5Vw~9gO`=6^I!;cyXS4hh?C_&_Y&1VrH@}Yg~Kk*5FfFI6g z1Se2QVlGz;k7#@x#~dDh(3Ud>A40ZRd}TkdFQN~p$f*|9OBb6CehM0b3rgW6N?X5; zQ7x{mLba0SP=)?WP3Oyj?`0FSzU`$?5~tRACu3n1Fep_b~@JWE~(N>~$G z!4zpiPICkswefkX6V{}B>MfR2t>I4-$f_<*QL$BjCW$DHXeI;NEI6e$#& zGmTJG&B8?w_X*!Y>g^``wx|)c=v1fHMt=7UmLuYXqNr)j5b32K{1Hk$={^ zf98#l&sp9I1Cnqd-a~JSd}c(bmy1_CooTDmyoh*OaJG<)V2E!xTd%hdZK7+mzFIDf zO7Cg(NW$lJ^*O=Wt~KR-{)>j`s|+JHKeV+lQ=NX8!nZ4#3gLwtv|nv=)DuW6olv-o ze2+ZFo$0%^J3{22LPh@M_?rt}zKrX(g!@3gfve1ATR6d9)^9;1TX$G~E#(lD056~z zy>!xgz3kDJH&$0jh!&>G>xNhOo~OCt)fSyn`}bQDmzwOD|Lhbf6-A1r^BdWPG2}jr zWBudJSXVSl|Fc>1KWdi0e1V2A!iTfr|8zK>UV=B9?ai!rBJ#UVNdEB`M2_X?-~I2Y z`_J+F%NH4t*MQC+wooAd%P;)-+lqGE~hkfX+`kpTmg*sp&$644~L`j%`HH%#WJFm-n`SrK|yBhyK_~{~#hmz!DSx#h@R1W#wW(K+V?C5$-VhUU)!Z%>w zeK7ga%Tg+*Qz3L^81cPKAGY;N~ zE&xnjftb3)TZ&^)!1N2GzAgpv{RkW|`b%h9Wt4I{##;tHS0B(g<$P%82-E-wE!7ob z!yEQDN6QX?WF9&NbEU&Yh{7m?{$~`18JiX8YXXret#7eWNb-)&|KVu<`Yh?hp}^j&1~by18ihaKK=5^j5*5-n=wdF=gD=!2 z5_!mSA)}T2C(N;CuOQpGW?okRZ6?7RAewE4PU@1BFvG5T|6*SNm&!CcW0-9^-z|e! z%6a|EYpsnF7xItDKrop9$d@r<<{NRE>9R7LED88;3(#yifCB6RP0!osNLLS6fK8`z zQ3j15j)Q#%s>Ug}w0tKJzu9(B?Gu;XQwWb9AzhgZz*eeG2@D&0@;P6{@eSbC=o2h{cMUZUeGm#8B$! ztM%;N^4~%oPdkDh2*KCjW@VBRTyETTt(%VIw_Y(QHvL5M6hlS01nK+L$oi{IYTCPq zD=M3EZ4-hrhuQBkS?^6Say+Ebl3>rSWq^e6wmT|RFWEYNfg9C&t_Ha5B^c_uzNIKH zO~Qto>hYUBBULVp3!aAu`>Ee}$1y=;@Ilp@tGuYPeNAon{fr}A-<3$J+vaZ|wpz@* z%fcsgHk=)&KIqSPjh%Yq4xTLJUZEq6njy;Ig=*&bKh%|i_=n$Qo7#Nt z@RWUM@w`LM<%I5=qfWnDk|R%ryfLX7c2QiZS}0jg_ZW&yMn@iX9jkdKb>o{QjNw|& z_2>sk42bDWzY?_f2*kuwzP<@p;xL#&7>(& z$f9N*jVST_a4Y5RusUX&f9YOfM`kEqLj@@bbFA|1|vn(QNU4LT;Z=Lx$P^ z@SD0gLUvh$dbQ+gqXzP8^-h`?=pnb5&IOXQ#xHx*7`MvJMha9rn9st^O%&mn30@`P zspA}pJ3r<|;S{ji#O0wQofPzG*Eb=MeHcs3d}4PC7A6&eaHTA`8ZNj+Au72VvtU=`Q5-Mr?0KfeM|lZ z619d*;P>V)L4)A1cp^GEQbB)GK|a10Od>XlcgV_s@NA?bh?*0goTJ*A3VEt6B3#h5j-(iFR3TCKqKjVS-0h5GoK_G7$%qLQP@T| zbYndmS~%8CWEhKbcyTyv6Z@5V*`tUmq-8HRJ4QX=i82+IurvJIaRGfjXtMO38$FnD zKOBGp5xenCCjekM7cg+u{vw`8lL?UW!Mjf1Belp@jr9=(o94*pmEL0=QrF%;9p3xe zkR2;KlDmw=0`S8Ocrs+1<+g#(L~pSvadixn#jo3&eM0iV6(CWZ zl~|;Jm#bT@z1QyTuk%Ur8mZQNnP1O`%gP31EG7wdd=1S(aPku*Vsls8m`XpCh`bl< zKn+V&ubCk5ZhQhy1P|-Xz6^9e{I@Qhz(-(QYUSy5Uf%GFcP)o>{Ls}l5((3zueL|=@=?hc=P8x!%GrYrrMNk-jl>ArwWIDF(|(3A35-RnEP#!&oq;t zzy;=Sp$b{~BVhp#qB5fBY_b7*-n`ys01vX5;$4c$VBhcW+u6ofiKiLn*)SSY>oame zK*ObNZ5bGv*%6+__nWe1VAT}1J821+d9)PO!ryY4v*B8eyIE5zqP>P1jYcV1E)Fl) zjHNb{-;wa7U_4~Y&rOSjNuoM2u6>uzUHM$&Ikn#5u}(~I zM#(~eUPS!!jR)TMBTp{US(&Fwd7r;^Z}pzdmoSI25zo)wLrH+jI!O3R+(CbJhixNF zZkz3XQ756*62+epcOJ%6r@_^lgur`u`MN#Lxk;5QwZ659cFNgPsj+L2c0l5{mGY&7 z1%ns+Y_}CZp16@uDm78YTAWlCBRRxvI*9Q<^ADrr`&f87zWZtnaQ=P65psfR_{EN# zeYc57@4bd%QDQpYxU7cUtG~~Wfds+(`_=xp_E26yb1~1X!`Cl~^9n{~V3NjeE)NX6FPt-nnTv4-1d@&mG*mLjy|H-kr~LSrX(SVfTycT za_-G7IUTGulvB7F-{7fTnB9}18Y$KMVB3aY5NyNVz{y8s)K6sIc}aDPZGMed;e3-9 z*#vtuuR;Dp+Czz!xZq?*j$A{Fz=4+^YMR@>ulERU9dsynNs6$qV*SEvBIV<%Tt>zE zuMr!vDcNeVeE@~7h+X%IlH!aEu8~ZeU`m;dxP87yXg(1w9ciCMA@J44N~GOo^2FzX zuV;S|$ntxR6vY}rL-|Ip&K7Xw8vW#Gdv!X>rr+aLOSkgQ`d1eVpXIS@olzD_C*Rne z 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

  • knfwwGa1aLqnWfA1MlAtfCG% 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 */ public class JdbcDriver implements Driver { + /** + * The info {@link Properties} object that is passed to the JDBC driver may contain an entry with + * this key and an {@link io.opentelemetry.api.OpenTelemetry} instance as its value. This {@link + * io.opentelemetry.api.OpenTelemetry} instance will be used for tracing and metrics in the JDBC + * connection. + */ + public static final String OPEN_TELEMETRY_PROPERTY_KEY = "openTelemetry"; + private static final String JDBC_API_CLIENT_LIB_TOKEN = "sp-jdbc"; // Updated to version 2 when upgraded to Java 8 (JDBC 4.2) static final int MAJOR_VERSION = 2; @@ -204,7 +213,7 @@ public Connection connect(String url, Properties info) throws SQLException { // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic // Connection API String connectionUri = appendPropertiesToUrl(url.substring(5), info); - ConnectionOptions options = ConnectionOptions.newBuilder().setUri(connectionUri).build(); + ConnectionOptions options = buildConnectionOptions(connectionUri, info); JdbcConnection connection = new JdbcConnection(url, options); if (options.getWarnings() != null) { connection.pushWarning(new SQLWarning(options.getWarnings())); @@ -223,10 +232,20 @@ public Connection connect(String url, Properties info) throws SQLException { return null; } + private ConnectionOptions buildConnectionOptions(String connectionUrl, Properties info) { + ConnectionOptions.Builder builder = + ConnectionOptions.newBuilder().setTracingPrefix("JDBC").setUri(connectionUrl); + if (info.containsKey(OPEN_TELEMETRY_PROPERTY_KEY) + && info.get(OPEN_TELEMETRY_PROPERTY_KEY) instanceof OpenTelemetry) { + builder.setOpenTelemetry((OpenTelemetry) info.get(OPEN_TELEMETRY_PROPERTY_KEY)); + } + return builder.build(); + } + private String appendPropertiesToUrl(String url, Properties info) { StringBuilder res = new StringBuilder(url); for (Entry entry : info.entrySet()) { - if (entry.getValue() != null && !"".equals(entry.getValue())) { + if (entry.getValue() instanceof String && !"".equals(entry.getValue())) { res.append(";").append(entry.getKey()).append("=").append(entry.getValue()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/SpannerOptionsHelper.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/SpannerOptionsHelper.java new file mode 100644 index 000000000000..9c70ecb196e5 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/SpannerOptionsHelper.java @@ -0,0 +1,30 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner; + +import com.google.api.core.InternalApi; + +/** This class is only here to access a package-private method in the Spanner client library. */ +@InternalApi +public class SpannerOptionsHelper { + private SpannerOptionsHelper() {} + + @InternalApi + public static void resetActiveTracingFramework() { + SpannerOptions.resetActiveTracingFramework(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java index a5d350501e1f..26722bd7b351 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionGeneratedSqlScriptTest.java @@ -21,13 +21,16 @@ import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.connection.AbstractConnectionImplTest; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; import com.google.cloud.spanner.connection.ConnectionImplTest; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.JdbcSqlScriptVerifier.JdbcGenericConnection; +import io.opentelemetry.api.OpenTelemetry; import java.sql.SQLException; import org.junit.Test; import org.junit.runner.RunWith; @@ -63,6 +66,10 @@ public GenericConnection getConnection() { when(options.getUri()).thenReturn(ConnectionImplTest.URI); com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options, dialect); + Spanner spanner = spannerConnection.getSpanner(); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); + when(spanner.getOptions()).thenReturn(spannerOptions); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); when(options.getDatabaseId()).thenReturn(DatabaseId.of("project", "instance", "database")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 96ea743819c6..cda51a7710c4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -32,7 +32,9 @@ import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ResultSets; +import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; @@ -42,6 +44,7 @@ import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.rpc.Code; +import io.opentelemetry.api.OpenTelemetry; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; @@ -80,6 +83,10 @@ private com.google.cloud.spanner.ResultSet createSelect1ResultSet() { private JdbcConnection createConnection(ConnectionOptions options) throws SQLException { com.google.cloud.spanner.connection.Connection spannerConnection = ConnectionImplTest.createConnection(options, dialect); + Spanner spanner = spannerConnection.getSpanner(); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spanner.getOptions()).thenReturn(spannerOptions); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); when(options.getDatabaseId()).thenReturn(DatabaseId.of("project", "instance", "database")); @@ -507,6 +514,11 @@ public void testIsValid() throws SQLException { mock(com.google.cloud.spanner.connection.Connection.class); when(spannerConnection.getDialect()).thenReturn(dialect); when(options.getConnection()).thenReturn(spannerConnection); + Spanner spanner = mock(Spanner.class); + when(spannerConnection.getSpanner()).thenReturn(spanner); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); + when(spanner.getOptions()).thenReturn(spannerOptions); Statement statement = Statement.of(JdbcConnection.LEGACY_IS_VALID_QUERY); // Verify that an opened connection that returns a result set is valid. @@ -751,6 +763,11 @@ public void testIsReturnCommitStats_throwsSqlException() { com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); + Spanner spanner = mock(Spanner.class); + when(spannerConnection.getSpanner()).thenReturn(spanner); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); + when(spanner.getOptions()).thenReturn(spannerOptions); when(spannerConnection.isReturnCommitStats()) .thenThrow( SpannerExceptionFactory.newSpannerException( @@ -773,6 +790,11 @@ public void testSetReturnCommitStats_throwsSqlException() { com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); + Spanner spanner = mock(Spanner.class); + when(spannerConnection.getSpanner()).thenReturn(spanner); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); + when(spanner.getOptions()).thenReturn(spannerOptions); Mockito.doThrow( SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "test exception")) @@ -796,6 +818,11 @@ public void testGetCommitResponse_throwsSqlException() { com.google.cloud.spanner.connection.Connection spannerConnection = mock(com.google.cloud.spanner.connection.Connection.class); when(options.getConnection()).thenReturn(spannerConnection); + Spanner spanner = mock(Spanner.class); + when(spannerConnection.getSpanner()).thenReturn(spanner); + SpannerOptions spannerOptions = mock(SpannerOptions.class); + when(spannerOptions.getOpenTelemetry()).thenReturn(OpenTelemetry.noop()); + when(spanner.getOptions()).thenReturn(spannerOptions); Mockito.doThrow( SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "test exception")) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java index b2f949e2d208..9391b52af9a1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java @@ -36,6 +36,7 @@ import java.sql.SQLException; import java.util.Collection; import java.util.Collections; +import java.util.Properties; import java.util.stream.Collectors; /** Base class for all JDBC integration tests. */ @@ -80,6 +81,11 @@ protected static boolean hasValidKeyFile() { */ public CloudSpannerJdbcConnection createConnection(JdbcIntegrationTestEnv env, Database database) throws SQLException { + return createConnection(env, database, new Properties()); + } + + public CloudSpannerJdbcConnection createConnection( + JdbcIntegrationTestEnv env, Database database, Properties properties) throws SQLException { // Create a connection URL for the generic connection API. StringBuilder url = ITAbstractSpannerTest.extractConnectionUrl(env.getTestHelper().getOptions(), database); @@ -90,7 +96,8 @@ public CloudSpannerJdbcConnection createConnection(JdbcIntegrationTestEnv env, D } appendConnectionUri(url); - return DriverManager.getConnection(url.toString()).unwrap(CloudSpannerJdbcConnection.class); + return DriverManager.getConnection(url.toString(), properties) + .unwrap(CloudSpannerJdbcConnection.class); } protected void appendConnectionUri(StringBuilder uri) {} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java new file mode 100644 index 000000000000..19fb1146e382 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java @@ -0,0 +1,281 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; + +import com.google.api.gax.core.FixedCredentialsProvider; +import com.google.api.gax.rpc.ResourceExhaustedException; +import com.google.cloud.opentelemetry.trace.TraceConfiguration; +import com.google.cloud.opentelemetry.trace.TraceExporter; +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.SpannerOptionsHelper; +import com.google.cloud.spanner.jdbc.JdbcDriver; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import com.google.cloud.trace.v1.TraceServiceClient; +import com.google.cloud.trace.v1.TraceServiceClient.ListTracesPagedResponse; +import com.google.cloud.trace.v1.TraceServiceSettings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.devtools.cloudtrace.v1.ListTracesRequest; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITOpenTelemetryTest extends ITAbstractJdbcTest { + static { + SpannerOptionsHelper.resetActiveTracingFramework(); + SpannerOptions.enableOpenTelemetryMetrics(); + SpannerOptions.enableOpenTelemetryTraces(); + } + + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private static OpenTelemetrySdk openTelemetry; + + private Database database; + + @BeforeClass + public static void setupOpenTelemetry() throws IOException { + assumeFalse("This test requires credentials", EmulatorSpannerHelper.isUsingEmulator()); + + SpannerOptions options = env.getTestHelper().getOptions(); + TraceConfiguration.Builder traceConfigurationBuilder = TraceConfiguration.builder(); + if (options.getCredentials() != null) { + traceConfigurationBuilder.setCredentials(options.getCredentials()); + } + TraceConfiguration traceConfiguration = + traceConfigurationBuilder.setProjectId(options.getProjectId()).build(); + SpanExporter traceExporter = TraceExporter.createWithConfiguration(traceConfiguration); + + String serviceName = + "java-spanner-jdbc-integration-tests-" + ThreadLocalRandom.current().nextInt(); + openTelemetry = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + // Always sample in this test to ensure we know what we get. + .setSampler(Sampler.alwaysOn()) + .setResource(Resource.builder().put("service.name", serviceName).build()) + .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) + .build()) + .build(); + } + + @AfterClass + public static void closeOpenTelemetry() { + if (openTelemetry != null) { + openTelemetry.close(); + } + } + + @Before + public void setup() { + database = + env.getOrCreateDatabase( + getDialect(), + ImmutableList.of("create table test (id int64, value string(max)) primary key (id)")); + } + + @Test + public void testGlobalOpenTelemetry() throws SQLException, IOException, InterruptedException { + GlobalOpenTelemetry.resetForTest(); + GlobalOpenTelemetry.set(openTelemetry); + Properties info = new Properties(); + info.put("enableExtendedTracing", "true"); + try (Connection connection = createConnection(env, database, info)) { + testOpenTelemetry(connection); + } finally { + GlobalOpenTelemetry.resetForTest(); + } + } + + @Test + public void testOpenTelemetryInProperties() + throws SQLException, IOException, InterruptedException { + // Make sure there is no Global OpenTelemetry. + GlobalOpenTelemetry.resetForTest(); + Properties info = new Properties(); + info.put(JdbcDriver.OPEN_TELEMETRY_PROPERTY_KEY, openTelemetry); + info.put("enableExtendedTracing", String.valueOf(true)); + try (Connection connection = createConnection(env, database, info)) { + testOpenTelemetry(connection); + } + } + + private void testOpenTelemetry(Connection connection) + throws SQLException, IOException, InterruptedException { + try (Statement statement = connection.createStatement()) { + // Generate a unique select statement so it is easy to find in the traces. + UUID uuid = UUID.randomUUID(); + String sql = "select '" + uuid + "'"; + + // Test executeQuery(String) + try (ResultSet resultSet = statement.executeQuery(sql)) { + assertQueryResult(resultSet, sql, uuid); + } + + // Test execute(String) + uuid = UUID.randomUUID(); + sql = "select '" + uuid + "'"; + assertTrue(statement.execute(sql)); + assertQueryResult(statement.getResultSet(), sql, uuid); + + // Test executeUpdate(String) + uuid = UUID.randomUUID(); + sql = + String.format( + "insert into test (id, value) values (%d, '%s')", + ThreadLocalRandom.current().nextLong(), uuid); + assertUpdateResult(statement.executeUpdate(sql), sql); + + // Test executeLargeUpdate(String) + uuid = UUID.randomUUID(); + sql = + String.format( + "insert into test (id, value) values (%d, '%s')", + ThreadLocalRandom.current().nextLong(), uuid); + assertUpdateResult(statement.executeLargeUpdate(sql), sql); + } + + UUID uuid = UUID.randomUUID(); + String sql = "select '" + uuid + "'"; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + try (ResultSet resultSet = statement.executeQuery()) { + assertQueryResult(resultSet, sql, uuid); + } + } + + uuid = UUID.randomUUID(); + sql = "select '" + uuid + "'"; + try (PreparedStatement statement = connection.prepareStatement(sql)) { + assertTrue(statement.execute()); + assertQueryResult(statement.getResultSet(), sql, uuid); + } + + uuid = UUID.randomUUID(); + sql = String.format("insert into test (id, value) values (?, '%s')", uuid); + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, ThreadLocalRandom.current().nextLong()); + String spannerSql = sql.replace("?", "@p1"); + assertUpdateResult(statement.executeUpdate(), spannerSql); + } + + uuid = UUID.randomUUID(); + sql = String.format("insert into test (id, value) values (?, '%s')", uuid); + try (PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, ThreadLocalRandom.current().nextLong()); + String spannerSql = sql.replace("?", "@p1"); + assertUpdateResult(statement.executeLargeUpdate(), spannerSql); + } + } + + private void assertQueryResult(ResultSet resultSet, String sql, UUID uuid) + throws SQLException, IOException, InterruptedException { + assertTrue(resultSet.next()); + assertEquals(uuid.toString(), resultSet.getString(1)); + assertFalse(resultSet.next()); + + flushOpenTelemetry(); + assertTrace(sql); + } + + private void assertUpdateResult(long updateCount, String sql) + throws IOException, InterruptedException { + assertEquals(1, updateCount); + + flushOpenTelemetry(); + assertTrace(sql); + } + + private void assertTrace(String sql) throws IOException, InterruptedException { + TraceServiceSettings settings = + env.getTestHelper().getOptions().getCredentials() == null + ? TraceServiceSettings.newBuilder().build() + : TraceServiceSettings.newBuilder() + .setCredentialsProvider( + FixedCredentialsProvider.create( + env.getTestHelper().getOptions().getCredentials())) + .build(); + try (TraceServiceClient client = TraceServiceClient.create(settings)) { + // It can take a few seconds before the trace is visible. + Thread.sleep(5000L); + boolean foundTrace = false; + for (int attempts = 0; attempts < 20; attempts++) { + // Ignore deprecation for now, as there is no alternative offered (yet?). + //noinspection deprecation + ListTracesPagedResponse response = + client.listTraces( + ListTracesRequest.newBuilder() + .setProjectId(database.getId().getInstanceId().getProject()) + .setFilter("db.statement:\"" + sql + "\"") + .build()); + int size = Iterables.size(response.iterateAll()); + if (size != 0) { + assertEquals(1, Iterables.size(response.iterateAll())); + foundTrace = true; + break; + } else { + Thread.sleep(5000L); + } + } + assertTrue(foundTrace); + } catch (ResourceExhaustedException resourceExhaustedException) { + if (resourceExhaustedException + .getMessage() + .contains("Quota exceeded for quota metric 'Read requests (free)'")) { + // Ignore and allow the test to succeed. + System.out.println("RESOURCE_EXHAUSTED error ignored"); + } else { + throw resourceExhaustedException; + } + } + } + + private void flushOpenTelemetry() { + openTelemetry.getSdkTracerProvider().forceFlush().join(10, TimeUnit.SECONDS); + } +} From 1e24f5f8b932ddf3334933765ebe287f488cf02d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jun 2024 13:34:46 +0200 Subject: [PATCH 1326/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.70.0 (#1657) 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.69.0` -> `6.70.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.70.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.70.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.69.0/6.70.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.69.0/6.70.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.70.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6700-2024-06-27) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.69.0...v6.70.0) ##### Features - Add field order_by in spanner.proto ([#​3064](https://togithub.com/googleapis/java-spanner/issues/3064)) ([52ee196](https://togithub.com/googleapis/java-spanner/commit/52ee1967ee3a37fb0482ad8b51c6e77e28b79844)) ##### Bug Fixes - Do not end transaction span when rolling back to savepoint ([#​3167](https://togithub.com/googleapis/java-spanner/issues/3167)) ([8ec0cf2](https://togithub.com/googleapis/java-spanner/commit/8ec0cf2032dece545c9e4d8a794b80d06550b710)) - Remove unused DmlBatch span ([#​3147](https://togithub.com/googleapis/java-spanner/issues/3147)) ([f7891c1](https://togithub.com/googleapis/java-spanner/commit/f7891c1ca42727c775cdbe91bff8d55191a3d799)) ##### Dependencies - Update dependencies ([#​3181](https://togithub.com/googleapis/java-spanner/issues/3181)) ([0c787e6](https://togithub.com/googleapis/java-spanner/commit/0c787e6fa67d2a259a76bbd2d7f1cfa20a1dbee8)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.32.0 ([#​3184](https://togithub.com/googleapis/java-spanner/issues/3184)) ([9c85a6f](https://togithub.com/googleapis/java-spanner/commit/9c85a6fabea527253ea40a8970cc9071804d94c4)) - Update dependency commons-cli:commons-cli to v1.8.0 ([#​3073](https://togithub.com/googleapis/java-spanner/issues/3073)) ([36b5340](https://togithub.com/googleapis/java-spanner/commit/36b5340ef8bf197fbc8ed882f76caff9a6fe84b6))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5bf5e74b8ff5..f40fd69196b3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.69.0 + 6.70.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2f4379755e2b..9b12418eb360 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.69.0 + 6.70.0 import pom From 483e79515f45b0159799574bccb3c4745df95f28 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jun 2024 13:52:22 +0200 Subject: [PATCH 1327/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.45.0 (#1659) 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.api.grpc:proto-google-cloud-trace-v1](https://togithub.com/googleapis/google-cloud-java) | `2.0.0` -> `2.45.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.0.0/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.0.0/2.45.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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f40fd69196b3..84aac7828f5a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -244,7 +244,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.0.0 + 2.45.0 test From 46b074a3514ea4121149019317c1d7ccf51622ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jun 2024 13:54:21 +0200 Subject: [PATCH 1328/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.19.4 (#1658) 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.19.3` -> `2.19.4` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.19.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.19.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.19.3/2.19.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.19.3/2.19.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.19.4`](https://togithub.com/googleapis/java-spanner-jdbc/releases/tag/v2.19.4) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.19.3...v2.19.4) ##### Dependencies - Update dependency org.springframework.data:spring-data-bom to v2024.0.1 ([#​1645](https://togithub.com/googleapis/java-spanner-jdbc/issues/1645)) ([b76e435](https://togithub.com/googleapis/java-spanner-jdbc/commit/b76e435538a6faf3f38da463ca05f5c5e9238705))
    --- ### 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). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 9b12418eb360..d3f026f868f8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.3 + 2.19.4 org.postgresql From adae2287f3d3855a24c1df3c5a47d39f74233463 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Jun 2024 14:50:45 +0200 Subject: [PATCH 1329/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.45.0 (#1661) 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-trace](https://togithub.com/googleapis/google-cloud-java) | `2.0.0` -> `2.45.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.0.0/2.45.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.0.0/2.45.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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 84aac7828f5a..fe5ef38c874e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.cloud google-cloud-trace - 2.0.0 + 2.45.0 test From 571fbfb98be7340c42230973f053642ccd790d85 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 15:36:18 +0000 Subject: [PATCH 1330/1979] chore(main): release 2.20.0 (#1652) :robot: I have created a release *beep* *boop* --- ## [2.20.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.19.4...v2.20.0) (2024-06-27) ### Features * Add OpenTelemetry tracing ([#1568](https://togithub.com/googleapis/java-spanner-jdbc/issues/1568)) ([438074d](https://togithub.com/googleapis/java-spanner-jdbc/commit/438074dc7682aca23e3b451c71fbf5eff1148af0)) ### Dependencies * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.45.0 ([#1659](https://togithub.com/googleapis/java-spanner-jdbc/issues/1659)) ([483e795](https://togithub.com/googleapis/java-spanner-jdbc/commit/483e79515f45b0159799574bccb3c4745df95f28)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.70.0 ([#1657](https://togithub.com/googleapis/java-spanner-jdbc/issues/1657)) ([1e24f5f](https://togithub.com/googleapis/java-spanner-jdbc/commit/1e24f5f8b932ddf3334933765ebe287f488cf02d)) * Update dependency com.google.cloud:google-cloud-trace to v2.45.0 ([#1661](https://togithub.com/googleapis/java-spanner-jdbc/issues/1661)) ([adae228](https://togithub.com/googleapis/java-spanner-jdbc/commit/adae2287f3d3855a24c1df3c5a47d39f74233463)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.32.0 ([#1654](https://togithub.com/googleapis/java-spanner-jdbc/issues/1654)) ([928d260](https://togithub.com/googleapis/java-spanner-jdbc/commit/928d26058a06d13e78277c44c316fe10e5db8e92)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.1 ([#1648](https://togithub.com/googleapis/java-spanner-jdbc/issues/1648)) ([ebb5198](https://togithub.com/googleapis/java-spanner-jdbc/commit/ebb51981e39aab0d5c295ac933c29391eeda39fe)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.1 ([#1649](https://togithub.com/googleapis/java-spanner-jdbc/issues/1649)) ([b45a341](https://togithub.com/googleapis/java-spanner-jdbc/commit/b45a34137fa6aa670f0e1e44d2062b4890ed0f4a)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 17 +++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 1dba9adc6589..5a5563af231b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [2.20.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.4...v2.20.0) (2024-06-27) + + +### Features + +* Add OpenTelemetry tracing ([#1568](https://github.com/googleapis/java-spanner-jdbc/issues/1568)) ([1485a04](https://github.com/googleapis/java-spanner-jdbc/commit/1485a04272c270851468254bebffe4f7d846f17c)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.45.0 ([#1659](https://github.com/googleapis/java-spanner-jdbc/issues/1659)) ([0491712](https://github.com/googleapis/java-spanner-jdbc/commit/0491712babfdc7088358f28c4f261e3ec6dd0d2b)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.70.0 ([#1657](https://github.com/googleapis/java-spanner-jdbc/issues/1657)) ([83aaec1](https://github.com/googleapis/java-spanner-jdbc/commit/83aaec17b0c28ac9ef45e99eb878d40572124f3f)) +* Update dependency com.google.cloud:google-cloud-trace to v2.45.0 ([#1661](https://github.com/googleapis/java-spanner-jdbc/issues/1661)) ([648224c](https://github.com/googleapis/java-spanner-jdbc/commit/648224cfb2310d80f781386be64be00157133a30)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.32.0 ([#1654](https://github.com/googleapis/java-spanner-jdbc/issues/1654)) ([503e281](https://github.com/googleapis/java-spanner-jdbc/commit/503e281106910dc9352deeaf790097e495df127b)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.1 ([#1648](https://github.com/googleapis/java-spanner-jdbc/issues/1648)) ([4df665f](https://github.com/googleapis/java-spanner-jdbc/commit/4df665fa3a0b65757fc1c00fcf7a0fbd6c0c5d2e)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.1 ([#1649](https://github.com/googleapis/java-spanner-jdbc/issues/1649)) ([efe87a6](https://github.com/googleapis/java-spanner-jdbc/commit/efe87a6016b8d61c42f4a4ad5b7ead180545d24e)) + ## [2.19.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.2...v2.19.3) (2024-06-19) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fe5ef38c874e..6def8aa0074a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.19.5-SNAPSHOT + 2.20.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5b2f09c631e4..e12fd9baf64b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.5-SNAPSHOT + 2.20.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 384d1c7daecc..66cb2bee159c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.19.4:2.19.5-SNAPSHOT +google-cloud-spanner-jdbc:2.20.0:2.20.0 From dca6816432c109799560ca589dd097846020a5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 28 Jun 2024 13:32:40 +0200 Subject: [PATCH 1331/1979] build: run graalvm integration tests on emulator (#1662) * build: run graalvm integration tests on emulator * build: always use emulator * fix: start emulator in detached mode * fix: typo in Docker run command * build: use owned instance when testing on emulator * build: use embedded emulator * chore: add logging for emulator startup * build: start emulator in build script * chore: cleanup --- java-spanner-jdbc/.kokoro/build.sh | 15 +++++++++++++++ .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 3 +-- .../cloud/spanner/jdbc/it/ITProtoColumnsTest.java | 3 +-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 1f2ae77dadd2..f4ea82a431c1 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -42,6 +42,16 @@ if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTI export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_GFILE_DIR}/${GOOGLE_APPLICATION_CREDENTIALS}) fi +# Start the Spanner emulator if the environment variable for it has been set. +# TODO: Change if statement once the env var can be set in the config. +#if [[ ! -z "${SPANNER_EMULATOR_HOST}" ]]; then +if [[ "$JOB_TYPE" == "graalvm" ]] || [[ "$JOB_TYPE" == "graalvm17" ]]; then + echo "Starting emulator" + export SPANNER_EMULATOR_HOST=localhost:9010 + docker pull gcr.io/cloud-spanner-emulator/emulator + docker run -d --rm --name spanner-emulator -p 9010:9010 -p 9020:9020 gcr.io/cloud-spanner-emulator/emulator +fi + RETURN_CODE=0 set +e @@ -145,6 +155,11 @@ clirr) ;; esac +if [[ ! -z "${SPANNER_EMULATOR_HOST}" ]]; then + echo "Stopping emulator" + docker container stop spanner-emulator +fi + if [ "${REPORT_COVERAGE}" == "true" ] then bash ${KOKORO_GFILE_DIR}/codecov.sh diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index 2198c9464b49..35dd2dfda35c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -25,7 +25,6 @@ import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.ConnectionOptions; @@ -54,7 +53,7 @@ @RunWith(JUnit4.class) public class ITJdbcPgNumericTest { - @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(10); private static RemoteSpannerHelper testHelper; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java index a5ecf5bba534..aa09aea6efee 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java @@ -28,7 +28,6 @@ import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; -import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.jdbc.ProtoEnumType; @@ -57,7 +56,7 @@ @Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) public class ITProtoColumnsTest { - @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(10); private static Database database; private static String url; From 1345f148ce616d6a98525cb79389fd59f0817f33 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:36:21 +0200 Subject: [PATCH 1332/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.46.0 (#1669) 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-trace](https://togithub.com/googleapis/google-cloud-java) | `2.45.0` -> `2.46.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.45.0/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.45.0/2.46.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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6def8aa0074a..0661072b5097 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.cloud google-cloud-trace - 2.45.0 + 2.46.0 test From 0575abb25a774219395c2421a057f78ba7699d26 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:36:25 +0200 Subject: [PATCH 1333/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.46.0 (#1668) 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.api.grpc:proto-google-cloud-trace-v1](https://togithub.com/googleapis/google-cloud-java) | `2.45.0` -> `2.46.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.45.0/2.46.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.45.0/2.46.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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0661072b5097..d14989d2a55a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -244,7 +244,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.45.0 + 2.46.0 test From 89684ce5325172dc31b33d033f6248964a995c39 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:38:21 +0200 Subject: [PATCH 1334/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.0 (#1667) 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.19.4` -> `2.20.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.20.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.20.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.19.4/2.20.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.19.4/2.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.20.0`](https://togithub.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2200-2024-06-27) [Compare Source](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.19.4...v2.20.0) ##### Features - Add OpenTelemetry tracing ([#​1568](https://togithub.com/googleapis/java-spanner-jdbc/issues/1568)) ([438074d](https://togithub.com/googleapis/java-spanner-jdbc/commit/438074dc7682aca23e3b451c71fbf5eff1148af0)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.45.0 ([#​1659](https://togithub.com/googleapis/java-spanner-jdbc/issues/1659)) ([483e795](https://togithub.com/googleapis/java-spanner-jdbc/commit/483e79515f45b0159799574bccb3c4745df95f28)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.70.0 ([#​1657](https://togithub.com/googleapis/java-spanner-jdbc/issues/1657)) ([1e24f5f](https://togithub.com/googleapis/java-spanner-jdbc/commit/1e24f5f8b932ddf3334933765ebe287f488cf02d)) - Update dependency com.google.cloud:google-cloud-trace to v2.45.0 ([#​1661](https://togithub.com/googleapis/java-spanner-jdbc/issues/1661)) ([adae228](https://togithub.com/googleapis/java-spanner-jdbc/commit/adae2287f3d3855a24c1df3c5a47d39f74233463)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.32.0 ([#​1654](https://togithub.com/googleapis/java-spanner-jdbc/issues/1654)) ([928d260](https://togithub.com/googleapis/java-spanner-jdbc/commit/928d26058a06d13e78277c44c316fe10e5db8e92)) - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.1 ([#​1648](https://togithub.com/googleapis/java-spanner-jdbc/issues/1648)) ([ebb5198](https://togithub.com/googleapis/java-spanner-jdbc/commit/ebb51981e39aab0d5c295ac933c29391eeda39fe)) - Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.1 ([#​1649](https://togithub.com/googleapis/java-spanner-jdbc/issues/1649)) ([b45a341](https://togithub.com/googleapis/java-spanner-jdbc/commit/b45a34137fa6aa670f0e1e44d2062b4890ed0f4a))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e5186696709e..3e07459a66fe 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.4 + 2.20.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d3f026f868f8..cda07c708e99 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.19.4 + 2.20.0 org.postgresql From 2663a7656efcb41fafaa195e520d71dfd491fc8d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:38:25 +0200 Subject: [PATCH 1335/1979] test(deps): update dependency com.google.truth:truth to v1.4.3 (#1664) 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.truth:truth](https://togithub.com/google/truth) | `1.4.2` -> `1.4.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.truth:truth/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.truth:truth/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.truth:truth/1.4.2/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.truth:truth/1.4.2/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    google/truth (com.google.truth:truth) ### [`v1.4.3`](https://togithub.com/google/truth/releases/tag/v1.4.3): 1.4.3 - Added more nullness information to our APIs (in the form of [JSpecify](https://jspecify.dev/) annotations). This could lead to additional warnings (or even errors) for users of Kotlin and other nullness checkers. Please [report any problems](https://togithub.com/google/truth/issues/new). ([`ee680cb`](https://togithub.com/google/truth/commit/ee680cbaf)) - Deprecated `Subject.Factory` methods for Java 8 types. We won't remove them, but you can simplify your code by migrating off them: Just replace `assertAbout(foos()).that(foo)` with `assertThat(foo)` (or `about(foos()).that(foo)` with `that(foo)`). ([`59e7a50`](https://togithub.com/google/truth/commit/59e7a5065))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d14989d2a55a..ea901b1ac466 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.2 + 1.4.3 4.11.0 2.2 0.31.1 From d94ed138610867fa9e07df9e2999f55996e92f8e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:40:48 +0200 Subject: [PATCH 1336/1979] test(deps): update dependency com.google.truth:truth to v1.4.3 (#1665) 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.truth:truth](https://togithub.com/google/truth) | `1.4.2` -> `1.4.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.truth:truth/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.truth:truth/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.truth:truth/1.4.2/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.truth:truth/1.4.2/1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    google/truth (com.google.truth:truth) ### [`v1.4.3`](https://togithub.com/google/truth/releases/tag/v1.4.3): 1.4.3 - Added more nullness information to our APIs (in the form of [JSpecify](https://jspecify.dev/) annotations). This could lead to additional warnings (or even errors) for users of Kotlin and other nullness checkers. Please [report any problems](https://togithub.com/google/truth/issues/new). ([`ee680cb`](https://togithub.com/google/truth/commit/ee680cbaf)) - Deprecated `Subject.Factory` methods for Java 8 types. We won't remove them, but you can simplify your code by migrating off them: Just replace `assertAbout(foos()).that(foo)` with `assertThat(foo)` (or `about(foos()).that(foo)` with `that(foo)`). ([`59e7a50`](https://togithub.com/google/truth/commit/59e7a5065))
    --- ### 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). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 3e07459a66fe..d219420513c6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.2 + 1.4.3 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e12fd9baf64b..60fe8c1fdf29 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.4.2 + 1.4.3 test From 322c7698337b8cf94d019755fd9941c664802770 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Jun 2024 13:40:52 +0200 Subject: [PATCH 1337/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.39.0 (#1663) 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 | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://togithub.com/open-telemetry/opentelemetry-java) | `1.37.0` -> `1.39.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.37.0/1.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.37.0/1.39.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.39.0`](https://togithub.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1390-2024-06-07) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-java/compare/v1.38.0...v1.39.0) ##### API ##### Incubator - BREAKING: Refactor ExtendedTracer, ExtendedSpanBuilder to reflect incubating API conventions ([#​6497](https://togithub.com/open-telemetry/opentelemetry-java/pull/6497)) ##### SDK ##### Exporter - BREAKING: Serve prometheus metrics only on `/metrics` by default. To restore the previous behavior and serve metrics on all paths, override the default handler as [demonstrated here](https://togithub.com/open-telemetry/opentelemetry-java/blob/main/exporters/prometheus/src/test/java/io/opentelemetry/exporter/prometheus/PrometheusHttpServerTest.java#L251-L259). ([#​6476](https://togithub.com/open-telemetry/opentelemetry-java/pull/6476)) - Make OTLP exporter memory mode API public ([#​6469](https://togithub.com/open-telemetry/opentelemetry-java/pull/6469)) - Speed up OTLP string marshaling using sun.misc.Unsafe ([#​6433](https://togithub.com/open-telemetry/opentelemetry-java/pull/6433)) - Add exporter data classes for experimental profiling signal type. ([#​6374](https://togithub.com/open-telemetry/opentelemetry-java/pull/6374)) - Start prometheus http server with daemon thread ([#​6472](https://togithub.com/open-telemetry/opentelemetry-java/pull/6472)) - Update the Prometheus metrics library and improve how units are included in metric names. ([#​6473](https://togithub.com/open-telemetry/opentelemetry-java/pull/6473)) - Remove android animalsniffer check from prometheus exporter ([#​6478](https://togithub.com/open-telemetry/opentelemetry-java/pull/6478)) ##### Extensions - Load file config YAML using core schema, ensure that env var substitution retains string types. ([#​6436](https://togithub.com/open-telemetry/opentelemetry-java/pull/6436)) - Define dedicated file configuration SPI ComponentProvider ([#​6457](https://togithub.com/open-telemetry/opentelemetry-java/pull/6457)) ##### Tooling - Normalize timestamps and file ordering in jars, making the outputs reproducible ([#​6471](https://togithub.com/open-telemetry/opentelemetry-java/pull/6471)) - GHA for generating the post-release pull request ([#​6449](https://togithub.com/open-telemetry/opentelemetry-java/pull/6449)) ### [`v1.38.0`](https://togithub.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1380-2024-05-10) [Compare Source](https://togithub.com/open-telemetry/opentelemetry-java/compare/v1.37.0...v1.38.0) ##### API - Stabilize synchronous gauge ([#​6419](https://togithub.com/open-telemetry/opentelemetry-java/pull/6419)) ##### Incubator - Add put(AttributeKey, T) overload to EventBuilder ([#​6331](https://togithub.com/open-telemetry/opentelemetry-java/pull/6331)) ##### Baggage - Baggage filters space-only keys ([#​6431](https://togithub.com/open-telemetry/opentelemetry-java/pull/6431)) ##### SDK - Add experimental scope config to enable / disable scopes (i.e. meter, logger, tracer) ([#​6375](https://togithub.com/open-telemetry/opentelemetry-java/pull/6375)) ##### Traces - Add ReadableSpan#getAttributes ([#​6382](https://togithub.com/open-telemetry/opentelemetry-java/pull/6382)) - Use standard ArrayList size rather than max number of links for initial span links allocation ([#​6252](https://togithub.com/open-telemetry/opentelemetry-java/pull/6252)) ##### Metrics - Use low precision Clock#now when computing timestamp for exemplars ([#​6417](https://togithub.com/open-telemetry/opentelemetry-java/pull/6417)) - Update invalid instrument name log message now that forward slash `/` is valid ([#​6343](https://togithub.com/open-telemetry/opentelemetry-java/pull/6343)) ##### Exporters - Introduce low allocation OTLP marshalers. If using autoconfigure, opt in via `OTEL_JAVA_EXPERIMENTAL_EXPORTER_MEMORY_MODE=REUSABLE_DATA`. - Low allocation OTLP logs marshaler ([#​6429](https://togithub.com/open-telemetry/opentelemetry-java/pull/6429)) - Low allocation OTLP metrics marshaler ([#​6422](https://togithub.com/open-telemetry/opentelemetry-java/pull/6422)) - Low allocation OTLP trace marshaler ([#​6410](https://togithub.com/open-telemetry/opentelemetry-java/pull/6410)) - Add memory mode support to OTLP exporters ([#​6430](https://togithub.com/open-telemetry/opentelemetry-java/pull/6430)) - Marshal span status description without allocation ([#​6423](https://togithub.com/open-telemetry/opentelemetry-java/pull/6423)) - Add private constructors for stateless marshalers ([#​6434](https://togithub.com/open-telemetry/opentelemetry-java/pull/6434)) - Mark opentelemetry-exporter-sender-jdk stable ([#​6357](https://togithub.com/open-telemetry/opentelemetry-java/pull/6357)) - PrometheusHttpServer prevent concurrent reads when reusable memory mode ([#​6371](https://togithub.com/open-telemetry/opentelemetry-java/pull/6371)) - Ignore TLS components (SSLContext, TrustManager, KeyManager) if plain HTTP protocol is used for exporting ([#​6329](https://togithub.com/open-telemetry/opentelemetry-java/pull/6329)) - Add is_remote_parent span flags to OTLP exported Spans and SpanLinks ([#​6388](https://togithub.com/open-telemetry/opentelemetry-java/pull/6388)) - Add missing fields to OTLP metric exporters `toString()` ([#​6402](https://togithub.com/open-telemetry/opentelemetry-java/pull/6402)) ##### Extensions - Rename otel.config.file to otel.experimental.config.file for autoconfigure ([#​6396](https://togithub.com/open-telemetry/opentelemetry-java/pull/6396)) ##### OpenCensus Shim - Fix opencensus shim spanBuilderWithRemoteParent behavior ([#​6415](https://togithub.com/open-telemetry/opentelemetry-java/pull/6415)) ##### Tooling - Add additional API incubator docs ([#​6356](https://togithub.com/open-telemetry/opentelemetry-java/pull/6356)) - Run build on java 21 ([#​6370](https://togithub.com/open-telemetry/opentelemetry-java/pull/6370)) - Fix running tests with java 8 on macos ([#​6411](https://togithub.com/open-telemetry/opentelemetry-java/pull/6411)) - Move away from deprecated gradle enterprise APIs ([#​6363](https://togithub.com/open-telemetry/opentelemetry-java/pull/6363))
    --- ### 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). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index cda07c708e99..f595c1920c5d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.37.0 + 1.39.0 pom import From eb502864f7d6a6630f3d39f811756e2874d4820b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2024 11:58:22 +0000 Subject: [PATCH 1338/1979] chore(main): release 2.20.1-SNAPSHOT (#1666) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ea901b1ac466..5af2ac51484d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.0 + 2.20.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 60fe8c1fdf29..ed0a014be3a1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.0 + 2.20.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 66cb2bee159c..2311d02bfb0a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.0:2.20.0 +google-cloud-spanner-jdbc:2.20.0:2.20.1-SNAPSHOT From b7b1f3cd05458a7a9a3e9378aba26b7c0cc9d895 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 3 Jul 2024 16:10:19 +0200 Subject: [PATCH 1339/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.71.0 (#1672) 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.70.0` -> `6.71.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.71.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.71.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.70.0/6.71.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.70.0/6.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.71.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6710-2024-07-03) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.70.0...v6.71.0) ##### Features - Include thread name in traces ([#​3173](https://togithub.com/googleapis/java-spanner/issues/3173)) ([92b1e07](https://togithub.com/googleapis/java-spanner/commit/92b1e079e6093bc4a2e7b458c1bbe0f62a0fada9)) - Support multiplexed sessions for RO transactions ([#​3141](https://togithub.com/googleapis/java-spanner/issues/3141)) ([2b8e9ed](https://togithub.com/googleapis/java-spanner/commit/2b8e9ededc1ea1a5e8d4f90083f2cf862fcc198a))
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5af2ac51484d..a99d0a0c0b99 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-bom - 6.70.0 + 6.71.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index f595c1920c5d..46641d014fb2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.70.0 + 6.71.0 import pom From 851a075056ee90945f973f6bccf9904186e8a28c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 3 Jul 2024 16:12:19 +0200 Subject: [PATCH 1340/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.30.0 (#1671) 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.opentelemetry:exporter-trace](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java) | `0.23.0` -> `0.30.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud.opentelemetry:exporter-trace/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud.opentelemetry:exporter-trace/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud.opentelemetry:exporter-trace/0.23.0/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud.opentelemetry:exporter-trace/0.23.0/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [com.google.cloud.opentelemetry:exporter-trace](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java) | `0.29.0` -> `0.30.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud.opentelemetry:exporter-trace/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud.opentelemetry:exporter-trace/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud.opentelemetry:exporter-trace/0.29.0/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud.opentelemetry:exporter-trace/0.29.0/0.30.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    GoogleCloudPlatform/opentelemetry-operations-java (com.google.cloud.opentelemetry:exporter-trace) ### [`v0.30.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.30.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.29.0...v0.30.0) ##### Release Highlights - Minimum supported Java version set to **Java 8** for all consumable artifacts. ##### What's Changed - Udpate maven-badges to link to sonatype central by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/349](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/349) - Make the trace flags optional when parsing x-cloud-trace-context by [@​sawadakaku](https://togithub.com/sawadakaku) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/350](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/350) - Update Metrics Exporter README by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/352](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/352) - Add Java8 support by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/353](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/353) ##### New Contributors - [@​sawadakaku](https://togithub.com/sawadakaku) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/350](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/350) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.29.0...v0.30.0 ### [`v0.29.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.29.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.28.0...v0.29.0) #### Release Highlights - Non-GKE resource now map to `k8s_*` monitored resource ([#​340](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/340) , [#​342](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/342)) - Support for mapping to custom Monitored Resources ([#​346](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/346)) - Newly deprecated APIs: [mapResource](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/blob/b0caafdaceb2b7418d256cecc05fa8fce9bafecc/exporters/metrics/src/main/java/com/google/cloud/opentelemetry/metric/ResourceTranslator.java#L36) #### What's Changed - Update maven-badges to link to sonatype central by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/322](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/322) - Add auth support for gRPC by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/323](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/323) - Switch to ConcurrentMap for thread-safety by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/328](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/328) - Add otlp with spring boot sample by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/327](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/327) - Change OTel quickstart to use log4j2 instead of logback by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/330](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/330) - Always output logging.googleapis.com/trace_sampled as true by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/332](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/332) - Update JVM flag otel.java.experimental.extension by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/338](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/338) - Add test case for zone resource detection on GAE standard by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/341](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/341) - Fix [#​258](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/258) enable mapping when not gcp kubernetes by [@​tkmsaaaam](https://togithub.com/tkmsaaaam) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/340](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/340) - Fix [#​340](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/340) bug by [@​tkmsaaaam](https://togithub.com/tkmsaaaam) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/342](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/342) - Make all AttributeMappings final by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/347](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/347) - Add support for custom MR mappings by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/346](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/346) #### New Contributors - [@​tkmsaaaam](https://togithub.com/tkmsaaaam) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/340](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/340) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.28.0...v0.29.0 ### [`v0.28.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.28.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.27.0...v0.28.0) #### Release Highlights - Add support for `CreateServiceTimeseries` in metrics exporter in [#​318](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/318). - Add resource attributes as metrics labels by providing a Predicate based filter to control which resource attributes end up as metric labels in [#​314](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/314), [#​319](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/319). #### What's Changed - Add Readme for detector-resources-support module by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/282](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/282) - Copy instrumentation quickstart out of java-docs-samples by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/283](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/283) - Enable snippet-bot by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/284](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/284) - Quota project fix by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/286](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/286) - Use logstash-logback-encoder version that works with spring boot 2 by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/285](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/285) - Update instrumentation quickstart README links by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/287](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/287) - Make examples/instrumentation-quickstart a standalone gradle build by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/289](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/289) - Add CI for examples/instrumentation-quickstart by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/290](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/290) - Test against java 11 by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/293](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/293) - Update TraceTranslator.java by [@​WadeGulbrandsen](https://togithub.com/WadeGulbrandsen) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/296](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/296) - feat: simplify logging in instrumentation quickstart by [@​dashpole](https://togithub.com/dashpole) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/298](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/298) - Update Gradle to v8.6 by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/300](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/300) - Replace resource detector with upstream detector by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/301](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/301) - Update links to the upstream detector by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/302](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/302) - Add OTLP trace with ADC example by [@​damemi](https://togithub.com/damemi) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/297](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/297) - Update auto-exporter readme by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/304](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/304) - Add tests to verify OTel integration using in-memory exporter by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/306](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/306) - Add GH action step to test shadowJar by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/309](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/309) - Add missing GOOGLE_CLOUD_QUOTA_PROJECT environment variable to compose file by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/311](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/311) - Update instrumentation quickstart to new region tag name by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/312](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/312) - Update instrumentation-quickstart README by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/315](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/315) - Add resource attributes as metric labels by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/314](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/314) - Update resource detection sample by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/317](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/317) - Make setResourceAttributesFilter public by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/319](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/319) - Add support for createServiceTimeSeries by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/318](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/318) - Disable release for gcp-resource-detector by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/321](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/321) #### New Contributors - [@​WadeGulbrandsen](https://togithub.com/WadeGulbrandsen) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/296](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/296) - [@​damemi](https://togithub.com/damemi) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/297](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/297) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.27.0...v0.28.0 ### [`v0.27.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.27.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.26.0...v0.27.0) #### Changes Highlights - Minimum compatible version for resource detectors is now Java 8 (Java 11 or higher was required with previous versions). - \[Not user facing] Resource detection library split into a `detector-resources-support` and `detector-resources` module. This enables [#​266](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/266). #### What's Changed - Make resource-detector compatible with Java 8 by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/275](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/275) - Fixed spotless config for copyright year by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/279](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/279) - Add new module for resource-detector support library by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/276](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/276) - Update readme to include download link for exporter auto by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/280](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/280) - Enable resource-detection-support library for release by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/281](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/281) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.26.0...v0.27.0 ### [`v0.26.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.26.0) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.25.2...v0.26.0) #### Changes Highlights - Updates the OTel dependencies so that the exporters are now compatible with newest Otel Java agent (fix [#​263](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/263)) - Updates internal resource mappings ([#​260](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/260), [#​272](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/272)) #### What's Changed - Update README.md by [@​nimf](https://togithub.com/nimf) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/257](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/257) - Use faas.instance instead of faas.id in resource detection and mapping by [@​dashpole](https://togithub.com/dashpole) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/260](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/260) - Fix cloudfunctions test by [@​dashpole](https://togithub.com/dashpole) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/270](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/270) - upgrade google java format for jdk 17 by [@​SylvainJuge](https://togithub.com/SylvainJuge) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/264](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/264) - Update OTel dependencies by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/267](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/267) - Update mappings for generic_task and generic_node by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/272](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/272) - Add security policy by [@​dashpole](https://togithub.com/dashpole) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/273](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/273) - chore: run codeql on PRs by [@​dashpole](https://togithub.com/dashpole) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/274](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/274) #### New Contributors - [@​nimf](https://togithub.com/nimf) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/257](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/257) - [@​SylvainJuge](https://togithub.com/SylvainJuge) made their first contribution in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/264](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/264) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.25.2...v0.26.0 ### [`v0.25.2`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.25.2) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.25.1...v0.25.2) #### Changes Highlights - Fixes invalid metric descriptor bug on Windows based environments [#​252](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/252) - Enable cloud run support for metric exporter [#​248](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/248) - Updates to documentation & examples #### Complete Release Notes - What's Changed - Update instructions for releasing by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/239](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/239) - Updates exporter-auto readme for shaded-variants by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/245](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/245) - Enable metrics-exporter example to run as cloud run job by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/249](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/249) - Update copyright from "Google" -> "Google LLC" by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/254](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/254) - Remove MR mapping for cloud run and cloud functions by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/250](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/250) - Hardcode path separator used for metric type by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/253](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/253) - Make private static fields final by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/256](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/256) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.25.1...v0.25.2 ### [`v0.25.1`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.25.1) [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.25.0...v0.25.1) #### What's Changed - Fixes broken pom by removing versionMapping by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/242](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/242) ##### Details The broken POM change for exporter-auto in v0.25.0 has been fixed now. ### [`v0.25.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.25.0): Release 0.25.0 [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.24.0...v0.25.0) #### Changes Highlights - With this release a shaded variant of the auto-exporter is being provided along with an un-shaded variant. The shaded jar is recommended when the auto-exporter required to be provided as an agent. This is a common use-case when using OTel auto-instrumentation. - Fixed underlying bug with the exporters that caused OpenTelemetry to disable if this library was used with opencensus-shim ([#​141](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/141)). - Updated metric exporter to set label descriptors for metrics to type String if the default prefix - `workload.googleapis.com` is used ([#​159](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/issues/159)). - Documentation updates and fixes to the examples that make them easier to run & follow. #### Important - Broken Dependencies - The non-shaded variant for `exporter-auto` has a broken POM, which will cause issues in a Maven project. Use the shaded variant instead. #### Complete Release Notes - What's Changed - Update README to add missing setup steps. by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/192](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/192) - Replaced concrete type TraceExporter with interface type SpanExporter by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/194](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/194) - Fix header check by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/197](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/197) - chore: add CODEOWNERS file to auto assign team for reviews by [@​aabmass](https://togithub.com/aabmass) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/200](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/200) - Fix trace exporter by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/193](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/193) - Fix metrics exporter by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/203](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/203) - Remove shadow plugin from exporter-trace module by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/204](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/204) - Fix exporter-trace example & add README by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/206](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/206) - Fix metrics exporter integration by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/207](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/207) - Fix documentation errors by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/208](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/208) - Upgrade to Gradle 7.6 by [@​punya](https://togithub.com/punya) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/209](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/209) - Update gradle by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/211](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/211) - Improve build time for e2e-test-server by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/213](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/213) - Relocate dependencies in the generated shadowJar by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/212](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/212) - Make GCPResourceTest environment agnostic by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/217](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/217) - Update dependencies by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/219](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/219) - Fix autoconf example by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/223](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/223) - Update license header by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/222](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/222) - Add missing otlp exporter dependency by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/221](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/221) - Add required env variables for publishing metrics by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/224](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/224) - Spotless yaml by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/227](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/227) - Update allowed copyright holders by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/230](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/230) - Spotless shell by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/228](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/228) - Fix timeseries by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/231](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/231) - Refactor: Rename method & variables for better readability by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/233](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/233) - Configures auto-exporter to publish shaded and non-shaded variants by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/235](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/235) - Adds dependency declarations to order tasks by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/237](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/237) - Declares explicit dependency for signMavenPublication by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/238](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/238) - Add script to run example in docker container by [@​psx95](https://togithub.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/229](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/229) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.24.0...v0.25.0 ### [`v0.24.0`](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.24.0): Release 0.24.0 [Compare Source](https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.23.0...v0.24.0) Dependency version updates, updated resource detection and prefix option for metrics exporter. With this release, minimum supported Java version has been upgraded to **Java 11**. *** #### What's Changed - FEATURE: enable resource detection for GCP compute environments. - CHORE: Upgrade Gradle from v6.x to v7.x. - FEATURE: Add prefix option to metrics exporter. - CHORE: Update dependency versions. **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.23.0...v0.24.0
    --- ### 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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a99d0a0c0b99..f05cce3e4bb4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.23.0 + 0.30.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 46641d014fb2..c81835b516e7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.29.0 + 0.30.0 From 1bfff9fc77d02fb6b060bf75c7504a960d67e2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 4 Jul 2024 10:24:02 +0200 Subject: [PATCH 1341/1979] perf: use multiplexed sessions (#1673) * perf: use multiplexed sessions Enable the use of multiplexed sessions by default for queries in auto-commit mode. Multiplexed sessions can handle any number of queries concurrently. This means that the JDBC driver does not need to check out a session exclusively from the internal session pool in order to execute a query. Instead, a single multiplexed session is enough for all queries that are executed by all JDBC connections that connect to the same Spanner database. This allows a higher degree of parallelism to be achieved from a single client machine. Note that due to how the JDBC API is defined, each JDBC connection can only execute one query at a time. If you for example want to execute 1000 queries in parallel, then you also need to create 1000 JDBC connections. Spanner JDBC connection are however lightweight, as each JDBC connection internally uses a pool of gRPC channels. It is recommended to enable the use of virtual threads to achieve the highest possible degree of parallelism with the JDBC driver. This option can be set by adding useVirtualThreads=true to the JDBC connection URL. Note that virtual threads are only supported on Java 21 and higher. * test: add test for multi-use read-only transaction --- .../spanner/SessionPoolOptionsHelper.java | 34 +++ .../google/cloud/spanner/jdbc/JdbcDriver.java | 5 + .../cloud/spanner/MockServerHelper.java | 28 +++ .../spanner/jdbc/JdbcConnectionUrlTest.java | 2 +- .../MultiplexedSessionsMockServerTest.java | 217 ++++++++++++++++++ 5 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/SessionPoolOptionsHelper.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/MockServerHelper.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/SessionPoolOptionsHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/SessionPoolOptionsHelper.java new file mode 100644 index 000000000000..71fb105ee1fb --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/SessionPoolOptionsHelper.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner; + +import com.google.api.core.InternalApi; + +/** + * This class is only here to access a package-private method in the Spanner client library and will + * be removed in the future. + */ +@InternalApi +public class SessionPoolOptionsHelper { + private SessionPoolOptionsHelper() {} + + @InternalApi + public static SessionPoolOptions.Builder useMultiplexedSessions( + SessionPoolOptions.Builder builder) { + return builder.setUseMultiplexedSession(true); + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 16538e653b44..d87aab02ebdb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -18,6 +18,8 @@ import com.google.api.core.InternalApi; import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.spanner.SessionPoolOptions; +import com.google.cloud.spanner.SessionPoolOptionsHelper; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; @@ -239,6 +241,9 @@ private ConnectionOptions buildConnectionOptions(String connectionUrl, Propertie && info.get(OPEN_TELEMETRY_PROPERTY_KEY) instanceof OpenTelemetry) { builder.setOpenTelemetry((OpenTelemetry) info.get(OPEN_TELEMETRY_PROPERTY_KEY)); } + // Enable multiplexed sessions by default for the JDBC driver. + builder.setSessionPoolOptions( + SessionPoolOptionsHelper.useMultiplexedSessions(SessionPoolOptions.newBuilder()).build()); return builder.build(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/MockServerHelper.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/MockServerHelper.java new file mode 100644 index 000000000000..95bdf1ed26a7 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/MockServerHelper.java @@ -0,0 +1,28 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner; + +import com.google.spanner.v1.Session; + +public class MockServerHelper { + + private MockServerHelper() {} + + public static Session getSession(MockSpannerServiceImpl server, String sessionName) { + return server.getSession(sessionName); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java index c0f9473bf9a2..bcf8256dfc2c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java @@ -68,7 +68,7 @@ public static void reset() { } protected String getBaseUrl() { - return super.getBaseUrl() + ";maxSessions=1"; + return super.getBaseUrl() + ";minSessions=0;maxSessions=1"; } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java new file mode 100644 index 000000000000..7688999a1984 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -0,0 +1,217 @@ +/* + * 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.MockServerHelper; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.spanner.v1.CreateSessionRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.Session; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +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 MultiplexedSessionsMockServerTest extends AbstractMockServerTest { + private static final String SELECT_RANDOM_SQL = SELECT_RANDOM_STATEMENT.getSql(); + + private static final String INSERT_SQL = INSERT_STATEMENT.getSql(); + + @Parameter public Dialect dialect; + + private Dialect currentDialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + @Before + public void setupDialect() { + if (this.dialect != currentDialect) { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(this.dialect)); + this.currentDialect = 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" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); + } + + private Connection createConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testUsesMultiplexedSessionForQueryInAutoCommit() throws SQLException { + try (Connection connection = createConnection()) { + assertTrue(connection.getAutoCommit()); + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) { + // Just consume the results + } + } + } + // Verify that one multiplexed session was created and used. + assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + assertTrue(request.getSession().getMultiplexed()); + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); + Session session = MockServerHelper.getSession(mockSpanner, sessionId); + assertNotNull(session); + assertTrue(session.getMultiplexed()); + } + + @Test + public void testUsesMultiplexedSessionForQueryInReadOnlyTransaction() throws SQLException { + int numQueries = 2; + try (Connection connection = createConnection()) { + connection.setReadOnly(true); + connection.setAutoCommit(false); + + for (int ignore = 0; ignore < numQueries; ignore++) { + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) { + // Just consume the results + } + } + } + } + // Verify that one multiplexed session was created and used. + assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + assertTrue(request.getSession().getMultiplexed()); + + // Verify that both queries used the multiplexed session. + assertEquals(numQueries, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + for (int index = 0; index < numQueries; index++) { + String sessionId = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(index).getSession(); + Session session = MockServerHelper.getSession(mockSpanner, sessionId); + assertNotNull(session); + assertTrue(session.getMultiplexed()); + } + } + + @Test + public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { + try (Connection connection = createConnection()) { + assertTrue(connection.getAutoCommit()); + assertEquals(1, connection.createStatement().executeUpdate(INSERT_SQL)); + } + // The JDBC connection creates a multiplexed session by default, because it executes a query to + // check what dialect the database uses. This query is executed using a multiplexed session. + assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + assertTrue(request.getSession().getMultiplexed()); + // Verify that a regular session was used for the insert statement. + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertEquals( + INSERT_SQL, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSql()); + String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); + Session session = MockServerHelper.getSession(mockSpanner, sessionId); + assertNotNull(session); + assertFalse(session.getMultiplexed()); + } + + @Test + public void testUsesRegularSessionForQueryInTransaction() throws SQLException { + try (Connection connection = createConnection()) { + connection.setAutoCommit(false); + assertFalse(connection.getAutoCommit()); + + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) { + // Just consume the results + } + } + connection.commit(); + } + // The JDBC connection creates a multiplexed session by default, because it executes a query to + // check what dialect the database uses. This query is executed using a multiplexed session. + assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + assertTrue(request.getSession().getMultiplexed()); + // Verify that a regular session was used for the select statement. + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertEquals( + SELECT_RANDOM_SQL, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSql()); + String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); + Session session = MockServerHelper.getSession(mockSpanner, sessionId); + assertNotNull(session); + assertFalse(session.getMultiplexed()); + } + + @Test + public void testUsesMultiplexedSessionInCombinationWithSessionPoolOptions() throws SQLException { + // Create a connection that uses a session pool with MinSessions=0. + // This should stop any regular sessions from being created. + // TODO: Modify this test once https://github.com/googleapis/java-spanner/pull/3197 has been + // released. + try (Connection connection = DriverManager.getConnection(createUrl() + ";minSessions=0")) { + assertTrue(connection.getAutoCommit()); + try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) { + // Just consume the results + } + } + } + // TODO: Remove this line once https://github.com/googleapis/java-spanner/pull/3197 has been + // released. + // Adding 'minSessions=X' or 'maxSessions=x' to the connection URL currently disables the use of + // multiplexed sessions due to a bug in the Spanner Java client. + assertEquals(0, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + + // Verify that one multiplexed session was created and used. + // TODO: Uncomment + // assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + // CreateSessionRequest request = + // mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + // assertTrue(request.getSession().getMultiplexed()); + // // There should be no regular sessions in use. + // assertEquals(0, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); + } +} From fcf19abbbfeda8fa9030f60b0eb454b93ccc143b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:30:08 +0200 Subject: [PATCH 1342/1979] chore(main): release 2.20.1 (#1670) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 5a5563af231b..61628c9de2d7 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.20.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.0...v2.20.1) (2024-07-04) + + +### Performance Improvements + +* Use multiplexed sessions ([#1673](https://github.com/googleapis/java-spanner-jdbc/issues/1673)) ([107ec66](https://github.com/googleapis/java-spanner-jdbc/commit/107ec661ad73648ed7689c4abafd186cc458e73e)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.46.0 ([#1668](https://github.com/googleapis/java-spanner-jdbc/issues/1668)) ([62620e0](https://github.com/googleapis/java-spanner-jdbc/commit/62620e0cc0b83bbf8b775593deac8aa4d555364e)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.71.0 ([#1672](https://github.com/googleapis/java-spanner-jdbc/issues/1672)) ([4bcfaf9](https://github.com/googleapis/java-spanner-jdbc/commit/4bcfaf9906a41cb0eb1fd3c053324e1d18606ca2)) +* Update dependency com.google.cloud:google-cloud-trace to v2.46.0 ([#1669](https://github.com/googleapis/java-spanner-jdbc/issues/1669)) ([debcfc0](https://github.com/googleapis/java-spanner-jdbc/commit/debcfc0cf8b076014487c5879a7c4df9e88c079a)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.30.0 ([#1671](https://github.com/googleapis/java-spanner-jdbc/issues/1671)) ([2cdc0a3](https://github.com/googleapis/java-spanner-jdbc/commit/2cdc0a3c0c6bd61e6cd57279dd8535943cac322f)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.39.0 ([#1663](https://github.com/googleapis/java-spanner-jdbc/issues/1663)) ([9c37fe3](https://github.com/googleapis/java-spanner-jdbc/commit/9c37fe35873d3296f54612377a868a6c5bfed9c6)) + ## [2.20.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.19.4...v2.20.0) (2024-06-27) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f05cce3e4bb4..90c0bc999021 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.1-SNAPSHOT + 2.20.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ed0a014be3a1..edd0343b6407 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1-SNAPSHOT + 2.20.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 2311d02bfb0a..3ba0302ddc7b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.0:2.20.1-SNAPSHOT +google-cloud-spanner-jdbc:2.20.1:2.20.1 From 54dacde0c06facc10bec3c38f435bf8152132588 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:09:49 +0200 Subject: [PATCH 1343/1979] chore(main): release 2.20.2-SNAPSHOT (#1674) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 90c0bc999021..064e0313f19c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.1 + 2.20.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index edd0343b6407..e173442f42d2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1 + 2.20.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3ba0302ddc7b..807395b03d74 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.1:2.20.1 +google-cloud-spanner-jdbc:2.20.1:2.20.2-SNAPSHOT From c064a54d43c75ad62e471a0bdc918a424cb80d6e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 6 Jul 2024 19:18:30 +0200 Subject: [PATCH 1344/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.1 (#1675) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d219420513c6..94307f836944 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.0 + 2.20.1 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c81835b516e7..bf354299ea09 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.0 + 2.20.1 org.postgresql From eb18733c7c403bf2e535a0b0b9445e336d5b120b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 9 Jul 2024 07:30:58 +0200 Subject: [PATCH 1345/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.43.0 (#1677) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a7c189c45a5f..0c3b12de909d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.42.0 + 26.43.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index bf354299ea09..adfc3dd38ad1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.42.0 + 26.43.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index f2adc315e796..db5af5419440 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.42.0 + 26.43.0 import pom From bc24c277978d80bb9b4a93c9a56dfc15d1b174ba Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 9 Jul 2024 07:51:51 +0200 Subject: [PATCH 1346/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.40.0 (#1676) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index adfc3dd38ad1..f65c691120b4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.39.0 + 1.40.0 pom import From f4fcd1afc8668f66adee4a3c5843ddf7661f7856 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 12 Jul 2024 09:46:35 +0200 Subject: [PATCH 1347/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.31.0 (#1679) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 064e0313f19c..c8d66c0d1fd9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.30.0 + 0.31.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index f65c691120b4..5990abbde1c2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -78,7 +78,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.30.0 + 0.31.0 From 9bdd6f3bdbfbb17a2b047222f2e5580571de64f7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 14 Jul 2024 08:10:12 +0200 Subject: [PATCH 1348/1979] test(deps): update dependency com.google.truth:truth to v1.4.4 (#1682) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 94307f836944..87be572f40d3 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.3 + 1.4.4 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e173442f42d2..cc99c9b5eab4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -41,7 +41,7 @@ com.google.truth truth - 1.4.3 + 1.4.4 test From 4ff9caab95d81567c6f48733e319f5ecbf443c15 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 14 Jul 2024 08:11:16 +0200 Subject: [PATCH 1349/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.2 (#1680) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5990abbde1c2..0d9e94c96e6d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.1 + 2024.0.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index db5af5419440..b9fe2a929f6e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.1 + 2024.0.2 import pom From 0468c9251541934d55ef95b6747f1d656745f62a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 14 Jul 2024 08:11:29 +0200 Subject: [PATCH 1350/1979] test(deps): update dependency com.google.truth:truth to v1.4.4 (#1681) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c8d66c0d1fd9..a8141a84bbad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.3 + 1.4.4 4.11.0 2.2 0.31.1 From d829175288ca912c29c509a68a7fd5a20c0b3e89 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Jul 2024 20:50:13 +0200 Subject: [PATCH 1351/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.6.2 (#1683) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a8141a84bbad..9cece1c6bcbe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -439,7 +439,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.6.1 + 3.6.2 From ccd6a9c37cbad7371573205e2349fd0b69d557b8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jul 2024 13:06:01 +0200 Subject: [PATCH 1352/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.2 (#1686) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b9fe2a929f6e..a5ad7633d73c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.1 + 3.3.2 From 080e8600316f893b391045d00381acc48e5b2a89 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jul 2024 13:06:14 +0200 Subject: [PATCH 1353/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.2 (#1685) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 0d9e94c96e6d..f2d20d8ac933 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.1 + 3.3.2 From d62793caa04656e0f1da96841b7417aeb4cc3ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 25 Jul 2024 17:35:16 +0200 Subject: [PATCH 1354/1979] test: add test to verify client-lib header is included (#1689) --- .../cloud/spanner/jdbc/JdbcDriverTest.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 36c97fa5e44f..13efeb8170f4 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -18,8 +18,11 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; @@ -27,7 +30,14 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.rpc.Code; +import io.grpc.Context; +import io.grpc.Contexts; +import io.grpc.Metadata; import io.grpc.Server; +import io.grpc.ServerCall; +import io.grpc.ServerCall.Listener; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; import java.io.IOException; import java.net.InetSocketAddress; @@ -64,7 +74,27 @@ public class JdbcDriverTest { public static void startStaticServer() throws IOException { MockSpannerServiceImpl mockSpanner = new MockSpannerServiceImpl(); InetSocketAddress address = new InetSocketAddress("localhost", 0); - server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + server = + NettyServerBuilder.forAddress(address) + .addService(mockSpanner) + .intercept( + new ServerInterceptor() { + @Override + public Listener interceptCall( + ServerCall call, + Metadata headers, + ServerCallHandler next) { + String clientLibToken = + headers.get( + Metadata.Key.of("x-goog-api-client", Metadata.ASCII_STRING_MARSHALLER)); + assertNotNull(clientLibToken); + assertTrue( + clientLibToken.contains(ServiceOptions.getGoogApiClientLibName() + "/")); + return Contexts.interceptCall(Context.current(), call, headers, next); + } + }) + .build() + .start(); } @AfterClass From 2fc58ccc31f90fae7791edd390e5aa6a94c322a5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 6 Aug 2024 17:45:01 +0200 Subject: [PATCH 1355/1979] deps: update dependency org.hamcrest:hamcrest to v3 (#1697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency org.hamcrest:hamcrest to v3 * deps: remove separate hamcrest dependency management * chore: remove all usage of hamcrest --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 13 - .../cloud/spanner/jdbc/JdbcBlobTest.java | 177 ++--- .../cloud/spanner/jdbc/JdbcClobTest.java | 202 +++-- .../spanner/jdbc/JdbcConnectionTest.java | 10 +- .../jdbc/JdbcDatabaseMetaDataTest.java | 403 +++++----- .../spanner/jdbc/JdbcExceptionMatcher.java | 64 -- .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 221 +++--- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 96 +-- .../cloud/spanner/jdbc/JdbcStatementTest.java | 140 ++-- .../jdbc/SpannerJdbcExceptionMatcher.java | 70 -- .../spanner/jdbc/it/ITAbstractJdbcTest.java | 3 - .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 739 +++++++++--------- .../it/ITJdbcReadWriteAutocommitTest.java | 9 +- .../spanner/jdbc/it/ITJdbcScriptTest.java | 19 +- 14 files changed, 965 insertions(+), 1201 deletions(-) delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9cece1c6bcbe..59adb9d33d0c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -53,7 +53,6 @@ 3.0.2 1.4.4 4.11.0 - 2.2 0.31.1 @@ -182,23 +181,11 @@ - - org.hamcrest - hamcrest - ${hamcrest.version} - test - org.mockito mockito-core ${mockito.version} test - - - org.hamcrest - hamcrest-core - - junit diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java index 46b85fe2dcfb..e7be0ecee2e0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcBlobTest.java @@ -16,9 +16,10 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import com.google.rpc.Code; import java.io.IOException; @@ -74,35 +75,31 @@ public String toString() { @Test public void testLength() throws SQLException { JdbcBlob blob = new JdbcBlob(); - assertThat(blob.length(), is(equalTo(0L))); + assertEquals(0L, blob.length()); blob.setBytes(1L, new byte[] {1, 2, 3}); - assertThat(blob.length(), is(equalTo(3L))); + assertEquals(3L, blob.length()); blob.free(); - assertThat(blob.length(), is(equalTo(0L))); + assertEquals(0L, blob.length()); } @Test public void testGetBytes() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); - assertThat(blob.getBytes(1L, 5), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); - assertThat(blob.getBytes(2L, 5), is(equalTo(new byte[] {2, 3, 4, 5}))); - assertThat(blob.getBytes(2L, 3), is(equalTo(new byte[] {2, 3, 4}))); - assertThat(blob.getBytes(1L, 0), is(equalTo(new byte[] {}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5}, blob.getBytes(1L, 5)); + assertArrayEquals(new byte[] {2, 3, 4, 5}, blob.getBytes(2L, 5)); + assertArrayEquals(new byte[] {2, 3, 4}, blob.getBytes(2L, 3)); + assertArrayEquals(new byte[] {}, blob.getBytes(1L, 0)); // test invalid parameters PosLength[] params = new PosLength[] {PosLength.of(0L, 4), PosLength.of(-1L, 4), PosLength.of(1L, -1)}; for (PosLength param : params) { - boolean exception = false; - try { - blob.getBytes(param.pos, param.len); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> blob.getBytes(param.pos, param.len)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -119,31 +116,31 @@ public void testGetBinaryStream() throws SQLException, IOException { index++; } } - assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5}, buf); buf = new byte[10]; try (InputStream is = blob.getBinaryStream()) { - assertThat(is.read(buf), is(equalTo(5))); - assertThat(is.read(), is(equalTo(-1))); + assertEquals(5, is.read(buf)); + assertEquals(-1, is.read()); } - assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 4, 5, 0, 0, 0, 0, 0}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 0, 0, 0, 0, 0}, buf); } @Test public void testPosition() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); - assertThat(blob.position(new byte[] {1}, 1L), is(equalTo(1L))); - assertThat(blob.position(new byte[] {1, 2}, 1L), is(equalTo(1L))); - assertThat(blob.position(new byte[] {2}, 1L), is(equalTo(2L))); + assertEquals(1L, blob.position(new byte[] {1}, 1L)); + assertEquals(1L, blob.position(new byte[] {1, 2}, 1L)); + assertEquals(2L, blob.position(new byte[] {2}, 1L)); // note that the spec says that the method should return the position within the BLOB where the // pattern can be found, so it's not relative to the starting position. - assertThat(blob.position(new byte[] {2}, 2L), is(equalTo(2L))); - assertThat(blob.position(new byte[] {1, 2, 3, 4, 5}, 1L), is(equalTo(1L))); - assertThat(blob.position(new byte[] {1, 2, 3, 4, 5, 6}, 1L), is(equalTo(-1L))); - assertThat(blob.position(new byte[] {1, 2, 3, 4, 5}, 2L), is(equalTo(-1L))); - assertThat(blob.position(new byte[] {2}, 3L), is(equalTo(-1L))); - assertThat(blob.position(new byte[] {1}, 6L), is(equalTo(-1L))); + assertEquals(2L, blob.position(new byte[] {2}, 2L)); + assertEquals(1L, blob.position(new byte[] {1, 2, 3, 4, 5}, 1L)); + assertEquals(-1L, blob.position(new byte[] {1, 2, 3, 4, 5, 6}, 1L)); + assertEquals(-1L, blob.position(new byte[] {1, 2, 3, 4, 5}, 2L)); + assertEquals(-1L, blob.position(new byte[] {2}, 3L)); + assertEquals(-1L, blob.position(new byte[] {1}, 6L)); // test invalid parameters PosBytes[] params = @@ -151,15 +148,11 @@ public void testPosition() throws SQLException { PosBytes.of(0L, new byte[] {}), PosBytes.of(-1L, new byte[] {}), PosBytes.of(1L, null) }; for (PosBytes param : params) { - boolean exception = false; - try { - blob.position(param.bytes, param.pos); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> blob.position(param.bytes, param.pos)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -168,17 +161,17 @@ public void testPositionBlob() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); - assertThat(blob.position(createBlob((byte) 1), 1L), is(equalTo(1L))); - assertThat(blob.position(createBlob((byte) 1, (byte) 2), 1L), is(equalTo(1L))); - assertThat(blob.position(createBlob((byte) 2), 1L), is(equalTo(2L))); + assertEquals(1L, blob.position(createBlob((byte) 1), 1L)); + assertEquals(1L, blob.position(createBlob((byte) 1, (byte) 2), 1L)); + assertEquals(2L, blob.position(createBlob((byte) 2), 1L)); // note that the spec says that the method should return the position within the BLOB where the // pattern can be found, so it's not relative to the starting position. - assertThat(blob.position(createBlob((byte) 2), 2L), is(equalTo(2L))); - assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 1L), is(equalTo(1L))); - assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5, 6}), 1L), is(equalTo(-1L))); - assertThat(blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 2L), is(equalTo(-1L))); - assertThat(blob.position(createBlob(new byte[] {2}), 3L), is(equalTo(-1L))); - assertThat(blob.position(createBlob(new byte[] {1}), 6L), is(equalTo(-1L))); + assertEquals(2L, blob.position(createBlob((byte) 2), 2L)); + assertEquals(1L, blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 1L)); + assertEquals(-1L, blob.position(createBlob(new byte[] {1, 2, 3, 4, 5, 6}), 1L)); + assertEquals(-1L, blob.position(createBlob(new byte[] {1, 2, 3, 4, 5}), 2L)); + assertEquals(-1L, blob.position(createBlob(new byte[] {2}), 3L)); + assertEquals(-1L, blob.position(createBlob(new byte[] {1}), 6L)); // test invalid parameters PosBytes[] params = @@ -186,15 +179,11 @@ public void testPositionBlob() throws SQLException { PosBytes.of(0L, new byte[] {}), PosBytes.of(-1L, new byte[] {}), PosBytes.of(1L, null) }; for (PosBytes param : params) { - boolean exception = false; - try { - blob.position(createBlob(param.bytes), param.pos); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> blob.position(createBlob(param.bytes), param.pos)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -211,35 +200,35 @@ private JdbcBlob createBlob(byte... bytes) throws SQLException { public void testSetBytes() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3}); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3}, blob.getBytes(1L, 10)); blob.setBytes(2L, new byte[] {1}); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3}))); + assertArrayEquals(new byte[] {1, 1, 3}, blob.getBytes(1L, 10)); blob.setBytes(4L, new byte[] {4}); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3, 4}))); + assertArrayEquals(new byte[] {1, 1, 3, 4}, blob.getBytes(1L, 10)); blob.setBytes(8L, new byte[] {8}); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {1, 1, 3, 4, 0, 0, 0, 8}))); + assertArrayEquals(new byte[] {1, 1, 3, 4, 0, 0, 0, 8}, blob.getBytes(1L, 10)); } @Test public void testSetBytesOffsetLength() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(4L, new byte[] {1, 2, 3}, 0, 3); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0, 1, 2, 3}))); + assertArrayEquals(new byte[] {0, 0, 0, 1, 2, 3}, blob.getBytes(1L, 10)); blob.free(); blob.setBytes(4L, new byte[] {1, 2, 3}, 1, 3); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0, 2, 3}))); + assertArrayEquals(new byte[] {0, 0, 0, 2, 3}, blob.getBytes(1L, 10)); blob.free(); blob.setBytes(4L, new byte[] {1, 2, 3}, 3, 3); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0}))); + assertArrayEquals(new byte[] {0, 0, 0}, blob.getBytes(1L, 10)); blob.free(); blob.setBytes(4L, new byte[] {1, 2, 3}, 4, 3); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 0, 0}))); + assertArrayEquals(new byte[] {0, 0, 0}, blob.getBytes(1L, 10)); blob.setBytes(2L, new byte[] {1, 2, 3}, 0, 10); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 1, 2, 3}))); + assertArrayEquals(new byte[] {0, 1, 2, 3}, blob.getBytes(1L, 10)); blob.setBytes(3L, new byte[] {1, 2, 3}, 2, 10); - assertThat(blob.getBytes(1L, 10), is(equalTo(new byte[] {0, 1, 3, 3}))); + assertArrayEquals(new byte[] {0, 1, 3, 3}, blob.getBytes(1L, 10)); blob.setBytes(10L, new byte[] {1, 2, 3}, 2, 10); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {0, 1, 3, 3, 0, 0, 0, 0, 0, 3}))); + assertArrayEquals(new byte[] {0, 1, 3, 3, 0, 0, 0, 0, 0, 3}, blob.getBytes(1L, 20)); } @Test @@ -249,51 +238,49 @@ public void testSetBinaryStream() throws SQLException, IOException { try (OutputStream os = blob.setBinaryStream(1L)) { os.write(6); // no flush yet, so it should be unchanged - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5}, blob.getBytes(1L, 20)); os.flush(); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 2, 3, 4, 5}))); + assertArrayEquals(new byte[] {6, 2, 3, 4, 5}, blob.getBytes(1L, 20)); os.write(7); } // closing the stream should also flush the changes - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 7, 3, 4, 5}))); + assertArrayEquals(new byte[] {6, 7, 3, 4, 5}, blob.getBytes(1L, 20)); // test writing beyond the end of the stream try (OutputStream os = blob.setBinaryStream(1L)) { os.write(new byte[] {1, 2, 3, 4, 5, 6, 7}); // no flush yet, so it should be unchanged - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {6, 7, 3, 4, 5}))); + assertArrayEquals(new byte[] {6, 7, 3, 4, 5}, blob.getBytes(1L, 20)); os.flush(); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7}, blob.getBytes(1L, 20)); } - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7}, blob.getBytes(1L, 20)); // test writing from a position that is larger than 1 try (OutputStream os = blob.setBinaryStream(5L)) { os.write(new byte[] {1, 2, 3}); // no flush yet, so it should be unchanged - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5, 6, 7}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7}, blob.getBytes(1L, 20)); os.flush(); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 1, 2, 3}, blob.getBytes(1L, 20)); } // test writing from a position that is larger than the current length try (OutputStream os = blob.setBinaryStream(10L)) { os.write(new byte[] {1, 2, 3}); // no flush yet, so it should be unchanged - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 1, 2, 3}, blob.getBytes(1L, 20)); os.flush(); - assertThat( - blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}, blob.getBytes(1L, 20)); } // test writing a large number of bytes try (OutputStream os = blob.setBinaryStream(1L)) { os.write(new byte[2000]); // no flush yet, so it should be unchanged - assertThat( - blob.getBytes(1L, 3000), is(equalTo(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 1, 2, 3, 0, 0, 1, 2, 3}, blob.getBytes(1L, 3000)); os.flush(); - assertThat(blob.getBytes(1L, 3000), is(equalTo(new byte[2000]))); + assertArrayEquals(new byte[2000], blob.getBytes(1L, 3000)); } } @@ -301,20 +288,20 @@ public void testSetBinaryStream() throws SQLException, IOException { public void testTruncate() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5}, blob.getBytes(1L, 20)); blob.truncate(3); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3}))); + assertArrayEquals(new byte[] {1, 2, 3}, blob.getBytes(1L, 20)); blob.truncate(0); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {}))); + assertArrayEquals(new byte[] {}, blob.getBytes(1L, 20)); } @Test public void testFree() throws SQLException { JdbcBlob blob = new JdbcBlob(); blob.setBytes(1L, new byte[] {1, 2, 3, 4, 5}); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {1, 2, 3, 4, 5}))); + assertArrayEquals(new byte[] {1, 2, 3, 4, 5}, blob.getBytes(1L, 20)); blob.free(); - assertThat(blob.getBytes(1L, 20), is(equalTo(new byte[] {}))); + assertArrayEquals(new byte[] {}, blob.getBytes(1L, 20)); } @Test @@ -331,19 +318,19 @@ public void testGetBinaryStreamPosLength() throws SQLException, IOException { index++; } } - assertThat(buf, is(equalTo(new byte[] {1, 2, 3, 0, 0}))); + assertArrayEquals(new byte[] {1, 2, 3, 0, 0}, buf); buf = new byte[10]; try (InputStream is = blob.getBinaryStream(4L, 10)) { - assertThat(is.read(buf), is(equalTo(2))); - assertThat(is.read(), is(equalTo(-1))); + assertEquals(2, is.read(buf)); + assertEquals(-1, is.read()); } - assertThat(buf, is(equalTo(new byte[] {4, 5, 0, 0, 0, 0, 0, 0, 0, 0}))); + assertArrayEquals(new byte[] {4, 5, 0, 0, 0, 0, 0, 0, 0, 0}, buf); buf = new byte[10]; try (InputStream is = blob.getBinaryStream(6L, 10)) { - assertThat(is.read(buf), is(equalTo(-1))); + assertEquals(-1L, is.read(buf)); } - assertThat(buf, is(equalTo(new byte[10]))); + assertArrayEquals(new byte[10], buf); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java index b195229180da..573200ddf660 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcClobTest.java @@ -16,10 +16,10 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import com.google.rpc.Code; import java.io.IOException; @@ -75,36 +75,32 @@ public String toString() { public void testLength() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "test"); - assertThat(clob.length(), is(equalTo(4L))); + assertEquals(4L, clob.length()); clob.setString(1L, "test-test"); - assertThat(clob.length(), is(equalTo(9L))); + assertEquals(9L, clob.length()); } @Test public void testGetSubstring() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "test"); - assertThat(clob.getSubString(1, 4), is(equalTo("test"))); - assertThat(clob.getSubString(1, 2), is(equalTo("te"))); - assertThat(clob.getSubString(3, 2), is(equalTo("st"))); - assertThat(clob.getSubString(1, 5), is(equalTo("test"))); - assertThat(clob.getSubString(4, 5), is(equalTo("t"))); - assertThat(clob.getSubString(5, 5), is(equalTo(""))); - assertThat(clob.getSubString(6, 5), is(equalTo(""))); + assertEquals("test", clob.getSubString(1, 4)); + assertEquals("te", clob.getSubString(1, 2)); + assertEquals("st", clob.getSubString(3, 2)); + assertEquals("test", clob.getSubString(1, 5)); + assertEquals("t", clob.getSubString(4, 5)); + assertEquals("", clob.getSubString(5, 5)); + assertEquals("", clob.getSubString(6, 5)); // test invalid parameters PosLength[] params = new PosLength[] {PosLength.of(0L, 4), PosLength.of(-1L, 4), PosLength.of(1L, -1)}; for (PosLength param : params) { - boolean exception = false; - try { - clob.getSubString(param.pos, param.len); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> clob.getSubString(param.pos, param.len)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -116,12 +112,12 @@ public void testGetCharacterStream() throws SQLException, IOException { try (Reader reader = clob.getCharacterStream()) { assertEquals(4, reader.read(cbuf, 0, 4)); } - assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + assertArrayEquals(new char[] {'t', 'e', 's', 't'}, cbuf); try (Reader reader = clob.getCharacterStream()) { assertEquals(2, reader.read(cbuf, 0, 2)); assertEquals(2, reader.read(cbuf, 2, 2)); } - assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + assertArrayEquals(new char[] {'t', 'e', 's', 't'}, cbuf); try (Reader reader = clob.getCharacterStream()) { assertEquals(2, reader.read(cbuf, 0, 2)); // changing the value of the clob will not change a character stream that has already been @@ -129,36 +125,32 @@ public void testGetCharacterStream() throws SQLException, IOException { clob.setString(1L, "foobar"); assertEquals(2, reader.read(cbuf, 2, 2)); } - assertThat(cbuf, is(equalTo(new char[] {'t', 'e', 's', 't'}))); + assertArrayEquals(new char[] {'t', 'e', 's', 't'}, cbuf); } @Test public void testPositionString() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "test"); - assertThat(clob.position("st", 1L), is(equalTo(3L))); + assertEquals(3L, clob.position("st", 1L)); clob.setString(1L, "foobarfoobar"); - assertThat(clob.position("bar", 1L), is(equalTo(4L))); - assertThat(clob.position("bar", 2L), is(equalTo(4L))); - assertThat(clob.position("bar", 5L), is(equalTo(10L))); - assertThat(clob.position("bar", 8L), is(equalTo(10L))); - assertThat(clob.position("bar", 10L), is(equalTo(10L))); - assertThat(clob.position("bar", 11L), is(equalTo(-1L))); - assertThat(clob.position("bar", 100L), is(equalTo(-1L))); - assertThat(clob.position("not_there", 1L), is(equalTo(-1L))); + assertEquals(4L, clob.position("bar", 1L)); + assertEquals(4L, clob.position("bar", 2L)); + assertEquals(10L, clob.position("bar", 5L)); + assertEquals(10L, clob.position("bar", 8L)); + assertEquals(10L, clob.position("bar", 10L)); + assertEquals(-1L, clob.position("bar", 11L)); + assertEquals(-1L, clob.position("bar", 100L)); + assertEquals(-1L, clob.position("not_there", 1L)); // test invalid parameters PosString[] params = new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; for (PosString param : params) { - boolean exception = false; - try { - clob.position(param.str, param.pos); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> clob.position(param.str, param.pos)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -168,32 +160,32 @@ public void testPositionClob() throws SQLException { clob.setString(1L, "test"); JdbcClob search = new JdbcClob(); search.setString(1L, "st"); - assertThat(clob.position(search, 1L), is(equalTo(3L))); + assertEquals(3L, clob.position(search, 1L)); clob.setString(1L, "foobarfoobar"); search.setString(1L, "bar"); - assertThat(clob.position(search, 1L), is(equalTo(4L))); - assertThat(clob.position(search, 2L), is(equalTo(4L))); - assertThat(clob.position(search, 5L), is(equalTo(10L))); - assertThat(clob.position(search, 8L), is(equalTo(10L))); - assertThat(clob.position(search, 10L), is(equalTo(10L))); - assertThat(clob.position(search, 11L), is(equalTo(-1L))); - assertThat(clob.position(search, 100L), is(equalTo(-1L))); + assertEquals(4L, clob.position(search, 1L)); + assertEquals(4L, clob.position(search, 2L)); + assertEquals(10L, clob.position(search, 5L)); + assertEquals(10L, clob.position(search, 8L)); + assertEquals(10L, clob.position(search, 10L)); + assertEquals(-1L, clob.position(search, 11L)); + assertEquals(-1L, clob.position(search, 100L)); search.setString(1L, "not_there"); - assertThat(clob.position(search, 1L), is(equalTo(-1L))); + assertEquals(-1L, clob.position(search, 1L)); // test invalid parameters PosString[] params = new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; for (PosString param : params) { - boolean exception = false; - try { - search.setString(1L, param.str); - clob.position(search, param.pos); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows( + SQLException.class, + () -> { + search.setString(1L, param.str); + clob.position(search, param.pos); + }); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -201,30 +193,26 @@ public void testPositionClob() throws SQLException { public void testSetString() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "test"); - assertThat(clob.getSubString(1L, 4), is(equalTo("test"))); + assertEquals("test", clob.getSubString(1L, 4)); clob.setString(1L, "bar"); - assertThat(clob.getSubString(1L, 4), is(equalTo("bart"))); + assertEquals("bart", clob.getSubString(1L, 4)); clob.setString(1L, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); clob.setString(2L, "foobar"); - assertThat(clob.getSubString(1L, 7), is(equalTo("ffoobar"))); + assertEquals("ffoobar", clob.getSubString(1L, 7)); clob.setString(8L, "test"); - assertThat(clob.getSubString(1L, 11), is(equalTo("ffoobartest"))); + assertEquals("ffoobartest", clob.getSubString(1L, 11)); clob.setString(15, "end"); - assertThat(clob.getSubString(1L, 17), is(equalTo("ffoobartest end"))); + assertEquals("ffoobartest end", clob.getSubString(1L, 17)); // test invalid parameters PosString[] params = new PosString[] {PosString.of(0L, "bar"), PosString.of(-1L, "bar"), PosString.of(1L, null)}; for (PosString param : params) { - boolean exception = false; - try { - clob.setString(param.pos, param.str); - } catch (SQLException e) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } - assertThat(param.toString(), exception, is(true)); + SQLException sqlException = + assertThrows(SQLException.class, () -> clob.setString(param.pos, param.str)); + assertTrue(sqlException instanceof JdbcSqlException); + JdbcSqlException jdbcSqlException = (JdbcSqlException) sqlException; + assertEquals(Code.INVALID_ARGUMENT, jdbcSqlException.getCode()); } } @@ -232,99 +220,99 @@ public void testSetString() throws SQLException { public void testSetStringOffsetLen() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "test", 2, 3); - assertThat(clob.getSubString(1L, 4), is(equalTo("est"))); + assertEquals("est", clob.getSubString(1L, 4)); clob.setString(1L, "bar", 1, 1); - assertThat(clob.getSubString(1L, 4), is(equalTo("bst"))); + assertEquals("bst", clob.getSubString(1L, 4)); clob.setString(1L, "foobar", 1, 6); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); clob.setString(2L, "foobar", 2, 5); - assertThat(clob.getSubString(1L, 7), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 7)); clob.setString(8L, "test", 4, 1); - assertThat(clob.getSubString(1L, 8), is(equalTo("foobar t"))); + assertEquals("foobar t", clob.getSubString(1L, 8)); clob.setString(15, "end", 1, 3); - assertThat(clob.getSubString(1L, 17), is(equalTo("foobar t end"))); + assertEquals("foobar t end", clob.getSubString(1L, 17)); } @Test public void testSetCharacterStream() throws SQLException, IOException { JdbcClob clob = new JdbcClob(); clob.setString(1, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); try (Writer writer = clob.setCharacterStream(1L)) { writer.write("t"); // not yet flushed, there should be no change - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); writer.flush(); // after a flush the change should be visible - assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + assertEquals("toobar", clob.getSubString(1L, 6)); writer.write("est"); } - // close should also autoflush - assertThat(clob.getSubString(1L, 6), is(equalTo("testar"))); + // close should also auto-flush + assertEquals("testar", clob.getSubString(1L, 6)); // start all over clob.free(); clob.setString(1, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); try (Writer writer = clob.setCharacterStream(5L)) { writer.write("t"); // not yet flushed, there should be no change - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); writer.flush(); // after a flush the change should be visible - assertThat(clob.getSubString(1L, 6), is(equalTo("foobtr"))); + assertEquals("foobtr", clob.getSubString(1L, 6)); writer.write("est"); } - // close should also autoflush - assertThat(clob.getSubString(1L, 8), is(equalTo("foobtest"))); + // close should also auto-flush + assertEquals("foobtest", clob.getSubString(1L, 8)); // do a test with multiple flushes clob.free(); clob.setString(1, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); try (Writer writer = clob.setCharacterStream(1L)) { writer.write("t"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); writer.flush(); - assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + assertEquals("toobar", clob.getSubString(1L, 6)); writer.write("est"); - assertThat(clob.getSubString(1L, 6), is(equalTo("toobar"))); + assertEquals("toobar", clob.getSubString(1L, 6)); writer.flush(); - assertThat(clob.getSubString(1L, 6), is(equalTo("testar"))); + assertEquals("testar", clob.getSubString(1L, 6)); } - assertThat(clob.getSubString(1L, 8), is(equalTo("testar"))); + assertEquals("testar", clob.getSubString(1L, 8)); // writer after end clob.free(); clob.setString(1, "foobar"); - assertThat(clob.getSubString(1L, 10), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 10)); try (Writer writer = clob.setCharacterStream(10L)) { writer.write("t"); - assertThat(clob.getSubString(1L, 20), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 20)); writer.flush(); - assertThat(clob.getSubString(1L, 20), is(equalTo("foobar t"))); + assertEquals("foobar t", clob.getSubString(1L, 20)); writer.write("est"); } - assertThat(clob.getSubString(1L, 20), is(equalTo("foobar test"))); + assertEquals("foobar test", clob.getSubString(1L, 20)); } @Test public void testTruncate() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); clob.truncate(3L); - assertThat(clob.getSubString(1L, 6), is(equalTo("foo"))); + assertEquals("foo", clob.getSubString(1L, 6)); clob.truncate(0L); - assertThat(clob.getSubString(1L, 6), is(equalTo(""))); + assertEquals("", clob.getSubString(1L, 6)); } @Test public void testFree() throws SQLException { JdbcClob clob = new JdbcClob(); clob.setString(1L, "foobar"); - assertThat(clob.getSubString(1L, 6), is(equalTo("foobar"))); + assertEquals("foobar", clob.getSubString(1L, 6)); clob.free(); - assertThat(clob.getSubString(1L, 6), is(equalTo(""))); + assertEquals("", clob.getSubString(1L, 6)); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index cda51a7710c4..5a9618e9acaf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -24,7 +24,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -118,7 +117,7 @@ public void testAutoCommit() throws SQLException { } @Test - public void testReadOnly() { + public void testReadOnly() throws SQLException { ConnectionOptions options = mockOptions(); when(options.isAutocommit()).thenReturn(true); when(options.isReadOnly()).thenReturn(true); @@ -129,10 +128,9 @@ public void testReadOnly() { // start a transaction connection.createStatement().execute("begin transaction"); // setting readonly should no longer be allowed - connection.setReadOnly(true); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(JdbcExceptionMatcher.matchCode(Code.FAILED_PRECONDITION).matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> connection.setReadOnly(true)); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 1dc95655f130..3e94a4ceb3ef 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -16,12 +16,9 @@ package com.google.cloud.spanner.jdbc; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; 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 static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -65,100 +62,97 @@ public static Object[] data() { public void testTrivialMethods() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); - assertThat(meta.allProceduresAreCallable(), is(true)); - assertThat(meta.allTablesAreSelectable(), is(true)); - assertThat(meta.autoCommitFailureClosesAllResultSets(), is(false)); - assertThat(meta.dataDefinitionCausesTransactionCommit(), is(false)); - assertThat(meta.dataDefinitionIgnoredInTransactions(), is(false)); + assertTrue(meta.allProceduresAreCallable()); + assertTrue(meta.allTablesAreSelectable()); + assertFalse(meta.autoCommitFailureClosesAllResultSets()); + assertFalse(meta.dataDefinitionCausesTransactionCommit()); + assertFalse(meta.dataDefinitionIgnoredInTransactions()); for (int type : new int[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE }) { - assertThat(meta.deletesAreDetected(type), is(false)); - assertThat(meta.insertsAreDetected(type), is(false)); - assertThat(meta.updatesAreDetected(type), is(false)); - assertThat(meta.ownDeletesAreVisible(type), is(false)); - assertThat(meta.ownInsertsAreVisible(type), is(false)); - assertThat(meta.ownUpdatesAreVisible(type), is(false)); - assertThat(meta.othersDeletesAreVisible(type), is(false)); - assertThat(meta.othersInsertsAreVisible(type), is(false)); - assertThat(meta.othersUpdatesAreVisible(type), is(false)); + assertFalse(meta.deletesAreDetected(type)); + assertFalse(meta.insertsAreDetected(type)); + assertFalse(meta.updatesAreDetected(type)); + assertFalse(meta.ownDeletesAreVisible(type)); + assertFalse(meta.ownInsertsAreVisible(type)); + assertFalse(meta.ownUpdatesAreVisible(type)); + assertFalse(meta.othersDeletesAreVisible(type)); + assertFalse(meta.othersInsertsAreVisible(type)); + assertFalse(meta.othersUpdatesAreVisible(type)); } - assertThat(meta.doesMaxRowSizeIncludeBlobs(), is(true)); - assertThat(meta.generatedKeyAlwaysReturned(), is(false)); - assertThat(meta.getCatalogSeparator(), is(equalTo("."))); - assertThat(meta.getCatalogTerm(), is(equalTo("CATALOG"))); - assertThat(meta.getDatabaseMajorVersion(), is(equalTo(DATABASE_MAJOR_VERSION))); - assertThat(meta.getDatabaseMinorVersion(), is(equalTo(DATABASE_MINOR_VERSION))); - assertThat(meta.getDatabaseProductName(), is(equalTo(DATABASE_PRODUCT_NAME))); - assertThat( - meta.getDatabaseProductVersion(), - is(equalTo(DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION))); - assertThat( - meta.getDefaultTransactionIsolation(), is(equalTo(Connection.TRANSACTION_SERIALIZABLE))); - assertThat(meta.getDriverName(), is(equalTo("com.google.cloud.spanner.jdbc.JdbcDriver"))); - assertThat(meta.getExtraNameCharacters(), is(equalTo(""))); - assertThat(meta.getIdentifierQuoteString(), is(equalTo("`"))); - assertThat(meta.getJDBCMajorVersion(), is(equalTo(4))); - assertThat(meta.getJDBCMinorVersion(), is(equalTo(1))); // Java 7 is JDBC 4.1 - assertThat(meta.getMaxBinaryLiteralLength(), is(equalTo(0))); - assertThat(meta.getMaxCatalogNameLength(), is(equalTo(0))); - assertThat(meta.getMaxCharLiteralLength(), is(equalTo(0))); - assertThat(meta.getMaxColumnNameLength(), is(equalTo(128))); - assertThat(meta.getMaxColumnsInGroupBy(), is(equalTo(1000))); - assertThat(meta.getMaxColumnsInIndex(), is(equalTo(16))); - assertThat(meta.getMaxColumnsInOrderBy(), is(equalTo(0))); - assertThat(meta.getMaxColumnsInSelect(), is(equalTo(0))); - assertThat(meta.getMaxColumnsInTable(), is(equalTo(1024))); - assertThat(meta.getMaxConnections(), is(equalTo(0))); // there is a max number of sessions, but - // that is not the same as connections - assertThat(meta.getMaxCursorNameLength(), is(equalTo(0))); - assertThat(meta.getMaxIndexLength(), is(equalTo(8000))); - assertThat(meta.getMaxProcedureNameLength(), is(equalTo(0))); - assertThat(meta.getMaxRowSize(), is(equalTo(0))); - assertThat(meta.getMaxSchemaNameLength(), is(equalTo(0))); - assertThat(meta.getMaxStatementLength(), is(equalTo(1000000))); - assertThat(meta.getMaxStatements(), is(equalTo(0))); - assertThat(meta.getMaxTableNameLength(), is(equalTo(128))); - assertThat(meta.getMaxTablesInSelect(), is(equalTo(0))); - assertThat(meta.getMaxUserNameLength(), is(equalTo(0))); - assertThat(meta.getProcedureTerm(), is(equalTo("PROCEDURE"))); - assertThat(meta.getResultSetHoldability(), is(equalTo(ResultSet.CLOSE_CURSORS_AT_COMMIT))); - assertThat(meta.getRowIdLifetime(), is(equalTo(RowIdLifetime.ROWID_UNSUPPORTED))); - assertThat(meta.getSchemaTerm(), is(equalTo("SCHEMA"))); - assertThat(meta.getSearchStringEscape(), is(equalTo("\\"))); - assertThat(meta.getSQLStateType(), is(equalTo(DatabaseMetaData.sqlStateSQL))); - assertThat(meta.locatorsUpdateCopy(), is(true)); - assertThat(meta.nullsAreSortedHigh(), is(false)); - assertThat(meta.nullsAreSortedLow(), is(true)); - assertThat(meta.nullsAreSortedAtStart(), is(false)); - assertThat(meta.nullsAreSortedAtEnd(), is(false)); - assertThat(meta.nullPlusNonNullIsNull(), is(true)); - assertThat(meta.isCatalogAtStart(), is(false)); - assertThat(meta.isReadOnly(), is(equalTo(connection.isReadOnly()))); - assertThat(meta.storesLowerCaseIdentifiers(), is(false)); - assertThat(meta.storesLowerCaseQuotedIdentifiers(), is(false)); - assertThat(meta.storesMixedCaseIdentifiers(), is(true)); - assertThat(meta.storesMixedCaseQuotedIdentifiers(), is(true)); - assertThat(meta.storesUpperCaseIdentifiers(), is(false)); - assertThat(meta.storesUpperCaseQuotedIdentifiers(), is(false)); - assertThat(meta.supportsAlterTableWithAddColumn(), is(true)); - assertThat(meta.supportsAlterTableWithDropColumn(), is(true)); - assertThat(meta.supportsANSI92EntryLevelSQL(), is(false)); - assertThat(meta.supportsANSI92FullSQL(), is(false)); - assertThat(meta.supportsANSI92IntermediateSQL(), is(false)); - assertThat(meta.supportsBatchUpdates(), is(true)); - assertThat(meta.supportsCatalogsInDataManipulation(), is(false)); - assertThat(meta.supportsCatalogsInIndexDefinitions(), is(false)); - assertThat(meta.supportsCatalogsInPrivilegeDefinitions(), is(false)); - assertThat(meta.supportsCatalogsInProcedureCalls(), is(false)); - assertThat(meta.supportsCatalogsInTableDefinitions(), is(false)); - assertThat(meta.supportsColumnAliasing(), is(true)); + assertTrue(meta.doesMaxRowSizeIncludeBlobs()); + assertFalse(meta.generatedKeyAlwaysReturned()); + assertEquals(".", meta.getCatalogSeparator()); + assertEquals("CATALOG", meta.getCatalogTerm()); + assertEquals(DATABASE_MAJOR_VERSION, meta.getDatabaseMajorVersion()); + assertEquals(DATABASE_MINOR_VERSION, meta.getDatabaseMinorVersion()); + assertEquals(DATABASE_PRODUCT_NAME, meta.getDatabaseProductName()); + assertEquals( + DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION, meta.getDatabaseProductVersion()); + assertEquals(Connection.TRANSACTION_SERIALIZABLE, meta.getDefaultTransactionIsolation()); + assertEquals("com.google.cloud.spanner.jdbc.JdbcDriver", meta.getDriverName()); + assertEquals("", meta.getExtraNameCharacters()); + assertEquals("`", meta.getIdentifierQuoteString()); + assertEquals(4, meta.getJDBCMajorVersion()); + assertEquals(1, meta.getJDBCMinorVersion()); // Java 7 is JDBC 4.1 + assertEquals(0, meta.getMaxBinaryLiteralLength()); + assertEquals(0, meta.getMaxCatalogNameLength()); + assertEquals(0, meta.getMaxCharLiteralLength()); + assertEquals(128, meta.getMaxColumnNameLength()); + assertEquals(1000, meta.getMaxColumnsInGroupBy()); + assertEquals(16, meta.getMaxColumnsInIndex()); + assertEquals(0, meta.getMaxColumnsInOrderBy()); + assertEquals(0, meta.getMaxColumnsInSelect()); + assertEquals(1024, meta.getMaxColumnsInTable()); + assertEquals(0, meta.getMaxConnections()); + assertEquals(0, meta.getMaxCursorNameLength()); + assertEquals(8000, meta.getMaxIndexLength()); + assertEquals(0, meta.getMaxProcedureNameLength()); + assertEquals(0, meta.getMaxRowSize()); + assertEquals(0, meta.getMaxSchemaNameLength()); + assertEquals(1000000, meta.getMaxStatementLength()); + assertEquals(0, meta.getMaxStatements()); + assertEquals(128, meta.getMaxTableNameLength()); + assertEquals(0, meta.getMaxTablesInSelect()); + assertEquals(0, meta.getMaxUserNameLength()); + assertEquals("PROCEDURE", meta.getProcedureTerm()); + assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, meta.getResultSetHoldability()); + assertEquals(RowIdLifetime.ROWID_UNSUPPORTED, meta.getRowIdLifetime()); + assertEquals("SCHEMA", meta.getSchemaTerm()); + assertEquals("\\", meta.getSearchStringEscape()); + assertEquals(DatabaseMetaData.sqlStateSQL, meta.getSQLStateType()); + assertTrue(meta.locatorsUpdateCopy()); + assertFalse(meta.nullsAreSortedHigh()); + assertTrue(meta.nullsAreSortedLow()); + assertFalse(meta.nullsAreSortedAtStart()); + assertFalse(meta.nullsAreSortedAtEnd()); + assertTrue(meta.nullPlusNonNullIsNull()); + assertFalse(meta.isCatalogAtStart()); + assertEquals(connection.isReadOnly(), meta.isReadOnly()); + assertFalse(meta.storesLowerCaseIdentifiers()); + assertFalse(meta.storesLowerCaseQuotedIdentifiers()); + assertTrue(meta.storesMixedCaseIdentifiers()); + assertTrue(meta.storesMixedCaseQuotedIdentifiers()); + assertFalse(meta.storesUpperCaseIdentifiers()); + assertFalse(meta.storesUpperCaseQuotedIdentifiers()); + assertTrue(meta.supportsAlterTableWithAddColumn()); + assertTrue(meta.supportsAlterTableWithDropColumn()); + assertFalse(meta.supportsANSI92EntryLevelSQL()); + assertFalse(meta.supportsANSI92FullSQL()); + assertFalse(meta.supportsANSI92IntermediateSQL()); + assertTrue(meta.supportsBatchUpdates()); + assertFalse(meta.supportsCatalogsInDataManipulation()); + assertFalse(meta.supportsCatalogsInIndexDefinitions()); + assertFalse(meta.supportsCatalogsInPrivilegeDefinitions()); + assertFalse(meta.supportsCatalogsInProcedureCalls()); + assertFalse(meta.supportsCatalogsInTableDefinitions()); + assertTrue(meta.supportsColumnAliasing()); // Note that the supportsConvert() method indicates whether the server side function CONVERT is // supported, not what the JDBC driver might be able to convert on the client side. - assertThat(meta.supportsConvert(), is(false)); + assertFalse(meta.supportsConvert()); int[] types = new int[] { Types.ARRAY, @@ -201,77 +195,76 @@ public void testTrivialMethods() throws SQLException { }; for (int from : types) { for (int to : types) { - assertThat(meta.supportsConvert(from, to), is(false)); + assertFalse(meta.supportsConvert(from, to)); } } - assertThat(meta.supportsCoreSQLGrammar(), is(false)); - assertThat(meta.supportsCorrelatedSubqueries(), is(true)); - assertThat(meta.supportsDataDefinitionAndDataManipulationTransactions(), is(false)); - assertThat(meta.supportsDataManipulationTransactionsOnly(), is(true)); - assertThat(meta.supportsDifferentTableCorrelationNames(), is(false)); - assertThat(meta.supportsExpressionsInOrderBy(), is(true)); - assertThat(meta.supportsExtendedSQLGrammar(), is(false)); - assertThat(meta.supportsFullOuterJoins(), is(true)); - assertThat(meta.supportsGetGeneratedKeys(), is(false)); - assertThat(meta.supportsGroupBy(), is(true)); - assertThat(meta.supportsGroupByBeyondSelect(), is(true)); - assertThat(meta.supportsGroupByUnrelated(), is(true)); - assertThat(meta.supportsIntegrityEnhancementFacility(), is(false)); - assertThat(meta.supportsLikeEscapeClause(), is(true)); - assertThat(meta.supportsLimitedOuterJoins(), is(true)); - assertThat(meta.supportsMinimumSQLGrammar(), is(false)); - assertThat(meta.supportsMixedCaseIdentifiers(), is(false)); - assertThat(meta.supportsMixedCaseQuotedIdentifiers(), is(false)); - assertThat(meta.supportsMultipleOpenResults(), is(true)); - assertThat(meta.supportsMultipleResultSets(), is(true)); - assertThat(meta.supportsMultipleTransactions(), is(true)); - assertThat(meta.supportsNamedParameters(), is(false)); - assertThat(meta.supportsNonNullableColumns(), is(true)); - assertThat(meta.supportsOpenCursorsAcrossCommit(), is(false)); - assertThat(meta.supportsOpenCursorsAcrossRollback(), is(false)); - assertThat(meta.supportsOpenStatementsAcrossCommit(), is(true)); - assertThat(meta.supportsOpenStatementsAcrossRollback(), is(true)); - assertThat(meta.supportsOrderByUnrelated(), is(true)); - assertThat(meta.supportsOuterJoins(), is(true)); - assertThat(meta.supportsPositionedDelete(), is(false)); - assertThat(meta.supportsPositionedUpdate(), is(false)); + assertFalse(meta.supportsCoreSQLGrammar()); + assertTrue(meta.supportsCorrelatedSubqueries()); + assertFalse(meta.supportsDataDefinitionAndDataManipulationTransactions()); + assertTrue(meta.supportsDataManipulationTransactionsOnly()); + assertFalse(meta.supportsDifferentTableCorrelationNames()); + assertTrue(meta.supportsExpressionsInOrderBy()); + assertFalse(meta.supportsExtendedSQLGrammar()); + assertTrue(meta.supportsFullOuterJoins()); + assertFalse(meta.supportsGetGeneratedKeys()); + assertTrue(meta.supportsGroupBy()); + assertTrue(meta.supportsGroupByBeyondSelect()); + assertTrue(meta.supportsGroupByUnrelated()); + assertFalse(meta.supportsIntegrityEnhancementFacility()); + assertTrue(meta.supportsLikeEscapeClause()); + assertTrue(meta.supportsLimitedOuterJoins()); + assertFalse(meta.supportsMinimumSQLGrammar()); + assertFalse(meta.supportsMixedCaseIdentifiers()); + assertFalse(meta.supportsMixedCaseQuotedIdentifiers()); + assertTrue(meta.supportsMultipleOpenResults()); + assertTrue(meta.supportsMultipleResultSets()); + assertTrue(meta.supportsMultipleTransactions()); + assertFalse(meta.supportsNamedParameters()); + assertTrue(meta.supportsNonNullableColumns()); + assertFalse(meta.supportsOpenCursorsAcrossCommit()); + assertFalse(meta.supportsOpenCursorsAcrossRollback()); + assertTrue(meta.supportsOpenStatementsAcrossCommit()); + assertTrue(meta.supportsOpenStatementsAcrossRollback()); + assertTrue(meta.supportsOrderByUnrelated()); + assertTrue(meta.supportsOuterJoins()); + assertFalse(meta.supportsPositionedDelete()); + assertFalse(meta.supportsPositionedUpdate()); for (int type : new int[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.TYPE_SCROLL_SENSITIVE }) { - assertThat(meta.supportsResultSetType(type), is(type == ResultSet.TYPE_FORWARD_ONLY)); + assertEquals(type == ResultSet.TYPE_FORWARD_ONLY, meta.supportsResultSetType(type)); for (int concur : new int[] {ResultSet.CONCUR_READ_ONLY, ResultSet.CONCUR_UPDATABLE}) { - assertThat( - meta.supportsResultSetConcurrency(type, concur), - is(type == ResultSet.TYPE_FORWARD_ONLY && concur == ResultSet.CONCUR_READ_ONLY)); + assertEquals( + type == ResultSet.TYPE_FORWARD_ONLY && concur == ResultSet.CONCUR_READ_ONLY, + meta.supportsResultSetConcurrency(type, concur)); } } - assertThat(meta.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT), is(true)); - assertThat(meta.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT), is(false)); - assertThat(meta.supportsSavepoints(), is(false)); - assertThat(meta.supportsSchemasInDataManipulation(), is(false)); - assertThat(meta.supportsSchemasInIndexDefinitions(), is(false)); - assertThat(meta.supportsSchemasInPrivilegeDefinitions(), is(false)); - assertThat(meta.supportsSchemasInProcedureCalls(), is(false)); - assertThat(meta.supportsSchemasInTableDefinitions(), is(false)); - assertThat(meta.supportsSelectForUpdate(), is(false)); - assertThat(meta.supportsStatementPooling(), is(false)); - assertThat(meta.supportsStoredFunctionsUsingCallSyntax(), is(false)); - assertThat(meta.supportsStoredProcedures(), is(false)); - assertThat(meta.supportsSubqueriesInComparisons(), is(true)); - assertThat(meta.supportsSubqueriesInExists(), is(true)); - assertThat(meta.supportsSubqueriesInIns(), is(true)); - assertThat(meta.supportsSubqueriesInQuantifieds(), is(true)); - assertThat(meta.supportsTableCorrelationNames(), is(true)); - assertThat(meta.supportsTransactions(), is(true)); - assertThat(meta.supportsUnion(), is(true)); - assertThat(meta.supportsUnionAll(), is(true)); - assertThat(meta.usesLocalFiles(), is(false)); - assertThat(meta.usesLocalFilePerTable(), is(false)); - assertThat( - meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE), is(true)); + assertTrue(meta.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT)); + assertFalse(meta.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT)); + assertFalse(meta.supportsSavepoints()); + assertFalse(meta.supportsSchemasInDataManipulation()); + assertFalse(meta.supportsSchemasInIndexDefinitions()); + assertFalse(meta.supportsSchemasInPrivilegeDefinitions()); + assertFalse(meta.supportsSchemasInProcedureCalls()); + assertFalse(meta.supportsSchemasInTableDefinitions()); + assertFalse(meta.supportsSelectForUpdate()); + assertFalse(meta.supportsStatementPooling()); + assertFalse(meta.supportsStoredFunctionsUsingCallSyntax()); + assertFalse(meta.supportsStoredProcedures()); + assertTrue(meta.supportsSubqueriesInComparisons()); + assertTrue(meta.supportsSubqueriesInExists()); + assertTrue(meta.supportsSubqueriesInIns()); + assertTrue(meta.supportsSubqueriesInQuantifieds()); + assertTrue(meta.supportsTableCorrelationNames()); + assertTrue(meta.supportsTransactions()); + assertTrue(meta.supportsUnion()); + assertTrue(meta.supportsUnionAll()); + assertFalse(meta.usesLocalFiles()); + assertFalse(meta.usesLocalFilePerTable()); + assertTrue(meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE)); for (int level : new int[] { Connection.TRANSACTION_NONE, @@ -279,17 +272,17 @@ public void testTrivialMethods() throws SQLException { Connection.TRANSACTION_READ_UNCOMMITTED, Connection.TRANSACTION_REPEATABLE_READ }) { - assertThat(meta.supportsTransactionIsolationLevel(level), is(false)); + assertFalse(meta.supportsTransactionIsolationLevel(level)); } assertEquals(10485760L, meta.getMaxLogicalLobSize()); assertFalse(meta.supportsRefCursors()); // trivial tests that guarantee that the function works, but the return value doesn't matter - assertThat(meta.getNumericFunctions(), is(notNullValue())); - assertThat(meta.getSQLKeywords(), is(notNullValue())); - assertThat(meta.getStringFunctions(), is(notNullValue())); - assertThat(meta.getSystemFunctions(), is(notNullValue())); - assertThat(meta.getTimeDateFunctions(), is(notNullValue())); + assertNotNull(meta.getNumericFunctions()); + assertNotNull(meta.getSQLKeywords()); + assertNotNull(meta.getStringFunctions()); + assertNotNull(meta.getSystemFunctions()); + assertNotNull(meta.getTimeDateFunctions()); } @Test @@ -297,9 +290,9 @@ public void testGetAttributes() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getAttributes(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(21))); + assertEquals(21, rsmd.getColumnCount()); } } @@ -314,9 +307,9 @@ public void testGetBestRowIdentifier() throws SQLException { TEST_TABLE, DatabaseMetaData.bestRowTransaction, false)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(8))); + assertEquals(8, rsmd.getColumnCount()); } } @@ -327,11 +320,11 @@ public void testGetCatalogs() throws SQLException { 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(connection.getDefaultCatalog()))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(connection.getDefaultCatalog(), rs.getString("TABLE_CAT")); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(1))); + assertEquals(1, rsmd.getColumnCount()); } } @@ -340,21 +333,21 @@ public void testGetClientInfoProperties() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getClientInfoProperties()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("APPLICATIONNAME"))); - assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + assertTrue(rs.next()); + assertEquals("APPLICATIONNAME", rs.getString("NAME")); + assertEquals("", rs.getString("DEFAULT_VALUE")); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("CLIENTHOSTNAME"))); - assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + assertTrue(rs.next()); + assertEquals("CLIENTHOSTNAME", rs.getString("NAME")); + assertEquals("", rs.getString("DEFAULT_VALUE")); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("NAME"), is(equalTo("CLIENTUSER"))); - assertThat(rs.getString("DEFAULT_VALUE"), is(equalTo(""))); + assertTrue(rs.next()); + assertEquals("CLIENTUSER", rs.getString("NAME")); + assertEquals("", rs.getString("DEFAULT_VALUE")); - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(4))); + assertEquals(4, rsmd.getColumnCount()); } } @@ -364,9 +357,9 @@ public void testGetColumnPrivileges() throws SQLException { DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getColumnPrivileges(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(8))); + assertEquals(8, rsmd.getColumnCount()); } } @@ -375,9 +368,9 @@ public void testGetFunctionColumns() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getFunctionColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(17))); + assertEquals(17, rsmd.getColumnCount()); } } @@ -386,9 +379,9 @@ public void testGetFunctions() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getFunctions(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(6))); + assertEquals(6, rsmd.getColumnCount()); } } @@ -397,9 +390,9 @@ public void testGetProcedureColumns() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getProcedureColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(20))); + assertEquals(20, rsmd.getColumnCount()); } } @@ -408,9 +401,9 @@ public void testGetProcedures() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getProcedures(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(9))); + assertEquals(9, rsmd.getColumnCount()); } } @@ -419,9 +412,9 @@ public void testGetPseudoColumns() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getPseudoColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(12))); + assertEquals(12, rsmd.getColumnCount()); } } @@ -430,9 +423,9 @@ public void testGetSuperTables() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getSuperTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(4))); + assertEquals(4, rsmd.getColumnCount()); } } @@ -441,9 +434,9 @@ public void testGetSuperTypes() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getSuperTypes(DEFAULT_CATALOG, DEFAULT_SCHEMA, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(6))); + assertEquals(6, rsmd.getColumnCount()); } } @@ -452,9 +445,9 @@ public void testGetTablePrivileges() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getTablePrivileges(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(7))); + assertEquals(7, rsmd.getColumnCount()); } } @@ -463,13 +456,13 @@ public void testGetTableTypes() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getTableTypes()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_TYPE"), is(equalTo("TABLE"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_TYPE"), is(equalTo("VIEW"))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals("TABLE", rs.getString("TABLE_TYPE")); + assertTrue(rs.next()); + assertEquals("VIEW", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(1))); + assertEquals(1, rsmd.getColumnCount()); } } @@ -500,9 +493,9 @@ public void testGetTypeInfo() throws SQLException { assertEquals("NUMERIC", rs.getString("TYPE_NAME")); assertTrue(rs.next()); assertEquals(dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON", rs.getString("TYPE_NAME")); - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(18))); + assertEquals(18, rsmd.getColumnCount()); } } } @@ -512,9 +505,9 @@ public void testGetUDTs() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getUDTs(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(7))); + assertEquals(7, rsmd.getColumnCount()); } } @@ -523,9 +516,9 @@ public void testGetVersionColumns() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); try (ResultSet rs = meta.getVersionColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TEST_TABLE)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); - assertThat(rsmd.getColumnCount(), is(equalTo(8))); + assertEquals(8, rsmd.getColumnCount()); } } @@ -540,6 +533,6 @@ public void testGetUserName() throws SQLException, IOException { when(options.getCredentials()).thenReturn(credentials); when(connection.getConnectionOptions()).thenReturn(options); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); - assertThat(meta.getUserName(), is(equalTo("test@test-project.iam.gserviceaccount.com"))); + assertEquals("test@test-project.iam.gserviceaccount.com", meta.getUserName()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java deleted file mode 100644 index afe9657f0471..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcExceptionMatcher.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 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.common.base.Preconditions; -import com.google.rpc.Code; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; - -public final class JdbcExceptionMatcher extends BaseMatcher { - private final Code errorCode; - private final String message; - - public static JdbcExceptionMatcher matchCode(Code errorCode) { - Preconditions.checkNotNull(errorCode); - return new JdbcExceptionMatcher(errorCode, null); - } - - public static JdbcExceptionMatcher matchCodeAndMessage(Code errorCode, String message) { - Preconditions.checkNotNull(errorCode); - Preconditions.checkNotNull(message); - return new JdbcExceptionMatcher(errorCode, message); - } - - private JdbcExceptionMatcher(Code errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } - - @Override - public boolean matches(Object item) { - if (item instanceof JdbcSqlException) { - JdbcSqlException exception = (JdbcSqlException) item; - if (message == null) { - return exception.getCode().equals(errorCode); - } - return exception.getCode().equals(errorCode) - && exception.getMessage().equals(errorCode.name() + ": " + message); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(JdbcSqlException.class.getName() + " with code " + errorCode.name()); - if (message != null) { - description.appendText(" - " + JdbcSqlException.class.getName() + " with message " + message); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index 2c1bfe820dc7..ba94647cbcfa 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -16,8 +16,9 @@ package com.google.cloud.spanner.jdbc; -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.MockSpannerServiceImpl; @@ -87,9 +88,6 @@ public class JdbcGrpcErrorTest { // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. private final Exception serverException = Status.FAILED_PRECONDITION.withDescription("test exception").asRuntimeException(); - private final SpannerJdbcExceptionMatcher testExceptionMatcher = - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, Code.FAILED_PRECONDITION, "test exception"); @BeforeClass public static void startStaticServer() throws IOException { @@ -152,69 +150,79 @@ private Connection createConnection() throws SQLException { } @Test - public void autocommitBeginTransaction() { + public void autocommitBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { // This triggers a retry with an explicit BeginTransaction RPC. mockSpanner.abortNextStatement(); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void autocommitBeginPDMLTransaction() { + public void autocommitBeginPDMLTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void transactionalBeginTransaction() { + public void transactionalBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); // This triggers a retry with an explicit BeginTransaction RPC. mockSpanner.abortNextStatement(); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void readOnlyBeginTransaction() { + public void readOnlyBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); - connection.createStatement().executeQuery(SELECT1.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeQuery(SELECT1.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void autocommitExecuteSql() { + public void autocommitExecuteSql() throws SQLException { mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -230,22 +238,26 @@ public void autocommitPDMLExecuteSql() throws SQLException { SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void transactionalExecuteSql() { + public void transactionalExecuteSql() throws SQLException { mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -257,10 +269,10 @@ public void autocommitExecuteBatchDml() throws SQLException { try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); - statement.executeBatch(); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } } @@ -274,52 +286,53 @@ public void transactionalExecuteBatchDml() throws SQLException { try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); - statement.executeBatch(); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } } @Test - public void autocommitCommit() { + public void autocommitCommit() throws SQLException { mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void transactionalCommit() { + public void transactionalCommit() throws SQLException { mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - connection.commit(); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, connection::commit); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void autocommitRollback() { + public void autocommitRollback() throws SQLException { // The JDBC driver should throw the exception of the SQL statement and ignore any errors from // the rollback() method. mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - connection.createStatement().executeUpdate(INVALID_UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, Code.NOT_FOUND, "Unknown table name") - .matches(e)) - .isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(INVALID_UPDATE_STATEMENT.getSql())); + assertEquals(Code.NOT_FOUND, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), sqlException.getMessage().contains("Unknown table name")); } } @@ -346,82 +359,88 @@ public void autocommitExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { - rs.next(); - fail("missing expected exception"); - } - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeQuery(SELECT1.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void transactionalExecuteStreamingSql() { + public void transactionalExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { - rs.next(); - fail("missing expected exception"); - } - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeQuery(SELECT1.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void readOnlyExecuteStreamingSql() { + public void readOnlyExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); - try (java.sql.ResultSet rs = connection.createStatement().executeQuery(SELECT1.getSql())) { - rs.next(); - fail("missing expected exception"); - } - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeQuery(SELECT1.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void autocommitCreateSession() { + public void autocommitCreateSession() throws SQLException { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void transactionalCreateSession() { + public void transactionalCreateSession() throws SQLException { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); - connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test - public void readOnlyCreateSession() { + public void readOnlyCreateSession() throws SQLException { mockSpanner.setBatchCreateSessionsExecutionTime( SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); - connection.createStatement().executeQuery(SELECT1.getSql()); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(testExceptionMatcher.matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> connection.createStatement().executeQuery(SELECT1.getSql())); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 08bc7e060f17..67b0cfd2305d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -16,12 +16,12 @@ package com.google.cloud.spanner.jdbc; -import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertArrayEquals; 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; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; @@ -497,18 +497,14 @@ public void testGetURLIndex() throws SQLException, MalformedURLException { @Test public void testGetURLIndexInvalid() throws SQLException { - try { - subject.getURL(STRING_COLINDEX_NOTNULL); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, - Code.INVALID_ARGUMENT, - "Invalid URL: " + subject.getString(STRING_COLINDEX_NOTNULL)) - .matches(e)) - .isTrue(); - } + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> subject.getURL(STRING_COLINDEX_NOTNULL)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains("Invalid URL: " + subject.getString(STRING_COLINDEX_NOTNULL))); } @Test @@ -901,18 +897,14 @@ public void testGetURLLabel() throws SQLException { @Test public void testGetURLLabelInvalid() throws SQLException { - try { - subject.getURL(STRING_COL_NOT_NULL); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, - Code.INVALID_ARGUMENT, - "Invalid URL: " + subject.getString(STRING_COL_NOT_NULL)) - .matches(e)) - .isTrue(); - } + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> subject.getURL(STRING_COL_NOT_NULL)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains("Invalid URL: " + subject.getString(STRING_COL_NOT_NULL))); } @Test @@ -1754,52 +1746,40 @@ public void testGetBinaryStreamLabel() throws SQLException, IOException { @Test public void testGetBeforeNext() { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { - rs.getBigDecimal(LONG_COLINDEX_NOTNULL); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, - Code.FAILED_PRECONDITION, - "ResultSet is before first row. Call next() first.") - .matches(e)) - .isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> rs.getBigDecimal(LONG_COLINDEX_NOTNULL)); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException.getMessage().contains("ResultSet is before first row. Call next() first.")); } } @Test - public void testGetAfterLast() { + public void testGetAfterLast() throws SQLException { try (JdbcResultSet rs = JdbcResultSet.of(mock(Statement.class), getMockResultSet())) { while (rs.next()) { assertNotNull(rs.getBigDecimal(LONG_COLINDEX_NOTNULL)); } - rs.getBigDecimal(LONG_COLINDEX_NOTNULL); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, - Code.FAILED_PRECONDITION, - "ResultSet is after last row. There is no more data available.") - .matches(e)) - .isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> rs.getBigDecimal(LONG_COLINDEX_NOTNULL)); + assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains("ResultSet is after last row. There is no more data available.")); } } @Test public void testFindIllegalColumnName() { - try { - subject.findColumn(UNKNOWN_COLUMN); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - SpannerJdbcExceptionMatcher.matchCodeAndMessage( - JdbcSqlExceptionImpl.class, - Code.INVALID_ARGUMENT, - "no column with label " + UNKNOWN_COLUMN + " found") - .matches(e)) - .isTrue(); - } + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> subject.findColumn(UNKNOWN_COLUMN)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException.getMessage().contains("no column with label " + UNKNOWN_COLUMN + " found")); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java index 727e63acf54d..cb4cc5a53cb2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTest.java @@ -300,16 +300,12 @@ public void testExecuteQuery() throws SQLException { } @Test - public void testExecuteQueryWithUpdateStatement() { - try { - Statement statement = createStatement(); - statement.executeQuery(UPDATE); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query") - .matches(e)) - .isTrue(); + public void testExecuteQueryWithUpdateStatement() throws SQLException { + try (Statement statement = createStatement()) { + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.executeQuery(UPDATE)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("not a query")); } } @@ -325,28 +321,22 @@ public void testExecuteQueryWithDmlReturningStatement() throws SQLException { } @Test - public void testExecuteQueryWithDdlStatement() { - try { - Statement statement = createStatement(); - statement.executeQuery(DDL); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - JdbcExceptionMatcher.matchCodeAndMessage(Code.INVALID_ARGUMENT, "not a query") - .matches(e)) - .isTrue(); + public void testExecuteQueryWithDdlStatement() throws SQLException { + try (Statement statement = createStatement()) { + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.executeQuery(DDL)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("not a query")); } } @Test public void testExecuteUpdate() throws SQLException { - Statement statement = createStatement(); - assertThat(statement.executeUpdate(UPDATE)).isEqualTo(1); - try { - statement.executeUpdate(LARGE_UPDATE); - fail("missing expected exception"); - } catch (JdbcSqlExceptionImpl e) { - assertThat(e.getCode()).isEqualTo(Code.OUT_OF_RANGE); + try (Statement statement = createStatement()) { + assertEquals(1, statement.executeUpdate(UPDATE)); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.executeUpdate(LARGE_UPDATE)); + assertEquals(Code.OUT_OF_RANGE, sqlException.getCode()); } } @@ -423,34 +413,31 @@ public void testExecuteLargeUpdate() throws SQLException { } @Test - public void testExecuteUpdateWithSelectStatement() { - try { - Statement statement = createStatement(); - statement.executeUpdate(SELECT); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, - "The statement is not a non-returning DML or DDL statement") - .matches(e)) - .isTrue(); + public void testExecuteUpdateWithSelectStatement() throws SQLException { + try (Statement statement = createStatement()) { + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.executeUpdate(SELECT)); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains("The statement is not a non-returning DML or DDL statement")); } } @Test - public void testExecuteUpdateWithDmlReturningStatement() { - try { - Statement statement = createStatement(); - SQLException e = - assertThrows(SQLException.class, () -> statement.executeUpdate(getDmlReturningSql())); + public void testExecuteUpdateWithDmlReturningStatement() throws SQLException { + try (Statement statement = createStatement()) { + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, () -> statement.executeUpdate(getDmlReturningSql())); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue( - JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, - "The statement is not a non-returning DML or DDL statement") - .matches(e)); - } catch (SQLException e) { - // ignore exception. + sqlException.getMessage(), + sqlException + .getMessage() + .contains("The statement is not a non-returning DML or DDL statement")); } } @@ -490,32 +477,36 @@ public void testMoreResults() throws SQLException { } @Test - public void testNoBatchMixing() { + public void testNoBatchMixing() throws SQLException { try (Statement statement = createStatement()) { statement.addBatch("INSERT INTO FOO (ID, NAME) VALUES (1, 'FOO')"); - statement.addBatch("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)"); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat( - JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, - "Mixing DML and DDL statements in a batch is not allowed.") - .matches(e)) - .isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> + statement.addBatch( + "CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains("Mixing DML and DDL statements in a batch is not allowed.")); } } @Test - public void testNoBatchQuery() { + public void testNoBatchQuery() throws SQLException { try (Statement statement = createStatement()) { - statement.addBatch("SELECT * FROM FOO"); - } catch (SQLException e) { - assertThat( - JdbcExceptionMatcher.matchCodeAndMessage( - Code.INVALID_ARGUMENT, - "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching.") - .matches(e)) - .isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.addBatch("SELECT * FROM FOO")); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); + assertTrue( + sqlException.getMessage(), + sqlException + .getMessage() + .contains( + "The statement is not suitable for batching. Only DML and DDL statements are allowed for batching.")); } } @@ -559,7 +550,7 @@ public void testLargeDmlBatch() throws SQLException { } @Test - public void testConvertUpdateCounts() { + public void testConvertUpdateCounts() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); when(connection.getDialect()).thenReturn(dialect); try (JdbcStatement statement = new JdbcStatement(connection)) { @@ -568,10 +559,11 @@ public void testConvertUpdateCounts() { updateCounts = statement.convertUpdateCounts(new long[] {0L, 0L, 0L}); assertThat(updateCounts).asList().containsExactly(0, 0, 0); - statement.convertUpdateCounts(new long[] {1L, Integer.MAX_VALUE + 1L}); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(JdbcExceptionMatcher.matchCode(Code.OUT_OF_RANGE).matches(e)).isTrue(); + JdbcSqlExceptionImpl sqlException = + assertThrows( + JdbcSqlExceptionImpl.class, + () -> statement.convertUpdateCounts(new long[] {1L, Integer.MAX_VALUE + 1L})); + assertEquals(Code.OUT_OF_RANGE, sqlException.getCode()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java deleted file mode 100644 index 062a5ac42da7..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SpannerJdbcExceptionMatcher.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019 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.common.base.Preconditions; -import com.google.rpc.Code; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; - -public final class SpannerJdbcExceptionMatcher extends BaseMatcher { - private final Class exceptionClass; - private final Code errorCode; - private final String message; - - public static SpannerJdbcExceptionMatcher matchCode( - Class exceptionClass, Code errorCode) { - Preconditions.checkNotNull(exceptionClass); - Preconditions.checkNotNull(errorCode); - return new SpannerJdbcExceptionMatcher<>(exceptionClass, errorCode, null); - } - - public static SpannerJdbcExceptionMatcher matchCodeAndMessage( - Class exceptionClass, Code errorCode, String message) { - Preconditions.checkNotNull(exceptionClass); - Preconditions.checkNotNull(errorCode); - Preconditions.checkNotNull(message); - return new SpannerJdbcExceptionMatcher<>(exceptionClass, errorCode, message); - } - - private SpannerJdbcExceptionMatcher(Class exceptionClass, Code errorCode, String message) { - this.exceptionClass = exceptionClass; - this.errorCode = errorCode; - this.message = message; - } - - @Override - public boolean matches(Object item) { - if (exceptionClass.isAssignableFrom(item.getClass())) { - JdbcSqlException exception = (JdbcSqlException) item; - if (message == null) { - return exception.getErrorCode() == errorCode.getNumber(); - } - return exception.getErrorCode() == errorCode.getNumber() - && exception.getMessage().contains(": " + message); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(exceptionClass.getName() + " with code " + errorCode.name()); - if (message != null) { - description.appendText(" - " + JdbcSqlException.class.getName() + " with message " + message); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java index 9391b52af9a1..049d51ca3772 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITAbstractJdbcTest.java @@ -124,9 +124,6 @@ static Collection getMusicTablesDdl(Dialect dialect) { default: scriptFile = "CreateMusicTables.sql"; } - if (dialect != Dialect.POSTGRESQL && isUsingEmulator()) { - scriptFile = "CreateMusicTables_Emulator.sql"; - } return AbstractSqlScriptVerifier.readStatementsFromFile(scriptFile, ITAbstractJdbcTest.class) .stream() .filter(sql -> !(sql.contains("START BATCH") || sql.contains("RUN BATCH"))) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 820bdfac91c0..903df91db067 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -16,20 +16,14 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; 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.assertTrue; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.ParallelIntegrationTest; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -177,63 +171,59 @@ public void testGetColumns() throws SQLException { .getColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { int pos = 1; for (Column col : EXPECTED_COLUMNS) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("COLUMN_NAME"), is(equalTo(col.name))); - assertThat(rs.getInt("DATA_TYPE"), is(equalTo(col.type))); - assertThat(rs.getString("TYPE_NAME"), is(equalTo(col.typeName))); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("TABLE_NAME")); + assertEquals(col.name, rs.getString("COLUMN_NAME")); + assertEquals(col.type, rs.getInt("DATA_TYPE")); + assertEquals(col.typeName, rs.getString("TYPE_NAME")); if (col.colSize == null) { - assertThat(rs.getInt("COLUMN_SIZE"), is(equalTo(0))); - assertThat(rs.wasNull(), is(true)); + assertEquals(0, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.wasNull()); } else { - assertThat(rs.getInt("COLUMN_SIZE"), is(equalTo(col.colSize))); + assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); } rs.getObject("BUFFER_LENGTH"); // just assert that it exists if (col.decimalDigits == null) { - assertThat(rs.getInt("DECIMAL_DIGITS"), is(equalTo(0))); - assertThat(rs.wasNull(), is(true)); + assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + assertTrue(rs.wasNull()); } else { - assertThat(rs.getInt("DECIMAL_DIGITS"), is(equalTo(col.decimalDigits))); + assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); } if (col.radix == null) { - assertThat(rs.getInt("NUM_PREC_RADIX"), is(equalTo(0))); - assertThat(rs.wasNull(), is(true)); + assertEquals(0, rs.getInt("NUM_PREC_RADIX")); + assertTrue(rs.wasNull()); } else { - assertThat(rs.getInt("NUM_PREC_RADIX"), is(equalTo(col.radix))); + assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); } - assertThat( - rs.getInt("NULLABLE"), - is( - equalTo( - col.nullable - ? DatabaseMetaData.columnNullable - : DatabaseMetaData.columnNoNulls))); - assertThat(rs.getString("REMARKS"), is(nullValue())); - assertThat(rs.getString("COLUMN_DEF"), is(nullValue())); - assertThat(rs.getInt("SQL_DATA_TYPE"), is(equalTo(0))); - assertThat(rs.getInt("SQL_DATETIME_SUB"), is(equalTo(0))); + assertEquals( + col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, + rs.getInt("NULLABLE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("COLUMN_DEF")); + assertEquals(0, rs.getInt("SQL_DATA_TYPE")); + assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); if (col.charOctetLength == null) { - assertThat(rs.getInt("CHAR_OCTET_LENGTH"), is(equalTo(0))); - assertThat(rs.wasNull(), is(true)); + assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + assertTrue(rs.wasNull()); } else { - assertThat(rs.getInt("CHAR_OCTET_LENGTH"), is(equalTo(col.charOctetLength))); + assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); } - assertThat(rs.getInt("ORDINAL_POSITION"), is(equalTo(pos))); - assertThat(rs.getString("IS_NULLABLE"), is(equalTo(col.nullable ? "YES" : "NO"))); - assertThat(rs.getString("SCOPE_CATALOG"), is(nullValue())); - assertThat(rs.getString("SCOPE_SCHEMA"), is(nullValue())); - assertThat(rs.getString("SCOPE_TABLE"), is(nullValue())); - assertThat(rs.getShort("SOURCE_DATA_TYPE"), is(equalTo((short) 0))); - assertThat(rs.wasNull(), is(true)); - assertThat(rs.getString("IS_AUTOINCREMENT"), is(equalTo("NO"))); - assertThat(rs.getString("IS_GENERATEDCOLUMN"), is(equalTo(col.computed ? "YES" : "NO"))); - assertThat(rs.getMetaData().getColumnCount(), is(equalTo(24))); + assertEquals(pos, rs.getInt("ORDINAL_POSITION")); + assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); + assertNull(rs.getString("SCOPE_CATALOG")); + assertNull(rs.getString("SCOPE_SCHEMA")); + assertNull(rs.getString("SCOPE_TABLE")); + assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); + assertTrue(rs.wasNull()); + assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); + assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + assertEquals(24, rs.getMetaData().getColumnCount()); pos++; } - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } } } @@ -251,25 +241,21 @@ public void testGetCrossReferences() throws SQLException { DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Singers"))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Albums"))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); } try (ResultSet rs = connection @@ -281,45 +267,37 @@ public void testGetCrossReferences() throws SQLException { DEFAULT_CATALOG, DEFAULT_SCHEMA, SONGS_TABLE)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Albums"))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Songs"))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Albums"))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("AlbumId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Songs"))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("AlbumId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); } try (ResultSet rs = @@ -332,26 +310,22 @@ public void testGetCrossReferences() throws SQLException { DEFAULT_CATALOG, DEFAULT_SCHEMA, CONCERTS_TABLE)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo("Singers"))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo("Concerts"))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_Concerts_Singer"))); - assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals("Concerts", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + assertEquals("PK_Singers", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertFalse(rs.next()); } try (ResultSet rs = @@ -365,64 +339,52 @@ public void testGetCrossReferences() throws SQLException { DEFAULT_SCHEMA, TABLE_WITH_REF)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColFloat64"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefFloat"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColString"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefString"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColDate"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(""))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefDate"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 3))); - assertThat( - rs.getShort("UPDATE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat( - rs.getShort("DELETE_RULE"), is(equalTo((short) DatabaseMetaData.importedKeyNoAction))); - assertThat(rs.getString("FK_NAME"), is(equalTo("Fk_TableWithRef_TableWithAllColumnTypes"))); - assertThat( - rs.getShort("DEFERRABILITY"), - is(equalTo((short) DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals("", rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals("", rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); + assertEquals(3, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertFalse(rs.next()); } // try getting self-references try (ResultSet rs = @@ -435,15 +397,15 @@ public void testGetCrossReferences() throws SQLException { DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } // try getting all cross-references in the database try (ResultSet rs = connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { for (int i = 0; i < 7; i++) { - assertThat(rs.next(), is(true)); + assertTrue(rs.next()); } - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } } } @@ -524,33 +486,33 @@ public void testGetIndexInfo() throws SQLException { .getIndexInfo(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, false, false)) { for (IndexInfo index : EXPECTED_INDICES) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(index.tableName))); - assertThat(rs.getBoolean("NON_UNIQUE"), is(index.nonUnique)); - assertThat(rs.getString("INDEX_QUALIFIER"), is(equalTo(DEFAULT_CATALOG))); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(index.tableName, rs.getString("TABLE_NAME")); + assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); + assertEquals(DEFAULT_CATALOG, rs.getString("INDEX_QUALIFIER")); // Foreign key index names are automatically generated. if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { - assertThat(rs.getString("INDEX_NAME"), is(equalTo(index.indexName))); + assertEquals(index.indexName, rs.getString("INDEX_NAME")); } if (index.indexName.equals("PRIMARY_KEY")) { - assertThat(rs.getShort("TYPE"), is(equalTo(DatabaseMetaData.tableIndexClustered))); + assertEquals(DatabaseMetaData.tableIndexClustered, rs.getShort("TYPE")); } else { - assertThat(rs.getShort("TYPE"), is(equalTo(DatabaseMetaData.tableIndexHashed))); + assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); } - assertThat(rs.getShort("ORDINAL_POSITION"), is(equalTo(index.ordinalPosition))); + assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); if (index.ordinalPosition == 0) { - assertThat(rs.wasNull(), is(true)); + assertTrue(rs.wasNull()); } - assertThat(rs.getString("COLUMN_NAME"), is(equalTo(index.columnName))); - assertThat(rs.getString("ASC_OR_DESC"), is(equalTo(index.ascDesc))); - assertThat(rs.getInt("CARDINALITY"), is(equalTo(-1))); - assertThat(rs.getInt("PAGES"), is(equalTo(-1))); - assertThat(rs.getString("FILTER_CONDITION"), is(nullValue())); + assertEquals(index.columnName, rs.getString("COLUMN_NAME")); + assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); + assertEquals(-1, rs.getInt("CARDINALITY")); + assertEquals(-1, rs.getInt("PAGES")); + assertNull(rs.getString("FILTER_CONDITION")); } // all indices found - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } } } @@ -604,170 +566,170 @@ public void testGetImportedKeys() throws SQLException { } private void assertImportedKeysSingers(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColFloat64"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefFloat"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); - assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColString"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefString"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); - assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(TABLE_WITH_ALL_COLS))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("ColDate"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(TABLE_WITH_REF))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("RefDate"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 3))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getString("FK_NAME"), is("Fk_TableWithRef_TableWithAllColumnTypes")); - assertThat(rs.getString("PK_NAME"), is(notNullValue())); // Index name is generated. - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertNotNull(rs.getString("PK_NAME")); // Index name is generated. + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertNotNull(rs.getString("PK_NAME")); // Index name is generated. + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); + assertEquals(3, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertNotNull(rs.getString("PK_NAME")); // Index name is generated. + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertFalse(rs.next()); } private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertFalse(rs.next()); } private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(CONCERTS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getString("FK_NAME"), is("Fk_Concerts_Singer")); - assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + assertEquals("PK_Singers", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertFalse(rs.next()); } private void assertExportedKeysSingers(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(SINGERS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(CONCERTS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getString("FK_NAME"), is("Fk_Concerts_Singer")); - assertThat(rs.getString("PK_NAME"), is(equalTo("PK_Singers"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + assertEquals("PK_Singers", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertFalse(rs.next()); } private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(SONGS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 1))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - - assertThat(rs.next(), is(true)); - assertThat(rs.getString("PKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("PKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("PKTABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("PKCOLUMN_NAME"), is(equalTo("AlbumId"))); - assertThat(rs.getString("FKTABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("FKTABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("FKTABLE_NAME"), is(equalTo(SONGS_TABLE))); - assertThat(rs.getString("FKCOLUMN_NAME"), is(equalTo("AlbumId"))); - assertThat(rs.getShort("KEY_SEQ"), is(equalTo((short) 2))); - assertThat(rs.getInt("UPDATE_RULE"), is(equalTo(DatabaseMetaData.importedKeyRestrict))); - assertThat(rs.getInt("DELETE_RULE"), is(equalTo(DatabaseMetaData.importedKeyCascade))); - assertThat(rs.getString("FK_NAME"), is(nullValue())); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.getInt("DEFERRABILITY"), is(equalTo(DatabaseMetaData.importedKeyNotDeferrable))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); + assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getInt("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); + assertFalse(rs.next()); } @Test @@ -775,39 +737,39 @@ public void testGetPrimaryKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(SINGERS_TABLE))); - assertThat(rs.getString("COLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getInt("KEY_SEQ"), is(equalTo(1))); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); } try (ResultSet rs = connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("COLUMN_NAME"), is(equalTo("SingerId"))); - assertThat(rs.getInt("KEY_SEQ"), is(equalTo(1))); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_CAT"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo(DEFAULT_SCHEMA))); - assertThat(rs.getString("TABLE_NAME"), is(equalTo(ALBUMS_TABLE))); - assertThat(rs.getString("COLUMN_NAME"), is(equalTo("AlbumId"))); - assertThat(rs.getInt("KEY_SEQ"), is(equalTo(2))); - assertThat(rs.getString("PK_NAME"), is(equalTo("PRIMARY_KEY"))); - assertThat(rs.next(), is(false)); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("AlbumId", rs.getString("COLUMN_NAME")); + assertEquals(2, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); } } } @Test public void testGetViews() throws SQLException { - assumeFalse("Emulator does not yet support views", EmulatorSpannerHelper.isUsingEmulator()); + // assumeFalse("Emulator does not yet support views", EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection(env, database)) { try (ResultSet rs = connection.getMetaData().getTables("", "", null, new String[] {"VIEW"})) { assertTrue(rs.next()); @@ -824,15 +786,15 @@ 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))); - assertThat(rs.getString("TABLE_CATALOG"), is(equalTo(DEFAULT_CATALOG))); - assertThat(rs.next(), is(true)); - assertThat(rs.getString("TABLE_SCHEM"), is(equalTo("INFORMATION_SCHEMA"))); - 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))); + assertTrue(rs.next()); + assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); + assertTrue(rs.next()); + assertEquals("INFORMATION_SCHEMA", rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); + assertTrue(rs.next()); + assertEquals("SPANNER_SYS", rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); assertFalse(rs.next()); } } @@ -882,9 +844,6 @@ public void testGetTables() throws SQLException { try (ResultSet rs = connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { for (Table table : EXPECTED_TABLES) { - if (EmulatorSpannerHelper.isUsingEmulator() && table.name.equals("SingersView")) { - continue; - } assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); @@ -897,7 +856,7 @@ public void testGetTables() throws SQLException { assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); assertNull(rs.getString("REF_GENERATION")); } - assertThat(rs.next(), is(false)); + assertFalse(rs.next()); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java index 525ccbbe13ba..3db849cfd4e2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcReadWriteAutocommitTest.java @@ -16,9 +16,8 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; @@ -101,8 +100,8 @@ public void test02_WriteMutation() throws Exception { "SHOW VARIABLE %sCOMMIT_TIMESTAMP", getDialect() == Dialect.POSTGRESQL ? "SPANNER." : "")); try (java.sql.ResultSet rs = statement.getResultSet()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getTimestamp(1), is(notNullValue())); + assertTrue(rs.next()); + assertNotNull(rs.getTimestamp(1)); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java index 8d8c0ffa0120..9aeb5c730395 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcScriptTest.java @@ -16,10 +16,9 @@ package com.google.cloud.spanner.jdbc.it; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; @@ -313,8 +312,8 @@ public void test11_TestStatementTimeout() throws Exception { statement.setQueryTimeout(1); statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); try (ResultSet rs = statement.getResultSet()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("STATEMENT_TIMEOUT"), is(nullValue())); + assertTrue(rs.next()); + assertNull(rs.getString("STATEMENT_TIMEOUT")); } // Now set a STATEMENT_TIMEOUT on the connection that is different from the query timeout of @@ -323,8 +322,8 @@ public void test11_TestStatementTimeout() throws Exception { statement.execute("SET STATEMENT_TIMEOUT='100ms'"); statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); try (ResultSet rs = statement.getResultSet()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("STATEMENT_TIMEOUT"), is(equalTo("100ms"))); + assertTrue(rs.next()); + assertEquals("100ms", rs.getString("STATEMENT_TIMEOUT")); } // Remove the statement timeout again, and verify that SHOW STATEMENT_TIMEOUT once again @@ -332,8 +331,8 @@ public void test11_TestStatementTimeout() throws Exception { statement.execute("SET STATEMENT_TIMEOUT=NULL"); statement.execute("SHOW VARIABLE STATEMENT_TIMEOUT"); try (ResultSet rs = statement.getResultSet()) { - assertThat(rs.next(), is(true)); - assertThat(rs.getString("STATEMENT_TIMEOUT"), is(nullValue())); + assertTrue(rs.next()); + assertNull(rs.getString("STATEMENT_TIMEOUT")); } } } From 4510756f69d2b8664d90afb965f1803b5c10e640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 6 Aug 2024 17:45:38 +0200 Subject: [PATCH 1356/1979] test: verify that executeUpdate can be used for DDL (#1694) The JDBC driver should now support executing DDL using the executeUpdate methods of java.sql.Statement and java.sql.PreparedStatement. Closes #1150 --- .../cloud/spanner/jdbc/DdlMockServerTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java index 76cac4fa604f..75f9d9efcbd9 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java @@ -31,6 +31,7 @@ import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.SQLException; import org.junit.Test; import org.junit.runner.RunWith; @@ -98,4 +99,45 @@ public void testDdlInAutoCommitIsFalse_failsWithActiveTransaction() throws SQLEx assertEquals(Code.FAILED_PRECONDITION, jdbcSqlException.getCode()); } } + + @Test + public void testDdlUsingStatementAndExecuteUpdate() throws SQLException { + for (boolean autoCommit : new boolean[] {true, false}) { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + + try (Connection connection = createConnection(autoCommit)) { + try (java.sql.Statement statement = connection.createStatement()) { + assertEquals(0, statement.executeUpdate("create table foo (id int64) primary key (id)")); + } + } + assertEquals(1, mockDatabaseAdmin.getRequests().size()); + mockDatabaseAdmin.getRequests().clear(); + } + } + + @Test + public void testDdlUsingPreparedStatementAndExecuteUpdate() throws SQLException { + for (boolean autoCommit : new boolean[] {true, false}) { + mockDatabaseAdmin.addResponse( + Operation.newBuilder() + .setDone(true) + .setResponse(Any.pack(Empty.getDefaultInstance())) + .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) + .build()); + + try (Connection connection = createConnection(autoCommit)) { + try (PreparedStatement preparedStatement = + connection.prepareStatement("create table foo (id int64) primary key (id)")) { + assertEquals(0, preparedStatement.executeUpdate()); + } + } + assertEquals(1, mockDatabaseAdmin.getRequests().size()); + mockDatabaseAdmin.getRequests().clear(); + } + } } From 7db29b4123f514e968f559c907aa24d1acdde2c5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 6 Aug 2024 19:00:56 +0200 Subject: [PATCH 1357/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.47.0 (#1696) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 59adb9d33d0c..98d60ce37e43 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -225,7 +225,7 @@ com.google.cloud google-cloud-trace - 2.46.0 + 2.47.0 test From 2c59ba5958d3c40bdda89c5d7c71a58501e3424e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 6 Aug 2024 19:01:19 +0200 Subject: [PATCH 1358/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.47.0 (#1695) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 98d60ce37e43..08f73f73e02f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -231,7 +231,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.46.0 + 2.47.0 test From 7b1857556cc1b499a81c19d705ecedd2656bb7ef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 6 Aug 2024 19:47:18 +0200 Subject: [PATCH 1359/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.33.0 (#1693) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.33.0 * deps: add incubator dep needed for test * deps: work around unnecessary dependency * chore: run formatter --------- Co-authored-by: Knut Olav Løite --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- .../.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 9 ++++++++- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- .../cloud/spanner/jdbc/it/ITOpenTelemetryTest.java | 8 +++++--- 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 8eb9dfbd6e81..09f9543875de 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.32.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.33.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 7d5ab3a25c4c..7008a7215676 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.32.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.33.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 519c2e3ce370..931f9bb00528 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.32.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.33.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 08f73f73e02f..d510d8133838 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.32.0 + 3.33.0 @@ -201,6 +201,13 @@ + + + io.opentelemetry + opentelemetry-api-incubator + 1.40.0-alpha + test + io.opentelemetry opentelemetry-sdk diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0c3b12de909d..ee6deda8b3f0 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.32.0 + 3.33.0 diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java index 19fb1146e382..bbbbaf344a76 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java @@ -38,6 +38,7 @@ import com.google.common.collect.Iterables; import com.google.devtools.cloudtrace.v1.ListTracesRequest; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.incubator.trace.ExtendedTracer; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; @@ -79,7 +80,7 @@ public class ITOpenTelemetryTest extends ITAbstractJdbcTest { private Database database; @BeforeClass - public static void setupOpenTelemetry() throws IOException { + public static void setupOpenTelemetry() { assumeFalse("This test requires credentials", EmulatorSpannerHelper.isUsingEmulator()); SpannerOptions options = env.getTestHelper().getOptions(); @@ -103,6 +104,9 @@ public static void setupOpenTelemetry() throws IOException { .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) .build()) .build(); + // TODO: Remove when the bug in OpenTelemetry that has SdkTracer implement ExtendedTracer, + // which is only available in the incubator project. + ExtendedTracer ignore = (ExtendedTracer) openTelemetry.getTracer("foo"); } @AfterClass @@ -245,8 +249,6 @@ private void assertTrace(String sql) throws IOException, InterruptedException { Thread.sleep(5000L); boolean foundTrace = false; for (int attempts = 0; attempts < 20; attempts++) { - // Ignore deprecation for now, as there is no alternative offered (yet?). - //noinspection deprecation ListTracesPagedResponse response = client.listTraces( ListTracesRequest.newBuilder() From 8c3dd24dd662cc4dccaa18c5753792aebef9e4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 6 Aug 2024 19:48:09 +0200 Subject: [PATCH 1360/1979] fix: support getShort for DATA_TYPE in TypeInfo (#1691) * fix: support getShort for DATA_TYPE in TypeInfo The ResultSet that is returned by DatabaseMetadata#getTypeInfo has a column at index 2 with the name DATA_TYPE. This field should contain one of the java.sql.Types constants, or a vendor-specific type code. The JDBC specification states that this column should be a `short` (although the constants in java.sql.Types are of type `int`). Cloud Spanner (at the time of writing) does not support any int16 fields. The type code is therefore returned as an int64. The codes that are used for vendor-specific types by Spanner exceed the max value of a `short`, and therefore resulted in an OUT_OF_RANGE exception if you tried to call `ResultSet#getShort(int)` on this column for any of the Spanner-specific types (e.g. JSON). This change fixes that by adding an additional vendor type code for these types that does fit in a `short`. This value is returned when `getShort(int)` is called on the ResultSet. Fixes #1688 * chore: cleanup --- .../spanner/jdbc/JdbcDatabaseMetaData.java | 5 +- .../spanner/jdbc/JdbcParameterStore.java | 38 ++++++++++++-- .../cloud/spanner/jdbc/JdbcResultSet.java | 28 +++++++++- .../google/cloud/spanner/jdbc/JsonType.java | 6 +++ .../cloud/spanner/jdbc/PgJsonbType.java | 6 +++ .../cloud/spanner/jdbc/ProtoEnumType.java | 6 +++ .../cloud/spanner/jdbc/ProtoMessageType.java | 6 +++ .../jdbc/JdbcDatabaseMetaDataTest.java | 29 ++++++++++- .../spanner/jdbc/JdbcParameterStoreTest.java | 51 ++++++++++++++++--- 9 files changed, 160 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 025b26570ac6..7bafb2f37432 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.connection.Connection.InternalMetadataQuery; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableSet; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -1284,7 +1285,9 @@ public ResultSet getTypeInfo() { .set("NUM_PREC_RADIX") .to(10) .build(), - getJsonType(connection.getDialect())))); + getJsonType(connection.getDialect()))), + // Allow column 2 to be cast to short without any range checks. + ImmutableSet.of(2)); } private Struct getJsonType(Dialect dialect) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index accb6323f5c0..47d096261dbd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -284,9 +284,13 @@ private boolean isTypeSupported(int sqlType) { case Types.NUMERIC: case Types.DECIMAL: case JsonType.VENDOR_TYPE_NUMBER: + case JsonType.SHORT_VENDOR_TYPE_NUMBER: case PgJsonbType.VENDOR_TYPE_NUMBER: + case PgJsonbType.SHORT_VENDOR_TYPE_NUMBER: case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER: case ProtoEnumType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER: return true; } return false; @@ -348,19 +352,23 @@ private boolean isValidTypeAndValue(Object value, int sqlType) { case Types.NCLOB: return value instanceof NClob || value instanceof Reader; case JsonType.VENDOR_TYPE_NUMBER: + case JsonType.SHORT_VENDOR_TYPE_NUMBER: return value instanceof String || value instanceof InputStream || value instanceof Reader || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.JSON); case PgJsonbType.VENDOR_TYPE_NUMBER: + case PgJsonbType.SHORT_VENDOR_TYPE_NUMBER: return value instanceof String || value instanceof InputStream || value instanceof Reader || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.PG_JSONB); case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER: return value instanceof AbstractMessage || value instanceof byte[]; case ProtoEnumType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER: return value instanceof ProtocolMessageEnum || value instanceof Number; } return false; @@ -449,7 +457,12 @@ private Builder setSingleValue(ValueBinder binder, Object value, Intege /** Set a JDBC parameter value on a Spanner {@link Statement} with a known SQL type. */ private Builder setParamWithKnownType(ValueBinder binder, Object value, Integer sqlType) throws SQLException { - switch (sqlType) { + if (sqlType == null) { + return null; + } + int type = sqlType; + + switch (type) { case Types.BIT: case Types.BOOLEAN: if (value instanceof Boolean) { @@ -522,7 +535,9 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } return binder.to(stringValue); case JsonType.VENDOR_TYPE_NUMBER: + case JsonType.SHORT_VENDOR_TYPE_NUMBER: case PgJsonbType.VENDOR_TYPE_NUMBER: + case PgJsonbType.SHORT_VENDOR_TYPE_NUMBER: String jsonValue; if (value instanceof String) { jsonValue = (String) value; @@ -534,7 +549,8 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, throw JdbcSqlExceptionFactory.of( value + " is not a valid JSON value", Code.INVALID_ARGUMENT); } - if (sqlType == PgJsonbType.VENDOR_TYPE_NUMBER) { + if (type == PgJsonbType.VENDOR_TYPE_NUMBER + || type == PgJsonbType.SHORT_VENDOR_TYPE_NUMBER) { return binder.to(Value.pgJsonb(jsonValue)); } return binder.to(Value.json(jsonValue)); @@ -631,6 +647,7 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, } throw JdbcSqlExceptionFactory.of(value + " is not a valid clob", Code.INVALID_ARGUMENT); case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER: if (value instanceof AbstractMessage) { return binder.to((AbstractMessage) value); } else if (value instanceof byte[]) { @@ -640,6 +657,7 @@ private Builder setParamWithKnownType(ValueBinder binder, Object value, value + " is not a valid PROTO value", Code.INVALID_ARGUMENT); } case ProtoEnumType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER: if (value instanceof ProtocolMessageEnum) { return binder.to((ProtocolMessageEnum) value); } else if (value instanceof Number) { @@ -809,8 +827,10 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.NCLOB: return binder.toStringArray(null); case JsonType.VENDOR_TYPE_NUMBER: + case JsonType.SHORT_VENDOR_TYPE_NUMBER: return binder.toJsonArray(null); case PgJsonbType.VENDOR_TYPE_NUMBER: + case PgJsonbType.SHORT_VENDOR_TYPE_NUMBER: return binder.toPgJsonbArray(null); case Types.DATE: return binder.toDateArray(null); @@ -825,7 +845,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu case Types.BLOB: return binder.toBytesArray(null); case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER: case ProtoEnumType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER: return binder.to( Value.untyped( com.google.protobuf.Value.newBuilder() @@ -886,9 +908,10 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value)); } else if (String[].class.isAssignableFrom(value.getClass())) { - if (type == JsonType.VENDOR_TYPE_NUMBER) { + if (type == JsonType.VENDOR_TYPE_NUMBER || type == JsonType.SHORT_VENDOR_TYPE_NUMBER) { return binder.toJsonArray(Arrays.asList((String[]) value)); - } else if (type == PgJsonbType.VENDOR_TYPE_NUMBER) { + } else if (type == PgJsonbType.VENDOR_TYPE_NUMBER + || type == PgJsonbType.SHORT_VENDOR_TYPE_NUMBER) { return binder.toPgJsonbArray(Arrays.asList((String[]) value)); } else { return binder.toStringArray(Arrays.asList((String[]) value)); @@ -992,11 +1015,13 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { Value.untyped( com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build())); } - switch (sqlType) { + int type = sqlType; + switch (type) { case Types.BIGINT: return binder.to((Long) null); case Types.BINARY: case ProtoMessageType.VENDOR_TYPE_NUMBER: + case ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER: return binder.to((ByteArray) null); case Types.BLOB: return binder.to((ByteArray) null); @@ -1021,6 +1046,7 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { return binder.to((Double) null); case Types.INTEGER: case ProtoEnumType.VENDOR_TYPE_NUMBER: + case ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER: return binder.to((Long) null); case Types.LONGNVARCHAR: return binder.to((String) null); @@ -1052,8 +1078,10 @@ private Builder setNullValue(ValueBinder binder, Integer sqlType) { case Types.VARCHAR: return binder.to((String) null); case JsonType.VENDOR_TYPE_NUMBER: + case JsonType.SHORT_VENDOR_TYPE_NUMBER: return binder.to(Value.json(null)); case PgJsonbType.VENDOR_TYPE_NUMBER: + case PgJsonbType.SHORT_VENDOR_TYPE_NUMBER: return binder.to(Value.pgJsonb(null)); default: return binder.to( diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 054c1ed007ea..00df251162c3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.connection.PartitionedQueryResultSet; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; @@ -57,8 +58,16 @@ class JdbcResultSet extends AbstractJdbcResultSet { static JdbcResultSet of(com.google.cloud.spanner.ResultSet resultSet) { - Preconditions.checkNotNull(resultSet); - return new JdbcResultSet(null, resultSet); + return of(resultSet, ImmutableSet.of()); + } + + static JdbcResultSet of( + com.google.cloud.spanner.ResultSet resultSet, + ImmutableSet columnsAllowedUncheckedLongCastToShort) { + return new JdbcResultSet( + null, + Preconditions.checkNotNull(resultSet), + Preconditions.checkNotNull(columnsAllowedUncheckedLongCastToShort)); } static JdbcResultSet of(Statement statement, com.google.cloud.spanner.ResultSet resultSet) { @@ -129,10 +138,19 @@ public Struct next() { private boolean nextCalledForMetaData = false; private boolean nextCalledForMetaDataResult = false; private long currentRow = 0L; + private final ImmutableSet columnsAllowedUncheckedLongCastToShort; JdbcResultSet(Statement statement, com.google.cloud.spanner.ResultSet spanner) { + this(statement, spanner, ImmutableSet.of()); + } + + JdbcResultSet( + Statement statement, + com.google.cloud.spanner.ResultSet spanner, + ImmutableSet columnsAllowedUncheckedLongCastToShort) { super(spanner); this.statement = statement; + this.columnsAllowedUncheckedLongCastToShort = columnsAllowedUncheckedLongCastToShort; } void checkClosedAndValidRow() throws SQLException { @@ -327,6 +345,12 @@ public short getShort(int columnIndex) throws SQLException { : checkedCastToShort(Double.valueOf(spanner.getDouble(spannerIndex)).longValue()); case INT64: case ENUM: + if (this.columnsAllowedUncheckedLongCastToShort.contains(columnIndex)) { + // This is used to allow frameworks that call getShort(int) on the ResultSet that is + // returned by DatabaseMetadata#getTypeInfo() to get the type code as a short, even when + // the value is out of range for a short. + return isNull ? 0 : (short) spanner.getLong(spannerIndex); + } return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); case NUMERIC: return isNull ? 0 : checkedCastToShort(spanner.getBigDecimal(spannerIndex)); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java index 44af26b6eac5..3e69adea4445 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.spanner.v1.TypeCode; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLType; @@ -31,6 +32,11 @@ public class JsonType implements SQLType { * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.JSON_VALUE; + /** + * Define a short type number as well, as this is what is expected to be returned in {@link + * DatabaseMetaData#getTypeInfo()}. + */ + public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER; private JsonType() {} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java index 8627d341391d..b0a819b0db72 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.spanner.v1.TypeCode; +import java.sql.DatabaseMetaData; import java.sql.SQLType; public class PgJsonbType implements SQLType { @@ -27,6 +28,11 @@ public class PgJsonbType implements SQLType { * the range starting at 100,000 (see {@link JsonType}). */ public static final int VENDOR_TYPE_NUMBER = 200_000 + TypeCode.JSON_VALUE; + /** + * Define a short type number as well, as this is what is expected to be returned in {@link + * DatabaseMetaData#getTypeInfo()}. + */ + public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER; private PgJsonbType() {} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java index 478d082e9664..953fb73b39c5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.spanner.v1.TypeCode; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLType; @@ -31,6 +32,11 @@ public class ProtoEnumType implements SQLType { * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.ENUM_VALUE; + /** + * Define a short type number as well, as this is what is expected to be returned in {@link + * DatabaseMetaData#getTypeInfo()}. + */ + public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER; private ProtoEnumType() {} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java index 5a813d66d7f0..2a7f6f705d8c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.jdbc; import com.google.spanner.v1.TypeCode; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLType; @@ -31,6 +32,11 @@ public class ProtoMessageType implements SQLType { * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.PROTO_VALUE; + /** + * Define a short type number as well, as this is what is expected to be returned in {@link + * DatabaseMetaData#getTypeInfo()}. + */ + public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER; private ProtoMessageType() {} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 3e94a4ceb3ef..64499f40a21a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -475,24 +475,51 @@ public void testGetTypeInfo() throws SQLException { try (ResultSet rs = meta.getTypeInfo()) { assertTrue(rs.next()); assertEquals("STRING", rs.getString("TYPE_NAME")); + assertEquals(Types.NVARCHAR, rs.getInt("DATA_TYPE")); + assertEquals(Types.NVARCHAR, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("INT64", rs.getString("TYPE_NAME")); + assertEquals(Types.BIGINT, rs.getInt("DATA_TYPE")); + assertEquals(Types.BIGINT, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("BYTES", rs.getString("TYPE_NAME")); + assertEquals(Types.BINARY, rs.getInt("DATA_TYPE")); + assertEquals(Types.BINARY, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("FLOAT32", rs.getString("TYPE_NAME")); + assertEquals(Types.REAL, rs.getInt("DATA_TYPE")); + assertEquals(Types.REAL, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("FLOAT64", rs.getString("TYPE_NAME")); + assertEquals(Types.DOUBLE, rs.getInt("DATA_TYPE")); + assertEquals(Types.DOUBLE, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("BOOL", rs.getString("TYPE_NAME")); + assertEquals(Types.BOOLEAN, rs.getInt("DATA_TYPE")); + assertEquals(Types.BOOLEAN, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("DATE", rs.getString("TYPE_NAME")); + assertEquals(Types.DATE, rs.getInt("DATA_TYPE")); + assertEquals(Types.DATE, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("TIMESTAMP", rs.getString("TYPE_NAME")); + assertEquals(Types.TIMESTAMP, rs.getInt("DATA_TYPE")); + assertEquals(Types.TIMESTAMP, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); assertEquals("NUMERIC", rs.getString("TYPE_NAME")); + assertEquals(Types.NUMERIC, rs.getInt("DATA_TYPE")); + assertEquals(Types.NUMERIC, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); - assertEquals(dialect == Dialect.POSTGRESQL ? "JSONB" : "JSON", rs.getString("TYPE_NAME")); + if (dialect == Dialect.POSTGRESQL) { + assertEquals("JSONB", rs.getString("TYPE_NAME")); + assertEquals(PgJsonbType.VENDOR_TYPE_NUMBER, rs.getInt("DATA_TYPE")); + assertEquals(PgJsonbType.SHORT_VENDOR_TYPE_NUMBER, rs.getShort("DATA_TYPE")); + } else { + assertEquals("JSON", rs.getString("TYPE_NAME")); + assertEquals(JsonType.VENDOR_TYPE_NUMBER, rs.getInt("DATA_TYPE")); + assertEquals(JsonType.SHORT_VENDOR_TYPE_NUMBER, rs.getShort("DATA_TYPE")); + } + assertFalse(rs.next()); ResultSetMetaData rsmd = rs.getMetaData(); assertEquals(18, rsmd.getColumnCount()); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index eb8237c0b608..d77c932c1b9e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -225,6 +225,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(jsonString, params.getParameter(1)); verifyParameter(params, Value.json(jsonString)); + params.setParameter(1, jsonString, (int) JsonType.SHORT_VENDOR_TYPE_NUMBER); + assertEquals(jsonString, params.getParameter(1)); + verifyParameter(params, Value.json(jsonString)); + params.setParameter(1, jsonString, JsonType.INSTANCE); assertEquals(jsonString, params.getParameter(1)); verifyParameter(params, Value.json(jsonString)); @@ -233,6 +237,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(jsonString, params.getParameter(1)); verifyParameter(params, Value.pgJsonb(jsonString)); + params.setParameter(1, jsonString, (int) PgJsonbType.SHORT_VENDOR_TYPE_NUMBER); + assertEquals(jsonString, params.getParameter(1)); + verifyParameter(params, Value.pgJsonb(jsonString)); + params.setParameter(1, jsonString, PgJsonbType.INSTANCE); assertEquals(jsonString, params.getParameter(1)); verifyParameter(params, Value.pgJsonb(jsonString)); @@ -250,6 +258,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(singerInfo, params.getParameter(1)); verifyParameter(params, Value.protoMessage(singerInfo)); + params.setParameter(1, singerInfo, (int) ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER); + assertEquals(singerInfo, params.getParameter(1)); + verifyParameter(params, Value.protoMessage(singerInfo)); + params.setParameter(1, singerInfo, ProtoMessageType.INSTANCE); assertEquals(singerInfo, params.getParameter(1)); verifyParameter(params, Value.protoMessage(singerInfo)); @@ -259,6 +271,11 @@ public void testSetParameterWithType() throws SQLException, IOException { assertArrayEquals(singerInfo.toByteArray(), (byte[]) params.getParameter(1)); verifyParameter(params, Value.bytes(ByteArray.copyFrom(singerInfo.toByteArray()))); + params.setParameter( + 1, singerInfo.toByteArray(), (int) ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER); + assertArrayEquals(singerInfo.toByteArray(), (byte[]) params.getParameter(1)); + verifyParameter(params, Value.bytes(ByteArray.copyFrom(singerInfo.toByteArray()))); + params.setParameter(1, singerInfo, Types.BINARY); assertEquals(singerInfo, params.getParameter(1)); verifyParameter(params, Value.protoMessage(singerInfo)); @@ -267,6 +284,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(Genre.ROCK, params.getParameter(1)); verifyParameter(params, Value.protoEnum(Genre.ROCK)); + params.setParameter(1, Genre.ROCK, (int) ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER); + assertEquals(Genre.ROCK, params.getParameter(1)); + verifyParameter(params, Value.protoEnum(Genre.ROCK)); + params.setParameter(1, Genre.ROCK, ProtoEnumType.INSTANCE); assertEquals(Genre.ROCK, params.getParameter(1)); verifyParameter(params, Value.protoEnum(Genre.ROCK)); @@ -276,6 +297,10 @@ public void testSetParameterWithType() throws SQLException, IOException { assertEquals(Genre.ROCK.getNumber(), params.getParameter(1)); verifyParameter(params, Value.int64(Genre.ROCK.getNumber())); + params.setParameter(1, Genre.ROCK.getNumber(), (int) ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER); + assertEquals(Genre.ROCK.getNumber(), params.getParameter(1)); + verifyParameter(params, Value.int64(Genre.ROCK.getNumber())); + params.setParameter(1, Genre.ROCK, Types.INTEGER); assertEquals(Genre.ROCK, params.getParameter(1)); verifyParameter(params, Value.protoEnum(Genre.ROCK)); @@ -287,7 +312,8 @@ public void testSetParameterWithType() throws SQLException, IOException { Types.SMALLINT, Types.INTEGER, Types.BIGINT, - ProtoEnumType.VENDOR_TYPE_NUMBER + ProtoEnumType.VENDOR_TYPE_NUMBER, + ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER }) { params.setParameter(1, (byte) 1, type); assertEquals(1, ((Byte) params.getParameter(1)).byteValue()); @@ -397,7 +423,11 @@ public void testSetParameterWithType() throws SQLException, IOException { // types that should lead to bytes (except BLOB which is handled separately) for (int type : new int[] { - Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY, ProtoMessageType.VENDOR_TYPE_NUMBER + Types.BINARY, + Types.VARBINARY, + Types.LONGVARBINARY, + ProtoMessageType.VENDOR_TYPE_NUMBER, + ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER }) { params.setParameter(1, new byte[] {1, 2, 3}, type); assertArrayEquals(new byte[] {1, 2, 3}, (byte[]) params.getParameter(1)); @@ -512,7 +542,8 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { Types.SMALLINT, Types.INTEGER, Types.BIGINT, - ProtoEnumType.VENDOR_TYPE_NUMBER + ProtoEnumType.VENDOR_TYPE_NUMBER, + ProtoEnumType.SHORT_VENDOR_TYPE_NUMBER }) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); @@ -557,7 +588,11 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { // types that should lead to bytes (except BLOB which is handled separately) for (int type : new int[] { - Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY, ProtoMessageType.VENDOR_TYPE_NUMBER + Types.BINARY, + Types.VARBINARY, + Types.LONGVARBINARY, + ProtoMessageType.VENDOR_TYPE_NUMBER, + ProtoMessageType.SHORT_VENDOR_TYPE_NUMBER }) { assertInvalidParameter(params, "1", type); assertInvalidParameter(params, new Object(), type); @@ -576,7 +611,9 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { Types.NVARCHAR, Types.LONGNVARCHAR, JsonType.VENDOR_TYPE_NUMBER, - PgJsonbType.VENDOR_TYPE_NUMBER + JsonType.SHORT_VENDOR_TYPE_NUMBER, + PgJsonbType.VENDOR_TYPE_NUMBER, + PgJsonbType.SHORT_VENDOR_TYPE_NUMBER }) { assertInvalidParameter(params, new Object(), type); assertInvalidParameter(params, Boolean.TRUE, type); @@ -603,7 +640,9 @@ public void testSetInvalidParameterWithType() throws SQLException, IOException { Types.NVARCHAR, Types.LONGNVARCHAR, JsonType.VENDOR_TYPE_NUMBER, - PgJsonbType.VENDOR_TYPE_NUMBER + JsonType.SHORT_VENDOR_TYPE_NUMBER, + PgJsonbType.VENDOR_TYPE_NUMBER, + PgJsonbType.SHORT_VENDOR_TYPE_NUMBER }) { Reader reader = new StringReader("test"); reader.close(); From 9e935f500c33ed8413ad3415ccb1725ea754d413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 7 Aug 2024 19:13:30 +0200 Subject: [PATCH 1361/1979] deps: bump Spanner to 6.72.0 (#1698) --- java-spanner-jdbc/pom.xml | 2 +- .../spanner/jdbc/JdbcConnectionUrlTest.java | 7 ++++-- .../MultiplexedSessionsMockServerTest.java | 22 +++++++------------ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d510d8133838..f205870d900e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.71.0 + 6.72.0 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java index bcf8256dfc2c..756007190c42 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java @@ -16,7 +16,7 @@ package com.google.cloud.spanner.jdbc; -import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.google.cloud.spanner.connection.AbstractMockServerTest; @@ -103,7 +103,10 @@ public void testMaxSessions() executor1.shutdown(); executor2.shutdown(); } - assertThat(mockSpanner.numSessionsCreated()).isEqualTo(1); + assertEquals(1, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); + BatchCreateSessionsRequest request = + mockSpanner.getRequestsOfType(BatchCreateSessionsRequest.class).get(0); + assertEquals(1, request.getSessionCount()); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java index 7688999a1984..8415f1a3794e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.SpannerPool; +import com.google.spanner.v1.BatchCreateSessionsRequest; import com.google.spanner.v1.CreateSessionRequest; import com.google.spanner.v1.ExecuteSqlRequest; import com.google.spanner.v1.Session; @@ -188,8 +189,6 @@ public void testUsesRegularSessionForQueryInTransaction() throws SQLException { public void testUsesMultiplexedSessionInCombinationWithSessionPoolOptions() throws SQLException { // Create a connection that uses a session pool with MinSessions=0. // This should stop any regular sessions from being created. - // TODO: Modify this test once https://github.com/googleapis/java-spanner/pull/3197 has been - // released. try (Connection connection = DriverManager.getConnection(createUrl() + ";minSessions=0")) { assertTrue(connection.getAutoCommit()); try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { @@ -199,19 +198,14 @@ public void testUsesMultiplexedSessionInCombinationWithSessionPoolOptions() thro } } } - // TODO: Remove this line once https://github.com/googleapis/java-spanner/pull/3197 has been - // released. - // Adding 'minSessions=X' or 'maxSessions=x' to the connection URL currently disables the use of - // multiplexed sessions due to a bug in the Spanner Java client. - assertEquals(0, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); // Verify that one multiplexed session was created and used. - // TODO: Uncomment - // assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); - // CreateSessionRequest request = - // mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); - // assertTrue(request.getSession().getMultiplexed()); - // // There should be no regular sessions in use. - // assertEquals(0, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); + assertEquals(1, mockSpanner.countRequestsOfType(CreateSessionRequest.class)); + CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); + assertTrue(request.getSession().getMultiplexed()); + // There should be no regular sessions in use. + // However, the query that detects the dialect that is used, uses a regular session. + // This should be fixed in the Java client. + assertEquals(1, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); } } From 449291359b1ff7f346356d0f4de355adfe4b3406 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 17:34:19 +0000 Subject: [PATCH 1362/1979] chore(main): release 2.20.2 (#1678) :robot: I have created a release *beep* *boop* --- ## [2.20.2](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.20.1...v2.20.2) (2024-08-07) ### Bug Fixes * Support getShort for DATA_TYPE in TypeInfo ([#1691](https://togithub.com/googleapis/java-spanner-jdbc/issues/1691)) ([8c3dd24](https://togithub.com/googleapis/java-spanner-jdbc/commit/8c3dd24dd662cc4dccaa18c5753792aebef9e4a0)) ### Dependencies * Bump Spanner to 6.72.0 ([#1698](https://togithub.com/googleapis/java-spanner-jdbc/issues/1698)) ([9e935f5](https://togithub.com/googleapis/java-spanner-jdbc/commit/9e935f500c33ed8413ad3415ccb1725ea754d413)) * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.47.0 ([#1695](https://togithub.com/googleapis/java-spanner-jdbc/issues/1695)) ([2c59ba5](https://togithub.com/googleapis/java-spanner-jdbc/commit/2c59ba5958d3c40bdda89c5d7c71a58501e3424e)) * Update dependency com.google.cloud:google-cloud-trace to v2.47.0 ([#1696](https://togithub.com/googleapis/java-spanner-jdbc/issues/1696)) ([7db29b4](https://togithub.com/googleapis/java-spanner-jdbc/commit/7db29b4123f514e968f559c907aa24d1acdde2c5)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.33.0 ([#1693](https://togithub.com/googleapis/java-spanner-jdbc/issues/1693)) ([7b18575](https://togithub.com/googleapis/java-spanner-jdbc/commit/7b1857556cc1b499a81c19d705ecedd2656bb7ef)) * Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.31.0 ([#1679](https://togithub.com/googleapis/java-spanner-jdbc/issues/1679)) ([f4fcd1a](https://togithub.com/googleapis/java-spanner-jdbc/commit/f4fcd1afc8668f66adee4a3c5843ddf7661f7856)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.40.0 ([#1676](https://togithub.com/googleapis/java-spanner-jdbc/issues/1676)) ([bc24c27](https://togithub.com/googleapis/java-spanner-jdbc/commit/bc24c277978d80bb9b4a93c9a56dfc15d1b174ba)) * Update dependency org.hamcrest:hamcrest to v3 ([#1697](https://togithub.com/googleapis/java-spanner-jdbc/issues/1697)) ([2fc58cc](https://togithub.com/googleapis/java-spanner-jdbc/commit/2fc58ccc31f90fae7791edd390e5aa6a94c322a5)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.2 ([#1685](https://togithub.com/googleapis/java-spanner-jdbc/issues/1685)) ([080e860](https://togithub.com/googleapis/java-spanner-jdbc/commit/080e8600316f893b391045d00381acc48e5b2a89)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.2 ([#1686](https://togithub.com/googleapis/java-spanner-jdbc/issues/1686)) ([ccd6a9c](https://togithub.com/googleapis/java-spanner-jdbc/commit/ccd6a9c37cbad7371573205e2349fd0b69d557b8)) * Update dependency org.springframework.data:spring-data-bom to v2024.0.2 ([#1680](https://togithub.com/googleapis/java-spanner-jdbc/issues/1680)) ([4ff9caa](https://togithub.com/googleapis/java-spanner-jdbc/commit/4ff9caab95d81567c6f48733e319f5ecbf443c15)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 21 +++++++++++++++++++++ java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 61628c9de2d7..4243899373db 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [2.20.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.1...v2.20.2) (2024-08-07) + + +### Bug Fixes + +* Support getShort for DATA_TYPE in TypeInfo ([#1691](https://github.com/googleapis/java-spanner-jdbc/issues/1691)) ([828aff6](https://github.com/googleapis/java-spanner-jdbc/commit/828aff6f7015b5f91ebbc2ad54aeeecf5515a9bd)) + + +### Dependencies + +* Bump Spanner to 6.72.0 ([#1698](https://github.com/googleapis/java-spanner-jdbc/issues/1698)) ([ce00b17](https://github.com/googleapis/java-spanner-jdbc/commit/ce00b176d39fe728eadd386d4e9794dc1fc0fbca)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.47.0 ([#1695](https://github.com/googleapis/java-spanner-jdbc/issues/1695)) ([148c655](https://github.com/googleapis/java-spanner-jdbc/commit/148c655a8bd1309250b5158d0f20a167e89bd9fe)) +* Update dependency com.google.cloud:google-cloud-trace to v2.47.0 ([#1696](https://github.com/googleapis/java-spanner-jdbc/issues/1696)) ([c6a54f7](https://github.com/googleapis/java-spanner-jdbc/commit/c6a54f7a3045fc711fcad8d16294c67aa8eb8810)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.33.0 ([#1693](https://github.com/googleapis/java-spanner-jdbc/issues/1693)) ([08011a5](https://github.com/googleapis/java-spanner-jdbc/commit/08011a520a2fb14d06614da5e2c7b9ae47d6c6f1)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.31.0 ([#1679](https://github.com/googleapis/java-spanner-jdbc/issues/1679)) ([ddf47f4](https://github.com/googleapis/java-spanner-jdbc/commit/ddf47f4fc7e1c05e6e3086ada0ff3b2c1efeb2af)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.40.0 ([#1676](https://github.com/googleapis/java-spanner-jdbc/issues/1676)) ([faf7c49](https://github.com/googleapis/java-spanner-jdbc/commit/faf7c4908a926cd7a10ea0b860babcaa97c4c7e1)) +* Update dependency org.hamcrest:hamcrest to v3 ([#1697](https://github.com/googleapis/java-spanner-jdbc/issues/1697)) ([3933cf2](https://github.com/googleapis/java-spanner-jdbc/commit/3933cf2c4099e0d06c1dc4e4583c11ba5e4eae19)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.2 ([#1685](https://github.com/googleapis/java-spanner-jdbc/issues/1685)) ([6a57b49](https://github.com/googleapis/java-spanner-jdbc/commit/6a57b49a34f2b44f42f6c07eaf5da063a1d648d0)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.2 ([#1686](https://github.com/googleapis/java-spanner-jdbc/issues/1686)) ([2be70c7](https://github.com/googleapis/java-spanner-jdbc/commit/2be70c74f673c796d7b366b56644b6d00038bc07)) +* Update dependency org.springframework.data:spring-data-bom to v2024.0.2 ([#1680](https://github.com/googleapis/java-spanner-jdbc/issues/1680)) ([23934f7](https://github.com/googleapis/java-spanner-jdbc/commit/23934f7f38f5c99b7a6859ab69525ce368317128)) + ## [2.20.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.0...v2.20.1) (2024-07-04) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f205870d900e..9f17e9c788d0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.2-SNAPSHOT + 2.20.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index cc99c9b5eab4..ef21adcf195b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.2-SNAPSHOT + 2.20.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 807395b03d74..6f8ffa714e6b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.1:2.20.2-SNAPSHOT +google-cloud-spanner-jdbc:2.20.2:2.20.2 From c90084369508cd3052c7360681436a84cbb69621 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 20:42:15 +0200 Subject: [PATCH 1363/1979] chore(main): release 2.20.3-SNAPSHOT (#1699) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9f17e9c788d0..48bad350bbb8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.2 + 2.20.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ef21adcf195b..fcfad34c952c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.20.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6f8ffa714e6b..716f29f11957 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.2:2.20.2 +google-cloud-spanner-jdbc:2.20.2:2.20.3-SNAPSHOT From 093202f555d5a4fdf66093db87c3c2af52680911 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 11:54:29 +0200 Subject: [PATCH 1364/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.34.0 (#1705) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 09f9543875de..8d462abb5838 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.33.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.34.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 7008a7215676..53cd15405a61 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.33.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.34.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 931f9bb00528..e211e47fc692 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.33.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.34.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 48bad350bbb8..4ab18c747bcb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.33.0 + 3.34.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ee6deda8b3f0..1df5b3ee5645 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.33.0 + 3.34.0 From f2f0da49e51ff9c8d54b4912fc7cd9086dd96419 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:04:54 +0200 Subject: [PATCH 1365/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.3 (#1704) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index f2d20d8ac933..019a08a3fb5e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.2 + 2024.0.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index a5ad7633d73c..0768173bfd28 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.2 + 2024.0.3 import pom From 096fb44f4ca007b3359e3d9e3c733912c3fd4bc6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:05:43 +0200 Subject: [PATCH 1366/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.41.0 (#1703) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 019a08a3fb5e..fbf80e355b85 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.40.0 + 1.41.0 pom import From f3dce3297b91913ffac0e25a9a301b49baa41a58 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:06:10 +0200 Subject: [PATCH 1367/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 (#1702) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index fbf80e355b85..866ef4812193 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.71.0 + 6.72.0 import pom From 31f437c8f0b320c7069de2807ef7db006bf356c1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:06:46 +0200 Subject: [PATCH 1368/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.44.0 (#1701) --- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 1df5b3ee5645..3260b2985f88 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 866ef4812193..f6135bb29d9a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 0768173bfd28..29fa43af7464 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 import pom From e45e6c95b4d31e933aca1ed51280c64ac5a4b988 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 12:07:11 +0200 Subject: [PATCH 1369/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.2 (#1700) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 87be572f40d3..522c41a61e8a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1 + 2.20.2 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index f6135bb29d9a..0cb0aaa7cb40 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.1 + 2.20.2 org.postgresql From 3a93aa4760190929f3a079b54f9b5a6492f2a944 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 Aug 2024 14:21:24 +0200 Subject: [PATCH 1370/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.1 (#1684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency org.testcontainers:testcontainers to v1.20.1 * chore: ignore errors during availability check --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java | 8 +++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4ab18c747bcb..97c020916da1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 3260b2985f88..2d0ed281141a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -48,7 +48,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 0cb0aaa7cb40..b6ea7780b077 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -109,7 +109,7 @@ org.testcontainers testcontainers - 1.19.8 + 1.20.1 test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java index 8874120484cd..74a00503802c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java @@ -45,7 +45,13 @@ public class ConcurrentTransactionOnEmulatorTest { @BeforeClass public static void startEmulator() { - assumeTrue(DockerClientFactory.instance().isDockerAvailable()); + boolean dockerAvailable = false; + try { + dockerAvailable = DockerClientFactory.instance().isDockerAvailable(); + } catch (Exception ignore) { + // Ignore, and just skip the test. + } + assumeTrue(dockerAvailable); emulator = new GenericContainer<>( From 20b90933379e4e645b4c5cefd460c7495b6bffd0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 12:16:31 +0200 Subject: [PATCH 1371/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.3 (#1707) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 31285be61f93..39d5d24c8a61 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.2 + 3.1.3 true From ea4ae06afb662d620c5bec2a4585fd360864d0d9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 14:31:25 +0200 Subject: [PATCH 1372/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.24 (#1708) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index b6ea7780b077..6a138bbcf95b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ com.spotify.fmt fmt-maven-plugin - 2.23 + 2.24 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 29fa43af7464..87793be8d4d0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -97,7 +97,7 @@ com.spotify.fmt fmt-maven-plugin - 2.23 + 2.24 From d67a249ab25d9fed82b96235d19e64ef3fe1e785 Mon Sep 17 00:00:00 2001 From: Szabolcs Rozsnyai Date: Tue, 20 Aug 2024 14:50:19 +0200 Subject: [PATCH 1373/1979] feat: add Quickperf for simple performance testing with JDBC (#1619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat:Adding Quickperf for simple performance testing with JDBC * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/readme.md Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Update samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java Co-authored-by: Knut Olav Løite * Updating based on review comments #1619 * Updating based on review comments * Incorporating additional changes from review #1619 * Split app into two classes to separate app driver and app following review feedback #1619 * fixed compilation issues * Update readme.md fixed markdown issues for indented bullet points * Update readme.md removed -Dexec.args from readme * Update QuickPerf.java separated thread init (for sampling) from thread execution * Update ProgressTracker.java added InterruptedException handling * chore: add parent pom and run code formatter * chore: cleanup some warnings + simplify test setup * test: add test runner for quickperf * chore: remove some more warnings * fix: include empty test file --------- Co-authored-by: Knut Olav Løite --- .../.github/workflows/quickperf.yaml | 30 ++ .../samples/quickperf/.gitignore | 3 + .../quickperf/exampleconfigs/config.json | 9 + .../exampleconfigs/users/groupmgt_config.json | 13 + .../exampleconfigs/users/loadtestusers.json | 13 + .../users/membership_config.json | 9 + .../quickperf/exampleconfigs/users/run.sh | 15 + .../quickperf/exampleconfigs/users/users.ddl | 17 + .../exampleconfigs/users/users_config.json | 13 + .../samples/quickperf/java.header | 15 + .../samples/quickperf/license-checks.xml | 10 + java-spanner-jdbc/samples/quickperf/pom.xml | 100 ++++++ java-spanner-jdbc/samples/quickperf/readme.md | 302 +++++++++++++++++ .../cloud/jdbc/quickperf/ProgressTracker.java | 79 +++++ .../cloud/jdbc/quickperf/QuickPerf.java | 191 +++++++++++ .../cloud/jdbc/quickperf/QuickPerfRunner.java | 320 ++++++++++++++++++ .../cloud/jdbc/quickperf/config/Config.java | 145 ++++++++ .../jdbc/quickperf/config/ConfigParser.java | 30 ++ .../jdbc/quickperf/config/QueryParam.java | 38 +++ .../google/cloud/jdbc/quickperf/AppTest.java | 174 ++++++++++ .../cloud/jdbc/quickperf/ProjectConfig.java | 113 +++++++ .../cloud/jdbc/quickperf/QueryParam.java | 45 +++ .../src/test/resources/testfile.json | 0 23 files changed, 1684 insertions(+) create mode 100644 java-spanner-jdbc/.github/workflows/quickperf.yaml create mode 100644 java-spanner-jdbc/samples/quickperf/.gitignore create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/config.json create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/groupmgt_config.json create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/loadtestusers.json create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/membership_config.json create mode 100755 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/run.sh create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users.ddl create mode 100644 java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users_config.json create mode 100644 java-spanner-jdbc/samples/quickperf/java.header create mode 100644 java-spanner-jdbc/samples/quickperf/license-checks.xml create mode 100644 java-spanner-jdbc/samples/quickperf/pom.xml create mode 100644 java-spanner-jdbc/samples/quickperf/readme.md create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java create mode 100644 java-spanner-jdbc/samples/quickperf/src/test/resources/testfile.json diff --git a/java-spanner-jdbc/.github/workflows/quickperf.yaml b/java-spanner-jdbc/.github/workflows/quickperf.yaml new file mode 100644 index 000000000000..03c242fefe92 --- /dev/null +++ b/java-spanner-jdbc/.github/workflows/quickperf.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Github action job to test core java library features on +# downstream client libraries before they are released. +on: + pull_request: +name: quickperf +jobs: + quickperf: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + - name: Run tests + run: mvn test + working-directory: samples/quickperf diff --git a/java-spanner-jdbc/samples/quickperf/.gitignore b/java-spanner-jdbc/samples/quickperf/.gitignore new file mode 100644 index 000000000000..1df5b5e0cfce --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/.gitignore @@ -0,0 +1,3 @@ +target +.vscode +.DS_Store \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/config.json b/java-spanner-jdbc/samples/quickperf/exampleconfigs/config.json new file mode 100644 index 000000000000..b43c32e1c9cb --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/config.json @@ -0,0 +1,9 @@ +{ + "project": "xxxx", + "instance": "xxx", + "database": "xxx", + "threads": 1, + "iterations": 100, + "query": "SELECT 1", + "writeMetricToFile": false +} \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/groupmgt_config.json b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/groupmgt_config.json new file mode 100644 index 000000000000..8bc094513273 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/groupmgt_config.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 4, + "iterations": 250, + "query": "INSERT INTO GroupMgmt (group_id, grpname) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/loadtestusers.json b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/loadtestusers.json new file mode 100644 index 000000000000..4a4a3aee87c0 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/loadtestusers.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 10, + "query": "SELECT users.user_id, membership.enrolled, GroupMgmt.grpname FROM users, GroupMgmt, membership WHERE users.user_id = ? AND users.user_id = membership.user_id AND GroupMgmt.group_id = membership.group_id", + "samplingQuery": "SELECT user_id FROM Users TABLESAMPLE RESERVOIR (100000 ROWS)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#pi"} + ] +} \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/membership_config.json b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/membership_config.json new file mode 100644 index 000000000000..d3c56d101a6c --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/membership_config.json @@ -0,0 +1,9 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 100, + "query": "INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP())", + "writeMetricToFile": false +} \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/run.sh b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/run.sh new file mode 100755 index 000000000000..ac82643f8cd1 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Generate Data +cd ../.. + +mvn -q compile + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/users_config.json" + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/groupmgt_config.json" + +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/membership_config.json" + +# load test random users +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/loadtestusers.json" diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users.ddl b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users.ddl new file mode 100644 index 000000000000..6498bb591a00 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users.ddl @@ -0,0 +1,17 @@ +CREATE TABLE GroupMgmt ( + group_id INT64, + grpname STRING(MAX), +) PRIMARY KEY(group_id); + +CREATE TABLE Users ( + user_id INT64, + name STRING(MAX), +) PRIMARY KEY(user_id); + +CREATE TABLE membership ( + user_id INT64, + group_id INT64, + enrolled TIMESTAMP NOT NULL OPTIONS ( + allow_commit_timestamp = true + ), +) PRIMARY KEY(user_id, group_id); \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users_config.json b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users_config.json new file mode 100644 index 000000000000..6cdbbedc5cc9 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/exampleconfigs/users/users_config.json @@ -0,0 +1,13 @@ +{ + "project": "xxx", + "instance": "xxx", + "database": "users", + "threads": 1, + "iterations": 1000, + "query": "INSERT INTO Users (user_id, name) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/java.header b/java-spanner-jdbc/samples/quickperf/java.header new file mode 100644 index 000000000000..d0970ba7d375 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/java.header @@ -0,0 +1,15 @@ +^/\*$ +^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)$ +^ \*$ +^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ +^ \* you may not use this file except in compliance with the License\.$ +^ \* You may obtain a copy of the License at$ +^ \*$ +^ \*[ ]+https?://www.apache.org/licenses/LICENSE-2\.0$ +^ \*$ +^ \* Unless required by applicable law or agreed to in writing, software$ +^ \* distributed under the License is distributed on an "AS IS" BASIS,$ +^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ +^ \* See the License for the specific language governing permissions and$ +^ \* limitations under the License\.$ +^ \*/$ diff --git a/java-spanner-jdbc/samples/quickperf/license-checks.xml b/java-spanner-jdbc/samples/quickperf/license-checks.xml new file mode 100644 index 000000000000..a7a61194058d --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/license-checks.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml new file mode 100644 index 000000000000..38750500e1e6 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -0,0 +1,100 @@ + + + + 4.0.0 + + com.google.cloud.jdbc.quickperf + jdbc-quickperf + 1.0.0 + jdbc-quickperf + + com.google.cloud + sdk-platform-java-config + 3.34.0 + + + + + UTF-8 + 1.8 + 1.8 + + + + + + com.google.cloud + libraries-bom + 26.43.0 + pom + import + + + + + + + net.datafaker + datafaker + 2.3.1 + + + com.google.cloud + google-cloud-spanner + + + commons-cli + commons-cli + 1.5.0 + + + com.google.cloud + google-cloud-spanner-jdbc + + + org.apache.commons + commons-lang3 + 3.13.0 + + + com.fasterxml.jackson.core + jackson-databind + 2.13.4.1 + + + + org.testcontainers + testcontainers + 1.20.1 + test + + + org.springframework.boot + spring-boot + 3.2.5 + test + + + junit + junit + 4.13.1 + test + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.google.cloud.jdbc.quickperf.QuickPerf + + + + + + \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/readme.md b/java-spanner-jdbc/samples/quickperf/readme.md new file mode 100644 index 000000000000..675155b94043 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/readme.md @@ -0,0 +1,302 @@ +# Introduction + +QuickPerf is a simple utility that uses JDBC to perform load testing on individual statements (such as queries and DML) against Spanner. It provides a rapid assessment of expected end-to-end latencies for specific statements, aiding in the performance tuning of schemas, indexes, and more. The tool includes random data generators to quickly fill a given schema with dummy data, respecting foreign-key relationships and interleaved tables. + +QuickPerf is not designed to replace comprehensive test suites like JMeter. Instead, it serves as a quick alternative for gaining performance insights or populating schemas. + +**Key Features**: +* Multi-threading to simulate concurrency +* Query parameterization with random value generators (String, Integer, Timestamp) +* Sampling of records for seeding foreign-key relationships or testing against a specific subset of data +* Batch mode support +* Automatic statement and transaction tagging + + +# Installation on Ubuntu +``` +sudo apt-get install openjdk-8-jdk +sudo apt install maven +``` + +## Authentification +It is recommended to use a service account, otherwise larger scale tests will run into quota limitations + +Set active auth to service account: +``` +gcloud auth list +gcloud config set account xxx-compute@developer.gserviceaccount.com +``` + +# Configuration + +## Parameters +``` +{ + "project": "Project ID", + "instance": "Spanner Instance", + "database": "Spanner Database", + "threads": Number of concurrent threads, + "iterations": Number of how often a statement should be executed in a thread, + "query": "Statement (e.g. query)", + "samplingQuery": "OPTIONAL - Sampling query", + "writeMetricToFile": Will write latency metrics to a file (true/false), + "batchSize": If testing batching - determines how large a batch size would be, + "queryParams": [ + {"order": 1, "value": "query paramters with value generator"} + ] +} +``` + +## Example Config +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 1, + "iterations": 10, + "query": "SELECT users.user_id, membership.enrolled, GroupMgmt.grpname FROM users, GroupMgmt, membership WHERE users.user_id = ? AND users.user_id = membership.user_id AND GroupMgmt.group_id = membership.group_id", + "samplingQuery": "SELECT user_id FROM Users TABLESAMPLE RESERVOIR (100000 ROWS)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#pi"} + ] +} +``` + +# Hello World Example + +The folder `exampleconfigs/config.json` contains a simple setup that runs SELECT 1 against the database + +Configure the right Spanner `project` and `instance` and run the app. + +**config.json** +``` +{ +"project": "xxxx", +"instance": "xxx", +"database": "xxx", +"threads": 1, +"iterations": 100, +"query": "SELECT 1", +"writeMetricToFile": false, +"batchSize": 0 +} +``` + +**Run:** +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/config.json" +``` + + + +# End-to-End Example + +Generates three tables with n:m relationships and performs a load test. + +All in one runner generating test data and executing load test: +``` +exampleconfigs/users/run.sh +``` + +What needs to be done to run it: +* Create spanner instance +* Create database named `users` +* Set `project` and `instance` in each of the config JSON files located under `exampleconfigs/users/users_config.json` + * `exampleconfigs/users/users_config.json` + * `exampleconfigs/users/groupmgt_config.json` + * `exampleconfigs/users/membership_config.json` + * `exampleconfigs/users/loadtestusers.json` + + +**Generate users table:** + +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/users_config.json" +``` + +users_config.json: +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO Users (user_id, name) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} +``` + +**Generate GroupMgmt table:** + +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/groupmgt_config.json" +``` + +groupmgt_config.json +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO GroupMgmt (group_id, grpname) VALUES(?,?)", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + {"order": 2, "value": "#s"} + ] +} +``` + +**Generate Membership table:** + +Run: +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/membership_config.json" +``` + +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "users", + "threads": 1, + "iterations": 100, + "query": "INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP())", + "writeMetricToFile": false +} +``` + + +Load test random users +``` +mvn -q exec:java -Dexec.args="-c exampleconfigs/users/loadtestusers.json" +``` + +# Randomization examples + +## String +Will generate a different random String value for each #s +``` +INSERT INTO transactions (id, name, ts) VALUES (#s, #s, CURRENT_TIMESTAMP()) +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO transactions (id, name, ts) VALUES (?, ?, CURRENT_TIMESTAMP())", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + {"order": 2, "value": "#s"} + ] +} +``` + +``` +SELECT * FROM transactions WHERE id=#s +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "SELECT * FROM transactions WHERE id=?", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + ] +} +``` + + +## Integer +Will generate a different random value for each #i +``` +UPDATE accounts SET cid=#i WHERE aaId=4 +``` + +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "UPDATE accounts SET ? WHERE aaId=4", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#i"}, + ] +} +``` + +## Integer min max +Generates #i(1,10) integer values between 1 and 10 +``` +INSERT INTO test (id, groupid, amount) VALUES (#s, #i(1,2)#, #i) +``` + +## Timestamp +Workaround for not randomizing timestamps is to use current_timestsamp() +``` +INSERT INTO transactions (id, name, ts) VALUES (#s, #s, CURRENT_TIMESTAMP())' +``` +``` +{ + "project": "xxxx", + "instance": "xxxx", + "database": "xxxx", + "threads": 4, + "iterations": 1000, + "query": "INSERT INTO transactions (id, name, ts) VALUES (?, ?, CURRENT_TIMESTAMP())'", + "writeMetricToFile": false, + "queryParams": [ + {"order": 1, "value": "#s"}, + {"order": 1, "value": "#s"} + ] +} +``` + +## Sampling IDs +Sometimes it might be required to sample existing IDs that are then used in the query that is executed. +The parameter ```-s``` allows to pull a sampled dataset, but only one column is allowed in the resultset. +This query is executed only once and before the beginning of the run and the dataset is reused across the threads. + +* #ps will add quotes - such as for Strings +* #pi will **not** add quotes such as when integers are used + +In this case the #ps is the placeholder for samples that are pulled from the -s parameter +``` +-q 'SELECT * FROM test WHERE id = #ps'' +-s 'SELECT id FROM test TABLESAMPLE RESERVOIR (100 ROWS)' +``` + +## Many-to-Many Relationship Example +Insert Users +``` +INSERT INTO Users (user_id, name) VALUES(#i,#s) +``` + +Insert Groups +``` +INSERT INTO GroupMgmt (group_id, grpname) VALUES(#i,#s) +``` + +Insert relationships with sampling: +``` +INSERT INTO membership(user_id, group_id, enrolled) VALUES((SELECT user_id FROM Users TABLESAMPLE RESERVOIR (1 ROWS)), (SELECT group_id FROM GroupMgmt TABLESAMPLE RESERVOIR (1 ROWS)), CURRENT_TIMESTAMP()) +``` \ No newline at end of file diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java new file mode 100644 index 000000000000..90b241b1dd5f --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/ProgressTracker.java @@ -0,0 +1,79 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import java.util.List; + +public class ProgressTracker extends Thread { + private static final int SLEEP_TIME_INIT = 2000; + private static final int SLEEP_TIME_POLL = 200; + + private final List threadList; + + private final int maxIt; + private int currentIt = 0; + + public ProgressTracker(List threadList, int maxIt) { + this.threadList = threadList; + this.maxIt = maxIt; + } + + public void run() { + sleep(SLEEP_TIME_INIT); + while (currentIt < maxIt) { + currentIt = 0; + for (QuickPerfRunner thread : threadList) { + currentIt = currentIt + thread.getProgress(); + + int percent = (int) Math.ceil(((double) currentIt / maxIt) * 100.0); + print_progress(percent); + } + + if (sleep(SLEEP_TIME_POLL)) { + break; + } + } + print_progress(100); + } + + public void print_progress(int percent) { + StringBuilder bar = new StringBuilder("Progress: ["); + + for (int i = 0; i < 50; i++) { + if (i < (percent / 2)) { + bar.append("="); + } else if (i == (percent / 2)) { + bar.append(">"); + } else { + bar.append(" "); + } + } + + bar.append("] ").append(percent).append("% "); + System.out.print("\r" + bar); + } + + private boolean sleep(int sleeptime) { + try { + Thread.sleep(sleeptime); + } catch (InterruptedException e) { + System.err.println("Progress tracker thread interrupted"); + return true; + } + return false; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java new file mode 100644 index 000000000000..9eb0fc45cf2d --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerf.java @@ -0,0 +1,191 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import com.google.cloud.jdbc.quickperf.config.Config; +import com.google.cloud.jdbc.quickperf.config.ConfigParser; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.lang3.ArrayUtils; + +public class QuickPerf extends Thread { + + private static final String BREAK_STR = + "###################################################################################################"; + + // TODO: make measurement file configurable + private static final String MEASURES_FILE_NAME = "measures.txt"; + + public static void main(String[] args) throws Exception { + Options options = new Options(); + + options.addOption(QuickPerf.addOption("c", "config", true, "Config File")); + + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + CommandLine cmd = null; + + ZonedDateTime testStartTimestamp = ZonedDateTime.now(); + + try { + cmd = parser.parse(options, args); + } catch (ParseException e) { + System.out.println(e.getMessage()); + formatter.printHelp("utility-name", options); + + System.exit(1); + } + + Config config = ConfigParser.parseConfigFile(cmd.getOptionValue("config")); + + float[] measures = new float[config.getIterations() * config.getThreads()]; + + // initialize threads (for sampling if present) + List threadList = new ArrayList(); + for (int i = 0; i < config.getThreads(); i++) { + QuickPerfRunner thread = new QuickPerfRunner(config); + if (config.getSamplingQuery() != null) { + thread.runSampling(); + } + threadList.add(thread); + } + + // start threads + for (QuickPerfRunner thread : threadList) { + thread.start(); + } + + // ProgressBar Tracker Thread + ProgressTracker progressTracker = + progressTracker = + new ProgressTracker(threadList, config.getIterations() * config.getThreads()); + + progressTracker.start(); + progressTracker.join(); + + int i = 0; + for (QuickPerfRunner thread : threadList) { + thread.join(); + + if (i == 0) { + measures = thread.getMeasures(); + } else { + measures = ArrayUtils.addAll(measures, thread.getMeasures()); + } + i++; + } + + // write to file before its sorted + if (config.getWriteMetricToFile()) { + try { + writeMeasuresToFile(measures, MEASURES_FILE_NAME); + } catch (IOException e) { + System.err.println("An error occurred while writing the file: " + e.getMessage()); + } + } + + System.out.println("\n" + BREAK_STR); + System.out.println("Query: " + config.getQuery()); + System.out.println("Params: " + config.paramsToString()); + System.out.println("Tag: " + Config.DEFAULT_TAG); + if (config.getBatchSize() > 0) { + System.out.println("Batching Enabled (size): " + config.getBatchSize()); + } + System.out.printf("Start: %s End: %s%n", testStartTimestamp, ZonedDateTime.now()); + System.out.printf( + "Finished with a total of %s runs across %s Threads.\nLatencies (ms): p50 = %s, p95 = %s, p99 = %s, min = %s, max = %s%n", + config.getIterations() * config.getThreads(), + config.getThreads(), + calcPerc(measures, 50), + calcPerc(measures, 95), + calcPerc(measures, 99), + getMin(measures), + getMax(measures)); + System.out.println(BREAK_STR); + } + + public static Option addOption(String option, String longOption, boolean hasArgs, String desc) { + Option opt = new Option(option, longOption, hasArgs, desc); + opt.setRequired(true); + + return opt; + } + + public static Option addOption( + String option, String longOption, boolean hasArgs, String desc, boolean required) { + Option opt = new Option(option, longOption, hasArgs, desc); + opt.setRequired(required); + + return opt; + } + + public static float calcPerc(float[] nums, double percentile) { + int n = nums.length; + Arrays.sort(nums); + + double index = (percentile / 100) * (n - 1); + + if (index == Math.floor(index)) { + return nums[(int) index]; + } else { + int lowerIndex = (int) Math.floor(index); + int upperIndex = (int) Math.ceil(index); + float lowerValue = nums[lowerIndex]; + float upperValue = nums[upperIndex]; + return (float) ((1 - (index - lowerIndex)) * lowerValue + (index - lowerIndex) * upperValue); + } + } + + public static float getMax(float[] measures) { + if (measures == null || measures.length == 0) { + throw new IllegalArgumentException("Array is null or empty"); + } + + Arrays.sort(measures); + return measures[measures.length - 1]; + } + + public static float getMin(float[] measures) { + if (measures == null || measures.length == 0) { + throw new IllegalArgumentException("Array is null or empty"); + } + + Arrays.sort(measures); + return measures[0]; + } + + public static void writeMeasuresToFile(float[] array, String fileName) throws IOException { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { + for (float value : array) { + writer.write(Float.toString(value)); + writer.newLine(); + } + } + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java new file mode 100644 index 000000000000..84e2bc9ac812 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java @@ -0,0 +1,320 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.jdbc.quickperf; + +import com.google.cloud.jdbc.quickperf.config.Config; +import com.google.cloud.jdbc.quickperf.config.QueryParam; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import java.security.SecureRandom; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import net.datafaker.Faker; + +public class QuickPerfRunner extends Thread { + private static final Properties DEFAULT_PROPERTIES = new Properties(); + + // perf measurement + private float[] measures; + + private final List sampledValueList = new ArrayList(); + private final Config config; + + private int progress; + + public QuickPerfRunner(Config config) { + this.config = config; + } + + public void runSampling() { + System.out.println("Running Sampling... "); + + try (Connection connection = createConnection(config)) { + try (Statement statement = connection.createStatement()) { + boolean hasResults = statement.execute(config.getSamplingQuery()); + + if (!hasResults) { + System.out.println("Nothing sampled"); + return; + } + + ResultSet rs = statement.getResultSet(); + while (rs.next()) { + String value = rs.getString(1); + sampledValueList.add(value); + } + + System.out.printf("Finished sampling %s records%n", sampledValueList.size()); + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + + private Connection createConnection(Config config) throws SQLException { + String connectionUrl = createConnectionURL(config); + Properties properties = createConnectionProperties(); + return DriverManager.getConnection(connectionUrl, properties); + } + + private String createConnectionURL(Config config) { + if (config.isIsEmulator()) { + return String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?autoConfigEmulator=true", + config.getProject(), config.getInstance(), config.getDatabase()); + } else { + return String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + config.getProject(), config.getInstance(), config.getDatabase()); + } + } + + private Properties createConnectionProperties() { + if (System.getProperty("spanner.host") != null) { + Properties properties = new Properties(); + properties.setProperty("endpoint", System.getProperty("spanner.host")); + return properties; + } + return DEFAULT_PROPERTIES; + } + + public void run() { + if (config.getBatchSize() > 0) { + int val = (int) Math.ceil((double) config.getIterations() / config.getBatchSize()); + measures = new float[val]; + } else { + measures = new float[config.getIterations()]; + } + + try (Connection connection = createConnection(config)) { + + // determine database dialect to set right tagging syntax + boolean isGoogleSQL = + connection + .unwrap(CloudSpannerJdbcConnection.class) + .getDialect() + .equals(Dialect.GOOGLE_STANDARD_SQL); + String tagPrefix = isGoogleSQL ? "" : "SPANNER."; + + connection.setAutoCommit(false); + + // if there is DML switch to r/w transaction mode and apply transaction tagging. + // Otherwise set to read-only mode. + if (config.getQuery().contains("INSERT") + || config.getQuery().contains("UPDATE") + || config.getQuery().contains("DELETE")) { + // read-write + connection.createStatement().execute("SET TRANSACTION READ WRITE"); + connection + .createStatement() + .execute(String.format("SET %sTRANSACTION_TAG = '%s'", tagPrefix, config.DEFAULT_TAG)); + + } else { + // read-only + // connection.createStatement().execute("SET TRANSACTION READ ONLY"); + connection.setAutoCommit(true); + } + + PreparedStatement statement = connection.prepareStatement(config.getQuery()); + int batchCounter = config.getBatchSize(); + int batchRound = 0; + + for (int i = 0; i < config.getIterations(); i++) { + if (config.getBatchSize() == 0) { + // single statements + try { + if (config.getQueryParams() != null) { + parametrizeStatement(statement, config.getQueryParams()); + } + connection + .createStatement() + .execute(String.format("SET %sSTATEMENT_TAG='%s'", tagPrefix, config.DEFAULT_TAG)); + + long start = System.nanoTime(); + boolean hasResults = statement.execute(); + if (!connection.getAutoCommit()) { + connection.commit(); + } + long stop = System.nanoTime() - start; + + if (hasResults) { + statement.getResultSet().close(); + } + + measures[i] = (float) stop / 1000000; + progress++; + } catch (Exception e) { + if (e.getMessage().contains("ALREADY_EXISTS:")) { + System.out.println("duplicate key - retry"); + i--; + } else { + throw e; + } + } + } else if (config.getQuery().contains("INSERT") + || config.getQuery().contains("UPDATE") + || config.getQuery().contains("DELETE")) { + // batching + try { + if (config.getQueryParams() != null) { + parametrizeStatement(statement, config.getQueryParams()); + } + + statement.addBatch(); + + if (batchCounter == 0 || i == config.getIterations() - 1) { + connection + .createStatement() + .execute( + String.format("SET %sSTATEMENT_TAG='%s'", tagPrefix, config.DEFAULT_TAG)); + + long start = System.nanoTime(); + statement.executeBatch(); + if (!connection.getAutoCommit()) { + connection.commit(); + } + long stop = System.nanoTime() - start; + + batchCounter = config.getBatchSize(); + + measures[batchRound] = (float) stop / 1000000; + batchRound++; + } + + progress++; + batchCounter--; + } catch (Exception e) { + if (e.getMessage().contains("ALREADY_EXISTS:")) { + System.out.println("duplicate key - retry"); + i--; + } else { + throw e; + } + } + } else { + System.out.println( + "Batching is only allowed for DML. Set batchSize=0 to disable batching."); + System.exit(1); + } + } + } catch (SQLException e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + + public static float[] appendFloatArray(float[] originalArray, float[] elementsToAppend) { + int originalLength = originalArray.length; + int elementsLength = elementsToAppend.length; + + float[] resultArray = new float[originalLength + elementsLength]; + System.arraycopy(originalArray, 0, resultArray, 0, originalLength); + System.arraycopy(elementsToAppend, 0, resultArray, originalLength, elementsLength); + + return resultArray; + } + + private void parametrizeStatement(PreparedStatement statement, List paramList) + throws SQLException { + for (QueryParam param : paramList) { + if (param.getValue().contains("#i")) { + // integer plus integer with custom range + int value = replaceInt(param.getValue()); + statement.setInt(param.getOrder(), value); + } else if (param.getValue().contains("#d")) { + // double + Double value = replaceDouble(param.getValue()); + statement.setDouble(param.getOrder(), value); + } else if (param.getValue().contains("#s")) { + // String + String value = replaceString(param.getValue()); + statement.setString(param.getOrder(), value); + } else if (param.getValue().contains("#ps")) { + // Sampled Query - String + String value = replaceSampleQueryString(param.getValue()); + statement.setString(param.getOrder(), value); + } else if (param.getValue().contains("#pi")) { + // Sampled Query - Integer + Long value = replaceSampleQueryInt(param.getValue()); + statement.setLong(param.getOrder(), value); + } + } + } + + private int replaceInt(String value) { + Faker f = new Faker(); + // integer with min, max + String pattern = "#i\\((\\d+),(\\d+)\\)#"; + Pattern regexPattern = Pattern.compile(pattern); + Matcher matcher = regexPattern.matcher(value); + + if (matcher.find()) { + int min = Integer.parseInt(matcher.group(1)); + int max = Integer.parseInt(matcher.group(2)); + + return f.number().numberBetween(min, max); + } + + return Integer.parseInt( + value.replaceFirst("#i", String.valueOf(new SecureRandom().nextInt(Integer.MAX_VALUE)))); + } + + private Double replaceDouble(String value) { + Faker f = new Faker(); + + return Double.valueOf( + value.replaceFirst("#d", String.valueOf(f.number().randomDouble(2, 0, 999999999)))); + } + + private String replaceString(String value) { + return value.replaceFirst("#s", UUID.randomUUID().toString()); + } + + private String replaceSampleQueryString(String value) { + int randomIndex = new Random().nextInt(sampledValueList.size()); + return value.replaceFirst("#ps", sampledValueList.get(randomIndex)); + } + + private Long replaceSampleQueryInt(String value) { + int randomIndex = new Random().nextInt(sampledValueList.size()); + + return Long.parseLong(value.replaceFirst("#pi", sampledValueList.get(randomIndex))); + } + + public int getProgress() { + return progress; + } + + public float[] getMeasures() { + return measures; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java new file mode 100644 index 000000000000..b869be386e46 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/Config.java @@ -0,0 +1,145 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +import java.util.List; +import java.util.Random; + +public class Config { + public static String DEFAULT_TAG = "perftest_" + (new Random()).nextInt(300); + + private String project; + private String instance; + private String database; + private int threads; + private int iterations; + private String query; + private String samplingQuery; + private boolean writeMetricToFile; + private int batchSize; + private boolean isEmulator; + private List queryParams; + + public String paramsToString() { + StringBuilder retVal = new StringBuilder(); + + if (queryParams != null) { + + for (QueryParam param : queryParams) { + retVal.append(String.format("%s:%s ", param.getOrder(), param.getValue())); + } + } + + return retVal.toString(); + } + + public int getBatchSize() { + return this.batchSize; + } + + public void setBatchSize(int batchSize) { + this.batchSize = batchSize; + } + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public int getThreads() { + return threads; + } + + public void setThreads(int threads) { + this.threads = threads; + } + + public int getIterations() { + return iterations; + } + + public void setIterations(int iterations) { + this.iterations = iterations; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public boolean isWriteMetricToFile() { + return writeMetricToFile; + } + + public void setWriteMetricToFile(boolean writeMetricToFile) { + this.writeMetricToFile = writeMetricToFile; + } + + public List getQueryParams() { + return queryParams; + } + + public void setQueryParams(List queryParams) { + this.queryParams = queryParams; + } + + public String getSamplingQuery() { + return this.samplingQuery; + } + + public void setSamplingQuery(String samplingQuery) { + this.samplingQuery = samplingQuery; + } + + public boolean getWriteMetricToFile() { + return this.writeMetricToFile; + } + + public boolean isIsEmulator() { + return this.isEmulator; + } + + public boolean getIsEmulator() { + return this.isEmulator; + } + + public void setIsEmulator(boolean isEmulator) { + this.isEmulator = isEmulator; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java new file mode 100644 index 000000000000..8f056d114cb5 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/ConfigParser.java @@ -0,0 +1,30 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; + +public class ConfigParser { + + public static Config parseConfigFile(String configFile) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + return mapper.readValue(new File(configFile), Config.class); + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java new file mode 100644 index 000000000000..52807eb499d1 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/config/QueryParam.java @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf.config; + +public class QueryParam { + private int order; + private String value; + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java new file mode 100644 index 000000000000..c147ebaa9b87 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/AppTest.java @@ -0,0 +1,174 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.jdbc.quickperf; + +import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.cloud.spanner.connection.SpannerPool; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import javax.annotation.Nonnull; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +public class AppTest { + + private static final String TEST_FILE = "src/test/resources/testfile.json"; + + private static GenericContainer emulator; + + private static final String projectId = "test"; + private static final String instanceId = "test"; + private static final String databaseId = "quickperftest"; + + @BeforeClass + public static void setup() throws Exception { + System.out.println("Starting Emulator"); + emulator = + new GenericContainer<>( + DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) + .withExposedPorts(9010) + .waitingFor(Wait.forListeningPort()); + + emulator.start(); + System.out.println("Finished starting Emulator"); + + List ddlList = + Arrays.asList( + "CREATE TABLE GroupMgmt (" + + "group_id INT64," + + "grpname STRING(MAX)," + + ") PRIMARY KEY(group_id)", + "CREATE TABLE Users (" + + "user_id INT64," + + "name STRING(MAX)," + + ") PRIMARY KEY(user_id)", + "CREATE TABLE membership (" + + "user_id INT64," + + "group_id INT64," + + "enrolled TIMESTAMP NOT NULL OPTIONS (" + + " allow_commit_timestamp = true" + + ")," + + ") PRIMARY KEY(user_id, group_id)"); + try (Connection connection = createConnection(); + Statement statement = connection.createStatement()) { + for (String ddl : ddlList) { + statement.addBatch(ddl); + } + statement.executeBatch(); + } + // create test file + ProjectConfig projectConfig = createProjectConfig(); + + // Write the JSON to a file + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + File file = new File(TEST_FILE); + mapper.writeValue(file, projectConfig); + } + + @Nonnull + private static ProjectConfig createProjectConfig() { + ProjectConfig projectConfig = new ProjectConfig(); + projectConfig.setProject(projectId); + projectConfig.setInstance(instanceId); + projectConfig.setDatabase(databaseId); + projectConfig.setThreads(1); + projectConfig.setIterations(1000); + projectConfig.setQuery("INSERT INTO Users (user_id, name) VALUES(?,?)"); + projectConfig.setWriteMetricToFile(false); + projectConfig.setIsEmulator(true); + + QueryParam param1 = new QueryParam(1, "#i"); + QueryParam param2 = new QueryParam(2, "#s"); + projectConfig.setQueryParams(Arrays.asList(param1, param2)); + return projectConfig; + } + + @AfterClass + public static void cleanup() throws IOException { + // Close all Spanner connections. + SpannerPool.closeSpannerPool(); + + // Write an empty test file + Path path = Paths.get(TEST_FILE); + Files.newBufferedWriter(path, TRUNCATE_EXISTING).close(); + + // Stop the emulator. + emulator.stop(); + } + + private static Connection createConnection() throws SQLException { + String url = + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?autoConfigEmulator=true", + projectId, instanceId, databaseId); + Properties properties = new Properties(); + properties.put("endpoint", "localhost:" + emulator.getMappedPort(9010)); + return DriverManager.getConnection(url, properties); + } + + @Test + public void testRunApplication() throws Exception { + + System.setProperty("spanner.emulator", "true"); + System.setProperty("spanner.host", "localhost:" + emulator.getMappedPort(9010)); + SpringApplication.run(AppTest.class).close(); + + String[] userConfig = {"-c" + TEST_FILE}; + QuickPerf.main(userConfig); + + try (Connection connection = createConnection()) { + testQuery(connection, "SELECT count(*) FROM Users", 1000); + } + } + + private void testQuery(Connection connection, String query, int expected) throws SQLException { + try (Statement statement = connection.createStatement()) { + boolean hasResults = statement.execute(query); + assertTrue(hasResults); + + ResultSet rs = statement.getResultSet(); + while (rs.next()) { + int value = rs.getInt(1); + assertEquals(expected, value); + } + } + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java new file mode 100644 index 000000000000..372d100fd330 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/ProjectConfig.java @@ -0,0 +1,113 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +import java.util.List; + +public class ProjectConfig { + private String project; + private String instance; + private String database; + private int threads; + private int iterations; + private String query; + private boolean writeMetricToFile; + private boolean isEmulator; + private List queryParams; + + // Getters and setters + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public int getThreads() { + return threads; + } + + public void setThreads(int threads) { + this.threads = threads; + } + + public int getIterations() { + return iterations; + } + + public void setIterations(int iterations) { + this.iterations = iterations; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public boolean isWriteMetricToFile() { + return writeMetricToFile; + } + + public void setWriteMetricToFile(boolean writeMetricToFile) { + this.writeMetricToFile = writeMetricToFile; + } + + public List getQueryParams() { + return queryParams; + } + + public void setQueryParams(List queryParams) { + this.queryParams = queryParams; + } + + public boolean getWriteMetricToFile() { + return this.writeMetricToFile; + } + + public boolean isIsEmulator() { + return this.isEmulator; + } + + public boolean getIsEmulator() { + return this.isEmulator; + } + + public void setIsEmulator(boolean isEmulator) { + this.isEmulator = isEmulator; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java new file mode 100644 index 000000000000..dcc0d85d4e38 --- /dev/null +++ b/java-spanner-jdbc/samples/quickperf/src/test/java/com/google/cloud/jdbc/quickperf/QueryParam.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.jdbc.quickperf; + +public class QueryParam { + private int order; + private String value; + + public QueryParam(int order, String value) { + this.order = order; + this.value = value; + } + + // Getters and setters + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/java-spanner-jdbc/samples/quickperf/src/test/resources/testfile.json b/java-spanner-jdbc/samples/quickperf/src/test/resources/testfile.json new file mode 100644 index 000000000000..e69de29bb2d1 From 0da6058d568b74a40d4d7bdf36eeb44d421cbd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 14:51:00 +0200 Subject: [PATCH 1374/1979] test: add a test for using the single-jar-with-dependencies (#1692) * test: add a test for using the single-jar-with-dependencies The single-jar-with-dependencies is prone to dependency issues, due to the fact that the build can only place one version of each file in the jar, if multiple dependencies define the same file. This change adds a test for using the single-jar with a very simple test application. Updates #1687 * fix: make the test work on the emulator * fix: only add slashes if host is actually set * test: add test for shaded jar --- java-spanner-jdbc/pom.xml | 26 ++++ .../jdbc/SingleJarTestApplication.java | 55 ++++++++ .../spanner/jdbc/it/ITSingleJarTest.java | 126 ++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97c020916da1..fc46b2952be1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -426,6 +426,32 @@ + + + alt_build_dir + + + alt.build.dir + + + + ${alt.build.dir} + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + + ${alt.build.dir}/single.jar + + + + + + + diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java new file mode 100644 index 000000000000..e9cfba1b219e --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java @@ -0,0 +1,55 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; + +/** + * Simple Java application that is used to verify the working of the single-jar-with-dependencies. + */ +public class SingleJarTestApplication { + + public static void main(String[] args) throws Exception { + if (args.length != 3) { + throw new IllegalArgumentException("expected 3 arguments"); + } + String project = args[0]; + String instance = args[1]; + String database = args[2]; + String extraOptions = ""; + String host = ""; + if (System.getenv("SPANNER_EMULATOR_HOST") != null) { + extraOptions = "?autoConfigEmulator=true"; + host = "//" + System.getenv("SPANNER_EMULATOR_HOST"); + } + + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:%s/projects/%s/instances/%s/databases/%s%s", + host, project, instance, database, extraOptions))) { + try (ResultSet resultSet = + connection.createStatement().executeQuery("select 'Hello World from Real Spanner!'")) { + while (resultSet.next()) { + System.out.println(resultSet.getString(1)); + } + } + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java new file mode 100644 index 000000000000..9ae8f60032b6 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITSingleJarTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.common.collect.ImmutableList; +import com.google.common.io.CharStreams; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Paths; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests that the following works: + * + *
      + *
    1. Build a single-jar-with-dependencies + *
    2. Compile a simple Java application consisting of a single file and no dependencies to a + * class file + *
    3. Run the simple Java application with only itself + the single-jar-with-dependencies on the + * class path + *
    + */ +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITSingleJarTest extends ITAbstractJdbcTest { + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private Database database; + + @Before + public void setup() { + database = + env.getOrCreateDatabase( + getDialect(), + ImmutableList.of("create table test (id int64, value string(max)) primary key (id)")); + } + + @Test + public void testUseSingleJar() throws Exception { + buildSingleJar(); + buildMainClass(); + runTestApplication(); + } + + @Test + public void testUseShadedJar() throws Exception { + buildShadedJar(); + buildMainClass(); + runTestApplication(); + } + + private void runTestApplication() throws Exception { + DatabaseId id = database.getId(); + ProcessBuilder builder = new ProcessBuilder(); + if (System.getenv("SPANNER_EMULATOR_HOST") != null) { + builder.environment().put("SPANNER_EMULATOR_HOST", System.getenv("SPANNER_EMULATOR_HOST")); + } + // This runs the simple test application with only the shaded jar on the classpath. + builder.command( + "java", + "-cp", + "./target/single/test/:target/single/single.jar", + "com/google/cloud/spanner/jdbc/SingleJarTestApplication", + id.getInstanceId().getProject(), + id.getInstanceId().getInstance(), + id.getDatabase()); + execute(builder); + } + + private void buildSingleJar() throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + builder.command("mvn", "clean", "package", "-DskipTests", "-Dalt.build.dir=./target/single"); + execute(builder); + } + + private void buildShadedJar() throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + builder.command( + "mvn", "clean", "-Pshade", "package", "-DskipTests", "-Dalt.build.dir=./target/single"); + execute(builder); + } + + private void buildMainClass() throws Exception { + Files.createDirectories(Paths.get("target", "single", "test")); + ProcessBuilder builder = new ProcessBuilder(); + builder.command( + "javac", + "src/test/java/com/google/cloud/spanner/jdbc/SingleJarTestApplication.java", + "-d", + "./target/single/test"); + execute(builder); + } + + private void execute(ProcessBuilder builder) throws Exception { + Process process = builder.start(); + String errors; + try (InputStreamReader reader = new InputStreamReader(process.getErrorStream())) { + errors = CharStreams.toString(reader); + } + assertEquals(errors, 0, process.waitFor()); + } +} From 7146a3bb0b32efa25de4d3ab42afdeb460dc9138 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:08:23 +0200 Subject: [PATCH 1375/1979] test(deps): update dependency junit:junit to v4.13.2 (#1711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [junit:junit](http://junit.org) ([source](https://togithub.com/junit-team/junit4)) | `4.13.1` -> `4.13.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/junit:junit/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/junit:junit/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/junit:junit/4.13.1/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/junit:junit/4.13.1/4.13.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 38750500e1e6..2ceca71a7b8c 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ junit junit - 4.13.1 + 4.13.2 test From 6a85879f348b04ee27dde248822baea1337090d3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:10:23 +0200 Subject: [PATCH 1376/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.13.4.2 [security] (#1710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) ([source](https://togithub.com/FasterXML/jackson-databind)) | `2.13.4.1` -> `2.13.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.1/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.1/2.13.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | ### GitHub Vulnerability Alerts #### [CVE-2022-42003](https://nvd.nist.gov/vuln/detail/CVE-2022-42003) In FasterXML jackson-databind 2.4.0-rc1 until 2.12.7.1 and in 2.13.x before 2.13.4.2 resource exhaustion can occur because of a lack of a check in primitive value deserializers to avoid deep wrapper array nesting, when the UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled. This was patched in 2.12.7.1, 2.13.4.2, and 2.14.0. Commits that introduced vulnerable code are https://togithub.com/FasterXML/jackson-databind/commit/d499f2e7bbc5ebd63af11e1f5cf1989fa323aa45, https://togithub.com/FasterXML/jackson-databind/commit/0e37a39502439ecbaa1a5b5188387c01bf7f7fa1, and https://togithub.com/FasterXML/jackson-databind/commit/7ba9ac5b87a9d6ac0d2815158ecbeb315ad4dcdc. Fix commits are https://togithub.com/FasterXML/jackson-databind/commit/cd090979b7ea78c75e4de8a4aed04f7e9fa8deea and https://togithub.com/FasterXML/jackson-databind/commit/d78d00ee7b5245b93103fef3187f70543d67ca33. --- ### Configuration 📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2ceca71a7b8c..031f4f26b8fb 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -61,7 +61,7 @@ com.fasterxml.jackson.core jackson-databind - 2.13.4.1 + 2.13.4.2 From f544dc77cca0ff4ac7c2867d9283629668dd7c56 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:28:24 +0200 Subject: [PATCH 1377/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.4.1 (#1712) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.codehaus.mojo:exec-maven-plugin](https://www.mojohaus.org/exec-maven-plugin) ([source](https://togithub.com/mojohaus/exec-maven-plugin)) | `3.1.0` -> `3.4.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.codehaus.mojo:exec-maven-plugin/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.codehaus.mojo:exec-maven-plugin/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.codehaus.mojo:exec-maven-plugin/3.1.0/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.codehaus.mojo:exec-maven-plugin/3.1.0/3.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mojohaus/exec-maven-plugin (org.codehaus.mojo:exec-maven-plugin) ### [`v3.4.1`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.4.1) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.4.0...3.4.1) #### 🐛 Bug Fixes - Environment variable Path should be used as case-insensitive ([#​442](https://togithub.com/mojohaus/exec-maven-plugin/pull/442)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - fix: NPE because declared MavenSession field hides field of superclass ([#​439](https://togithub.com/mojohaus/exec-maven-plugin/pull/439)) [@​sebthom](https://togithub.com/sebthom) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 84 to 85 ([#​441](https://togithub.com/mojohaus/exec-maven-plugin/pull/441)) [@​dependabot](https://togithub.com/dependabot) #### 👻 Maintenance - Remove redundant spotless configuration ([#​440](https://togithub.com/mojohaus/exec-maven-plugin/pull/440)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) #### 🔧 Build - Use Maven4 enabled with GH Action ([#​443](https://togithub.com/mojohaus/exec-maven-plugin/pull/443)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use shared release drafter GH Action ([#​444](https://togithub.com/mojohaus/exec-maven-plugin/pull/444)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ### [`v3.4.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.4.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.3.0...3.4.0) #### 🚀 New features and improvements - Allow `` to be specified for the exec:exec goal ([#​432](https://togithub.com/mojohaus/exec-maven-plugin/pull/432)) [@​sebthom](https://togithub.com/sebthom) #### 🐛 Bug Fixes - Do not get UPPERCASE env vars ([#​427](https://togithub.com/mojohaus/exec-maven-plugin/pull/427)) [@​wheezil](https://togithub.com/wheezil) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 82 to 84 ([#​434](https://togithub.com/mojohaus/exec-maven-plugin/pull/434)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-xml from 3.0.0 to 3.0.1 ([#​431](https://togithub.com/mojohaus/exec-maven-plugin/pull/431)) [@​dependabot](https://togithub.com/dependabot) #### 👻 Maintenance - Remove Log4j 1.2.x from ITs ([#​437](https://togithub.com/mojohaus/exec-maven-plugin/pull/437)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) #### 🔧 Build - Use Maven 3.9.7 and 4.0.0-beta-3 ([#​433](https://togithub.com/mojohaus/exec-maven-plugin/pull/433)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ### [`v3.3.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.3.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.2.0...3.3.0) #### 🚀 New features and improvements - Add option to include runtime and provided ([#​61](https://togithub.com/mojohaus/exec-maven-plugin/pull/61)) [@​rehevkor5](https://togithub.com/rehevkor5) #### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 80 to 82 ([#​429](https://togithub.com/mojohaus/exec-maven-plugin/pull/429)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 4.0.0 to 4.0.1 ([#​424](https://togithub.com/mojohaus/exec-maven-plugin/pull/424)) [@​dependabot](https://togithub.com/dependabot) - Bump asm.version from 9.6 to 9.7 ([#​422](https://togithub.com/mojohaus/exec-maven-plugin/pull/422)) [@​dependabot](https://togithub.com/dependabot) - Bump apache/maven-gh-actions-shared from 3 to 4 ([#​420](https://togithub.com/mojohaus/exec-maven-plugin/pull/420)) [@​dependabot](https://togithub.com/dependabot) ### [`v3.2.0`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.2.0) [Compare Source](https://togithub.com/mojohaus/exec-maven-plugin/compare/3.1.1...3.2.0) ##### 🚀 New features and improvements - Enable to exec:java runnables and not only mains with loosely coupled injections ([#​408](https://togithub.com/mojohaus/exec-maven-plugin/pull/408)) [@​rmannibucau](https://togithub.com/rmannibucau) - Try to get rid of legacy API which can break starting with java 17 ([#​409](https://togithub.com/mojohaus/exec-maven-plugin/pull/409)) [@​rmannibucau](https://togithub.com/rmannibucau) ##### 🐛 Bug Fixes - Fix [#​401](https://togithub.com/mojohaus/exec-maven-plugin/issues/401) - Maven v4 compatibility ([#​414](https://togithub.com/mojohaus/exec-maven-plugin/pull/414)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 78 to 80 ([#​419](https://togithub.com/mojohaus/exec-maven-plugin/pull/419)) [@​dependabot](https://togithub.com/dependabot) - Bump commons-io:commons-io from 1.1 to 2.7 in /src/it/projects/setup-parent ([#​416](https://togithub.com/mojohaus/exec-maven-plugin/pull/416)) [@​dependabot](https://togithub.com/dependabot) - Bump org.apache.commons:commons-exec from 1.3 to 1.4.0 ([#​405](https://togithub.com/mojohaus/exec-maven-plugin/pull/405)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.mojo:mojo-parent from 77 to 78 ([#​406](https://togithub.com/mojohaus/exec-maven-plugin/pull/406)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-component-metadata from 2.1.1 to 2.2.0 ([#​403](https://togithub.com/mojohaus/exec-maven-plugin/pull/403)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-component-annotations from 2.1.1 to 2.2.0 ([#​404](https://togithub.com/mojohaus/exec-maven-plugin/pull/404)) [@​dependabot](https://togithub.com/dependabot) ##### 👻 Maintenance - ITs improvement ([#​415](https://togithub.com/mojohaus/exec-maven-plugin/pull/415)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Fix documentation formatting, add menu items for new examples ([#​412](https://togithub.com/mojohaus/exec-maven-plugin/pull/412)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Execute mexec-137 also on unix family ([#​413](https://togithub.com/mojohaus/exec-maven-plugin/pull/413)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Remove unused test ([#​410](https://togithub.com/mojohaus/exec-maven-plugin/pull/410)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 🔧 Build - Bump release-drafter/release-drafter from 5 to 6 ([#​417](https://togithub.com/mojohaus/exec-maven-plugin/pull/417)) [@​dependabot](https://togithub.com/dependabot) ### [`v3.1.1`](https://togithub.com/mojohaus/exec-maven-plugin/releases/tag/3.1.1) ##### 🚀 New features and improvements - Remove unused killAfter options ([#​394](https://togithub.com/mojohaus/exec-maven-plugin/pull/394)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - \[[#​391](https://togithub.com/mojohaus/exec-maven-plugin/issues/391)] Cope with Thread::stop being unavailable in JDK 20+ ([#​393](https://togithub.com/mojohaus/exec-maven-plugin/pull/393)) [@​kriegaex](https://togithub.com/kriegaex) - Only prefix program output with thread name when running with multiple threads ([#​157](https://togithub.com/mojohaus/exec-maven-plugin/pull/157)) [@​hankolerd](https://togithub.com/hankolerd) - \[[#​389](https://togithub.com/mojohaus/exec-maven-plugin/issues/389)] Add option 'blockSystemExit' to 'java' mojo ([#​390](https://togithub.com/mojohaus/exec-maven-plugin/pull/390)) [@​kriegaex](https://togithub.com/kriegaex) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - Ensure maven.properties can be forwarded to system properties for exec:java ([#​346](https://togithub.com/mojohaus/exec-maven-plugin/pull/346)) [@​rmannibucau](https://togithub.com/rmannibucau) ##### 🐛 Bug Fixes - Fix [#​158](https://togithub.com/mojohaus/exec-maven-plugin/issues/158) - Fix non ascii character handling ([#​372](https://togithub.com/mojohaus/exec-maven-plugin/pull/372)) [@​jebeaudet](https://togithub.com/jebeaudet) - \[[#​323](https://togithub.com/mojohaus/exec-maven-plugin/issues/323)] exec arguments missing ([#​324](https://togithub.com/mojohaus/exec-maven-plugin/pull/324)) [@​bmarwell](https://togithub.com/bmarwell) ##### 📦 Dependency updates - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-module+mainclass ([#​382](https://togithub.com/mojohaus/exec-maven-plugin/pull/382)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-mainclass ([#​380](https://togithub.com/mojohaus/exec-maven-plugin/pull/380)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/java_module-export ([#​379](https://togithub.com/mojohaus/exec-maven-plugin/pull/379)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/longModulepath with spaces ([#​383](https://togithub.com/mojohaus/exec-maven-plugin/pull/383)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/projects/jigsaw ([#​381](https://togithub.com/mojohaus/exec-maven-plugin/pull/381)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.plexus:plexus-utils from 3.0.16 to 3.0.24 in /src/it/mrm/java_module ([#​378](https://togithub.com/mojohaus/exec-maven-plugin/pull/378)) [@​dependabot](https://togithub.com/dependabot) - Bump org.codehaus.mojo:mojo-parent from 76 to 77 ([#​384](https://togithub.com/mojohaus/exec-maven-plugin/pull/384)) [@​dependabot](https://togithub.com/dependabot) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - Bump plexus-utils from 3.5.1 to 4.0.0 ([#​368](https://togithub.com/mojohaus/exec-maven-plugin/pull/368)) [@​dependabot](https://togithub.com/dependabot) - Bump parent from 70 to 76 ([#​375](https://togithub.com/mojohaus/exec-maven-plugin/pull/375)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Bump groovy from 3.0.17 to 3.0.18 ([#​371](https://togithub.com/mojohaus/exec-maven-plugin/pull/371)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.16 to 3.0.17 ([#​365](https://togithub.com/mojohaus/exec-maven-plugin/pull/365)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.15 to 3.0.16 ([#​363](https://togithub.com/mojohaus/exec-maven-plugin/pull/363)) [@​dependabot](https://togithub.com/dependabot) - Bump plexus-utils from 3.5.0 to 3.5.1 ([#​362](https://togithub.com/mojohaus/exec-maven-plugin/pull/362)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.14 to 3.0.15 ([#​361](https://togithub.com/mojohaus/exec-maven-plugin/pull/361)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.13 to 3.0.14 ([#​354](https://togithub.com/mojohaus/exec-maven-plugin/pull/354)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.9.0 to 4.11.0 ([#​355](https://togithub.com/mojohaus/exec-maven-plugin/pull/355)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.8.1 to 4.9.0 ([#​347](https://togithub.com/mojohaus/exec-maven-plugin/pull/347)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.12 to 3.0.13 ([#​340](https://togithub.com/mojohaus/exec-maven-plugin/pull/340)) [@​dependabot](https://togithub.com/dependabot) - Bump plexus-utils from 3.4.2 to 3.5.0 ([#​343](https://togithub.com/mojohaus/exec-maven-plugin/pull/343)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.7.0 to 4.8.1 ([#​344](https://togithub.com/mojohaus/exec-maven-plugin/pull/344)) [@​dependabot](https://togithub.com/dependabot) - Bump mojo-parent from 69 to 70 ([#​329](https://togithub.com/mojohaus/exec-maven-plugin/pull/329)) [@​dependabot](https://togithub.com/dependabot) - Bump mockito-core from 4.6.1 to 4.7.0 ([#​330](https://togithub.com/mojohaus/exec-maven-plugin/pull/330)) [@​dependabot](https://togithub.com/dependabot) - Bump groovy from 3.0.11 to 3.0.12 ([#​325](https://togithub.com/mojohaus/exec-maven-plugin/pull/325)) [@​dependabot](https://togithub.com/dependabot) ##### 👻 Maintenance - Code cleanups - use newer JDK features ([#​396](https://togithub.com/mojohaus/exec-maven-plugin/pull/396)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Enable spotless for code formatting ([#​395](https://togithub.com/mojohaus/exec-maven-plugin/pull/395)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Require Maven 3.6.3+ ([#​385](https://togithub.com/mojohaus/exec-maven-plugin/pull/385)) [@​slachiewicz](https://togithub.com/slachiewicz) - ITs cleanups ([#​374](https://togithub.com/mojohaus/exec-maven-plugin/pull/374)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use Resolver Api for dependency resolving ([#​349](https://togithub.com/mojohaus/exec-maven-plugin/pull/349)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) ##### 🔧 Build - Workaround for concurrent access to local repository on Windows by ITs ([#​392](https://togithub.com/mojohaus/exec-maven-plugin/pull/392)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski) - Use Maven 3.9.4, 3.8.8 in GitHub build ([#​377](https://togithub.com/mojohaus/exec-maven-plugin/pull/377)) [@​slawekjaranowski](https://togithub.com/slawekjaranowski)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 031f4f26b8fb..cf419f960482 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -89,7 +89,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.4.1 com.google.cloud.jdbc.quickperf.QuickPerf From 0d3aac4617dfe6c826d0deb2574978cfbdfffe7e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 15:30:24 +0200 Subject: [PATCH 1378/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.44.0 (#1713) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:libraries-bom](https://cloud.google.com/java/docs/bom) ([source](https://togithub.com/googleapis/java-cloud-bom)) | `26.43.0` -> `26.44.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.43.0/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.43.0/26.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.44.0`](https://togithub.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26440-2024-08-08) [Compare Source](https://togithub.com/googleapis/java-cloud-bom/compare/v26.43.0...v26.44.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.33.0 ([#​6687](https://togithub.com/googleapis/java-cloud-bom/issues/6687)) ([d93c7c1](https://togithub.com/googleapis/java-cloud-bom/commit/d93c7c1e5c8cfea5f0bb3b570282af1d17ac9992)) - update dependency com.google.cloud:gapic-libraries-bom to v1.41.0 ([#​6689](https://togithub.com/googleapis/java-cloud-bom/issues/6689)) ([e5afcc8](https://togithub.com/googleapis/java-cloud-bom/commit/e5afcc8a5afd362f7cdb6d19f446c99db7832fb9)) - update dependency com.google.cloud:google-cloud-bigquery to v2.42.0 ([#​6688](https://togithub.com/googleapis/java-cloud-bom/issues/6688)) ([58ed9ce](https://togithub.com/googleapis/java-cloud-bom/commit/58ed9cef18361489756bafdf9b6159077f498608)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.8.0 ([#​6685](https://togithub.com/googleapis/java-cloud-bom/issues/6685)) ([c6968cb](https://togithub.com/googleapis/java-cloud-bom/commit/c6968cb3315c37d21539daa5001c6b297f600ba4)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.41.0 ([#​6686](https://togithub.com/googleapis/java-cloud-bom/issues/6686)) ([256f1b0](https://togithub.com/googleapis/java-cloud-bom/commit/256f1b0e97dc1c28453fd0c302e5ecc6958a5a55)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.42.0 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.21.0 ([#​6697](https://togithub.com/googleapis/java-cloud-bom/issues/6697)) ([046ad04](https://togithub.com/googleapis/java-cloud-bom/commit/046ad04177bca0cfd2aecce6bc1170617939bfbb)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.21.1 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.24.2 ([#​6681](https://togithub.com/googleapis/java-cloud-bom/issues/6681)) ([91673de](https://togithub.com/googleapis/java-cloud-bom/commit/91673debfaec89f2c6b49249966f9ed772acc3bd)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.24.3 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.20.0 ([#​6694](https://togithub.com/googleapis/java-cloud-bom/issues/6694)) ([780736c](https://togithub.com/googleapis/java-cloud-bom/commit/780736c2b35f8f657b686bd1f4e61946835736ec)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.10-alpha ([#​6695](https://togithub.com/googleapis/java-cloud-bom/issues/6695)) ([6ecff38](https://togithub.com/googleapis/java-cloud-bom/commit/6ecff38a39d0bbc2516ffcba64507afc9b4ac027)) - update dependency com.google.cloud:google-cloud-nio to v0.127.21 ([4534296](https://togithub.com/googleapis/java-cloud-bom/commit/4534296641ba101fae87219bbabc7efdd86f3fbc)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.132.0 ([#​6693](https://togithub.com/googleapis/java-cloud-bom/issues/6693)) ([b0483b9](https://togithub.com/googleapis/java-cloud-bom/commit/b0483b95065ae38522547c736a753c751279f014)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.14.0 ([#​6696](https://togithub.com/googleapis/java-cloud-bom/issues/6696)) ([ad905cc](https://togithub.com/googleapis/java-cloud-bom/commit/ad905ccb7d41bd64cc519bd855dabb0523bd7fa8)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 ([9e666cf](https://togithub.com/googleapis/java-cloud-bom/commit/9e666cf1efb8ba694a945814060df0ccdb26f363)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.20.2 ([4534296](https://togithub.com/googleapis/java-cloud-bom/commit/4534296641ba101fae87219bbabc7efdd86f3fbc)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.41.0 ([#​6690](https://togithub.com/googleapis/java-cloud-bom/issues/6690)) ([43aef8e](https://togithub.com/googleapis/java-cloud-bom/commit/43aef8e9bf082ce98afd0c34163b016b8f315ee0)) - update dependency com.google.googlejavaformat:google-java-format to v1.23.0 ([#​6692](https://togithub.com/googleapis/java-cloud-bom/issues/6692)) ([b403c50](https://togithub.com/googleapis/java-cloud-bom/commit/b403c5040d47ba87dd32162e3be71ded6fdd127c))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index cf419f960482..e42e323ef4aa 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.43.0 + 26.44.0 pom import From c45b00f166be6f5c12ba08ec9cc6265a051b2a04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:34:23 +0000 Subject: [PATCH 1379/1979] build(deps): bump com.fasterxml.jackson.core:jackson-databind from 2.13.4.1 to 2.13.4.2 in /samples/quickperf (#1709) Bumps [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) from 2.13.4.1 to 2.13.4.2.

    [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.fasterxml.jackson.core:jackson-databind&package-manager=maven&previous-version=2.13.4.1&new-version=2.13.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
    Dependabot commands and options
    You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://togithub.com/googleapis/java-spanner-jdbc/network/alerts).
    From 07ee1fd175c4ececfd9a75f90ab471db00eabdbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 15:49:57 +0200 Subject: [PATCH 1380/1979] test: add tests for named schemas (#1450) * chore: modify metadata queries to support named schemas Modify metadata queries so these are able to handle multiple named schemas in the same database, potentially with tables and indexes with the same names in different schemas. * test: add tests for named schemas Adds integration tests for metadata queries using multiple named schemas and tables and indexes with the same names in different schemas. --- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 802 +++++++++--------- .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 786 +++++++++-------- .../spanner/jdbc/it/CreateMusicTables_PG.sql | 5 + 3 files changed, 846 insertions(+), 747 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 903df91db067..efc3934d3da3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -21,9 +21,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -31,7 +35,8 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; -import org.junit.Before; +import java.util.stream.Collectors; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -53,11 +58,46 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); - private Database database; - - @Before - public void setup() { - database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + private static Database database; + + @BeforeClass + public static void setup() throws Exception { + assumeFalse( + "Named schemas are not yet supported on the emulator", + EmulatorSpannerHelper.isUsingEmulator()); + + database = + env.getOrCreateDatabase( + Dialect.GOOGLE_STANDARD_SQL, getMusicTablesDdl(Dialect.GOOGLE_STANDARD_SQL)); + + // Create the same tables in an additional 'test' schema. + DatabaseAdminClient client = env.getTestHelper().getClient().getDatabaseAdminClient(); + List tables = + getMusicTablesDdl(Dialect.GOOGLE_STANDARD_SQL).stream() + .map(statement -> statement.replace("CREATE TABLE ", "CREATE TABLE test.")) + .map(statement -> statement.replace("CREATE INDEX ", "CREATE INDEX test.")) + .map( + statement -> statement.replace("CREATE UNIQUE INDEX ", "CREATE UNIQUE INDEX test.")) + .map(statement -> statement.replace("CREATE VIEW ", "CREATE VIEW test.")) + .map(statement -> statement.replace("FROM ", "FROM test.")) + .map( + statement -> + statement.replace("INTERLEAVE IN PARENT ", "INTERLEAVE IN PARENT test.")) + .map(statement -> statement.replace("INTERLEAVE IN ", "INTERLEAVE IN test.")) + .map( + statement -> statement.replace("INTERLEAVE IN test.PARENT", "INTERLEAVE IN PARENT")) + .map(statement -> statement.replace(" ON ", " ON test.")) + .map(statement -> statement.replace(" ON test.DELETE", " ON DELETE")) + .map(statement -> statement.replace(" REFERENCES ", " REFERENCES test.")) + .collect(Collectors.toList()); + tables.add(0, "create schema test"); + client + .updateDatabaseDdl( + database.getId().getInstanceId().getInstance(), + database.getId().getDatabase(), + tables, + null) + .get(); } private static final class Column { @@ -165,65 +205,65 @@ private Column( @Test public void testGetColumns() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getColumns(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { - int pos = 1; - for (Column col : EXPECTED_COLUMNS) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("TABLE_NAME")); - assertEquals(col.name, rs.getString("COLUMN_NAME")); - assertEquals(col.type, rs.getInt("DATA_TYPE")); - assertEquals(col.typeName, rs.getString("TYPE_NAME")); - if (col.colSize == null) { - assertEquals(0, rs.getInt("COLUMN_SIZE")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); - } - rs.getObject("BUFFER_LENGTH"); // just assert that it exists - if (col.decimalDigits == null) { - assertEquals(0, rs.getInt("DECIMAL_DIGITS")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); - } - if (col.radix == null) { - assertEquals(0, rs.getInt("NUM_PREC_RADIX")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); - } - assertEquals( - col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, - rs.getInt("NULLABLE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("COLUMN_DEF")); - assertEquals(0, rs.getInt("SQL_DATA_TYPE")); - assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); - if (col.charOctetLength == null) { - assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getColumns(DEFAULT_CATALOG, schema, TABLE_WITH_ALL_COLS, null)) { + int ordinalPosition = 0; + for (Column col : EXPECTED_COLUMNS) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("TABLE_NAME")); + assertEquals(col.name, rs.getString("COLUMN_NAME")); + assertEquals(col.type, rs.getInt("DATA_TYPE")); + assertEquals(col.typeName, rs.getString("TYPE_NAME")); + if (col.colSize == null) { + assertEquals(0, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); + } + rs.getObject("BUFFER_LENGTH"); // just assert that it exists + if (col.decimalDigits == null) { + assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); + } + if (col.radix == null) { + assertEquals(0, rs.getInt("NUM_PREC_RADIX")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); + } + assertEquals( + col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, + rs.getInt("NULLABLE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("COLUMN_DEF")); + assertEquals(0, rs.getInt("SQL_DATA_TYPE")); + assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); + if (col.charOctetLength == null) { + assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + } + assertEquals(++ordinalPosition, rs.getInt("ORDINAL_POSITION")); + assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); + assertNull(rs.getString("SCOPE_CATALOG")); + assertNull(rs.getString("SCOPE_SCHEMA")); + assertNull(rs.getString("SCOPE_TABLE")); + assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); - } else { - assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); + assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + assertEquals(24, rs.getMetaData().getColumnCount()); } - assertEquals(pos, rs.getInt("ORDINAL_POSITION")); - assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); - assertNull(rs.getString("SCOPE_CATALOG")); - assertNull(rs.getString("SCOPE_SCHEMA")); - assertNull(rs.getString("SCOPE_TABLE")); - assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); - assertTrue(rs.wasNull()); - assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); - assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); - assertEquals(24, rs.getMetaData().getColumnCount()); - - pos++; + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -231,181 +271,173 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SINGERS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Singers", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SONGS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Songs", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Albums", rs.getString("PKTABLE_NAME")); - assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Songs", rs.getString("FKTABLE_NAME")); - assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); - assertEquals(2, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); - assertNull(rs.getString("FK_NAME")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + SINGERS_TABLE, + DEFAULT_CATALOG, + schema, + ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, schema, ALBUMS_TABLE, DEFAULT_CATALOG, schema, SONGS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - SINGERS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - CONCERTS_TABLE)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals("Singers", rs.getString("PKTABLE_NAME")); - assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals("Concerts", rs.getString("FKTABLE_NAME")); - assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); - assertEquals("PK_Singers", rs.getString("PK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Albums", rs.getString("PKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Songs", rs.getString("FKTABLE_NAME")); + assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyCascade, rs.getShort("DELETE_RULE")); + assertNull(rs.getString("FK_NAME")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - TABLE_WITH_ALL_COLS, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - TABLE_WITH_REF)) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + SINGERS_TABLE, + DEFAULT_CATALOG, + schema, + CONCERTS_TABLE)) { + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("Singers", rs.getString("PKTABLE_NAME")); + assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("Concerts", rs.getString("FKTABLE_NAME")); + assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + assertEquals("PK_Singers", rs.getString("PK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertFalse(rs.next()); + } - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); - assertEquals(1, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, + schema, + TABLE_WITH_ALL_COLS, + DEFAULT_CATALOG, + schema, + TABLE_WITH_REF)) { - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); - assertEquals(2, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); + assertEquals(1, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertTrue(rs.next()); - assertEquals("", rs.getString("PKTABLE_CAT")); - assertEquals("", rs.getString("PKTABLE_SCHEM")); - assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); - assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); - assertEquals("", rs.getString("FKTABLE_CAT")); - assertEquals("", rs.getString("FKTABLE_SCHEM")); - assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); - assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); - assertEquals(3, rs.getShort("KEY_SEQ")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); - assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); + assertEquals(2, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } - // try getting self-references - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE, - DEFAULT_CATALOG, - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertFalse(rs.next()); - } - // try getting all cross-references in the database - try (ResultSet rs = - connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { - for (int i = 0; i < 7; i++) { assertTrue(rs.next()); + assertEquals("", rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); + assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); + assertEquals("", rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); + assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); + assertEquals(3, rs.getShort("KEY_SEQ")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + + assertFalse(rs.next()); + } + // try getting self-references + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + DEFAULT_CATALOG, schema, ALBUMS_TABLE, DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertFalse(rs.next()); + } + // try getting all cross-references in the database + try (ResultSet rs = + connection.getMetaData().getCrossReference(null, null, null, null, null, null)) { + for (int i = 0; i < 14; i++) { + assertTrue(rs.next()); + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -480,39 +512,39 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getIndexInfo(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, false, false)) { - - for (IndexInfo index : EXPECTED_INDICES) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(index.tableName, rs.getString("TABLE_NAME")); - assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); - assertEquals(DEFAULT_CATALOG, rs.getString("INDEX_QUALIFIER")); - // Foreign key index names are automatically generated. - if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { - assertEquals(index.indexName, rs.getString("INDEX_NAME")); - } - if (index.indexName.equals("PRIMARY_KEY")) { - assertEquals(DatabaseMetaData.tableIndexClustered, rs.getShort("TYPE")); - } else { - assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); - } - assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); - if (index.ordinalPosition == 0) { - assertTrue(rs.wasNull()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getIndexInfo(DEFAULT_CATALOG, schema, null, false, false)) { + + for (IndexInfo index : EXPECTED_INDICES) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(index.tableName, rs.getString("TABLE_NAME")); + assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); + assertEquals(DEFAULT_CATALOG, rs.getString("INDEX_QUALIFIER")); + // Foreign key index names are automatically generated. + if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { + assertEquals(index.indexName, rs.getString("INDEX_NAME")); + } + if (index.indexName.equals("PRIMARY_KEY")) { + assertEquals(DatabaseMetaData.tableIndexClustered, rs.getShort("TYPE")); + } else { + assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); + } + assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); + if (index.ordinalPosition == 0) { + assertTrue(rs.wasNull()); + } + assertEquals(index.columnName, rs.getString("COLUMN_NAME")); + assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); + assertEquals(-1, rs.getInt("CARDINALITY")); + assertEquals(-1, rs.getInt("PAGES")); + assertNull(rs.getString("FILTER_CONDITION")); } - assertEquals(index.columnName, rs.getString("COLUMN_NAME")); - assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); - assertEquals(-1, rs.getInt("CARDINALITY")); - assertEquals(-1, rs.getInt("PAGES")); - assertNull(rs.getString("FILTER_CONDITION")); + // all indices found + assertFalse(rs.next()); } - // all indices found - assertFalse(rs.next()); } } } @@ -520,15 +552,15 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertExportedKeysSingers(rs); - } - try (ResultSet rs = - connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertKeysAlbumsSongs(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertExportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getExportedKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } } } } @@ -536,31 +568,27 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertImportedKeysSingers(rs); - } - try (ResultSet rs = - connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertImportedKeysAlbums(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, CONCERTS_TABLE)) { - assertImportedKeysConcerts(rs); - } - try (ResultSet rs = - connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SONGS_TABLE)) { - assertKeysAlbumsSongs(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, TABLE_WITH_REF)) { - assertImportedKeysTableWithRef(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertImportedKeysSingers(rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertImportedKeysAlbums(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, CONCERTS_TABLE)) { + assertImportedKeysConcerts(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, SONGS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } + try (ResultSet rs = + connection.getMetaData().getImportedKeys(DEFAULT_CATALOG, schema, TABLE_WITH_REF)) { + assertImportedKeysTableWithRef(schema, rs); + } } } } @@ -569,14 +597,14 @@ private void assertImportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { + private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColFloat64", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefFloat", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -588,11 +616,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColString", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefString", rs.getString("FKCOLUMN_NAME")); assertEquals(2, rs.getShort("KEY_SEQ")); @@ -604,11 +632,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(TABLE_WITH_ALL_COLS, rs.getString("PKTABLE_NAME")); assertEquals("ColDate", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(TABLE_WITH_REF, rs.getString("FKTABLE_NAME")); assertEquals("RefDate", rs.getString("FKCOLUMN_NAME")); assertEquals(3, rs.getShort("KEY_SEQ")); @@ -621,14 +649,14 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { + private void assertImportedKeysAlbums(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -641,14 +669,14 @@ private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { + private void assertImportedKeysConcerts(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -661,14 +689,14 @@ private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertExportedKeysSingers(ResultSet rs) throws SQLException { + private void assertExportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -680,11 +708,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(SINGERS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(CONCERTS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -697,14 +725,14 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { + private void assertKeysAlbumsSongs(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("SingerId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("SingerId", rs.getString("FKCOLUMN_NAME")); assertEquals(1, rs.getShort("KEY_SEQ")); @@ -716,11 +744,11 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals(ALBUMS_TABLE, rs.getString("PKTABLE_NAME")); assertEquals("AlbumId", rs.getString("PKCOLUMN_NAME")); assertEquals(DEFAULT_CATALOG, rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals(SONGS_TABLE, rs.getString("FKTABLE_NAME")); assertEquals("AlbumId", rs.getString("FKCOLUMN_NAME")); assertEquals(2, rs.getShort("KEY_SEQ")); @@ -735,48 +763,54 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(SINGERS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("SingerId", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); - } - try (ResultSet rs = - connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("SingerId", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); - assertEquals("AlbumId", rs.getString("COLUMN_NAME")); - assertEquals(2, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, schema, SINGERS_TABLE)) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(SINGERS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } + try (ResultSet rs = + connection.getMetaData().getPrimaryKeys(DEFAULT_CATALOG, schema, ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("SingerId", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(ALBUMS_TABLE, rs.getString("TABLE_NAME")); + assertEquals("AlbumId", rs.getString("COLUMN_NAME")); + assertEquals(2, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } } } } @Test public void testGetViews() throws SQLException { - // assumeFalse("Emulator does not yet support views", EmulatorSpannerHelper.isUsingEmulator()); try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = connection.getMetaData().getTables("", "", null, new String[] {"VIEW"})) { - assertTrue(rs.next()); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals("SingersView", rs.getString("TABLE_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getTables(DEFAULT_CATALOG, schema, null, new String[] {"VIEW"})) { + assertTrue(rs.next()); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals("SingersView", rs.getString("TABLE_NAME")); + assertFalse(rs.next()); + } } } } @@ -785,17 +819,24 @@ public void testGetViews() throws SQLException { public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { assertEquals("", connection.getSchema()); - try (ResultSet rs = connection.getMetaData().getSchemas()) { - assertTrue(rs.next()); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertTrue(rs.next()); - assertEquals("INFORMATION_SCHEMA", rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertTrue(rs.next()); - assertEquals("SPANNER_SYS", rs.getString("TABLE_SCHEM")); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CATALOG")); - assertFalse(rs.next()); + try (ResultSet schemas = connection.getMetaData().getSchemas()) { + assertTrue(schemas.next()); + assertEquals(DEFAULT_SCHEMA, schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("INFORMATION_SCHEMA", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("SPANNER_SYS", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertTrue(schemas.next()); + assertEquals("test", schemas.getString("TABLE_SCHEM")); + assertEquals(DEFAULT_CATALOG, schemas.getString("TABLE_CATALOG")); + + assertFalse(schemas.next()); } } } @@ -841,22 +882,27 @@ private Table(String name, String type) { @Test public void testGetTables() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection.getMetaData().getTables(DEFAULT_CATALOG, DEFAULT_SCHEMA, null, null)) { - for (Table table : EXPECTED_TABLES) { - assertTrue(rs.next()); - assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(table.name, rs.getString("TABLE_NAME")); - assertEquals(table.type, rs.getString("TABLE_TYPE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("TYPE_CAT")); - assertNull(rs.getString("TYPE_SCHEM")); - assertNull(rs.getString("TYPE_NAME")); - assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); - assertNull(rs.getString("REF_GENERATION")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection.getMetaData().getTables(DEFAULT_CATALOG, schema, null, null)) { + for (Table table : EXPECTED_TABLES) { + if (EmulatorSpannerHelper.isUsingEmulator() && table.name.equals("SingersView")) { + continue; + } + assertTrue(rs.next()); + assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(table.name, rs.getString("TABLE_NAME")); + assertEquals(table.type, rs.getString("TABLE_TYPE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("TYPE_CAT")); + assertNull(rs.getString("TYPE_SCHEM")); + assertNull(rs.getString("TYPE_NAME")); + assertNull(rs.getString("SELF_REFERENCING_COL_NAME")); + assertNull(rs.getString("REF_GENERATION")); + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index 1b96e9569d5b..033ff27e45de 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -21,10 +21,13 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -32,9 +35,9 @@ import java.sql.Types; import java.util.Arrays; import java.util.List; -import org.junit.Before; +import java.util.stream.Collectors; +import org.junit.BeforeClass; import org.junit.ClassRule; -import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -54,11 +57,41 @@ public class ITJdbcPgDatabaseMetaDataTest extends ITAbstractJdbcTest { private static final String TABLE_WITH_ALL_COLS = "TableWithAllColumnTypes"; private static final String TABLE_WITH_REF = "TableWithRef"; - private Database database; - - @Before - public void setup() { - database = env.getOrCreateDatabase(getDialect(), getMusicTablesDdl(getDialect())); + private static Database database; + + @BeforeClass + public static void setup() throws Exception { + assumeFalse( + "PostgreSQL dialect is not yet supported on the emulator", + EmulatorSpannerHelper.isUsingEmulator()); + + database = env.getOrCreateDatabase(Dialect.POSTGRESQL, getMusicTablesDdl(Dialect.POSTGRESQL)); + + // Create the same tables in an additional 'test' schema. + DatabaseAdminClient client = env.getTestHelper().getClient().getDatabaseAdminClient(); + List tables = + getMusicTablesDdl(Dialect.POSTGRESQL).stream() + .map(statement -> statement.replace("CREATE TABLE ", "CREATE TABLE test.")) + .map(statement -> statement.replace("CREATE VIEW ", "CREATE VIEW test.")) + .map(statement -> statement.replace("FROM ", "FROM test.")) + .map( + statement -> + statement.replace("INTERLEAVE IN PARENT ", "INTERLEAVE IN PARENT test.")) + .map(statement -> statement.replace("INTERLEAVE IN ", "INTERLEAVE IN test.")) + .map( + statement -> statement.replace("INTERLEAVE IN test.PARENT", "INTERLEAVE IN PARENT")) + .map(statement -> statement.replace(" ON ", " ON test.")) + .map(statement -> statement.replace(" ON test.DELETE", " ON DELETE")) + .map(statement -> statement.replace(" REFERENCES ", " REFERENCES test.")) + .collect(Collectors.toList()); + tables.add(0, "create schema test"); + client + .updateDatabaseDdl( + database.getId().getInstanceId().getInstance(), + database.getId().getDatabase(), + tables, + null) + .get(); } @Override @@ -138,68 +171,70 @@ private Column( @Test public void testGetColumns() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getColumns(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_ALL_COLS, null)) { - int pos = 1; - for (Column col : EXPECTED_COLUMNS) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("TABLE_NAME")); - assertEquals(col.name, rs.getString("COLUMN_NAME")); - assertEquals(col.type, rs.getInt("DATA_TYPE")); - assertEquals(col.typeName, rs.getString("TYPE_NAME")); - if (col.colSize == null) { - assertEquals(0, rs.getInt("COLUMN_SIZE")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); - } - rs.getObject("BUFFER_LENGTH"); // just assert that it exists - if (col.decimalDigits == null) { - assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getColumns(getDefaultCatalog(database), schema, TABLE_WITH_ALL_COLS, null)) { + int pos = 1; + for (Column col : EXPECTED_COLUMNS) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("TABLE_NAME")); + assertEquals(col.name, rs.getString("COLUMN_NAME")); + assertEquals(col.type, rs.getInt("DATA_TYPE")); + assertEquals(col.typeName, rs.getString("TYPE_NAME")); + if (col.colSize == null) { + assertEquals(0, rs.getInt("COLUMN_SIZE")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.colSize.intValue(), rs.getInt("COLUMN_SIZE")); + } + rs.getObject("BUFFER_LENGTH"); // just assert that it exists + if (col.decimalDigits == null) { + assertEquals(0, rs.getInt("DECIMAL_DIGITS")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); + } + if (col.radix == null) { + assertEquals(0, rs.getInt("NUM_PREC_RADIX")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); + } + assertEquals( + "Nullable difference for " + col.name, + col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, + rs.getInt("NULLABLE")); + assertNull(rs.getString("REMARKS")); + assertNull(rs.getString("COLUMN_DEF")); + assertEquals(0, rs.getInt("SQL_DATA_TYPE")); + assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); + if (col.charOctetLength == null) { + assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); + assertTrue(rs.wasNull()); + } else { + assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); + } + assertEquals(pos, rs.getInt("ORDINAL_POSITION")); + assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); + assertNull(rs.getString("SCOPE_CATALOG")); + assertNull(rs.getString("SCOPE_SCHEMA")); + assertNull(rs.getString("SCOPE_TABLE")); + + assertEquals((short) 0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); - } else { - assertEquals(col.decimalDigits.intValue(), rs.getInt("DECIMAL_DIGITS")); - } - if (col.radix == null) { - assertEquals(0, rs.getInt("NUM_PREC_RADIX")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.radix.intValue(), rs.getInt("NUM_PREC_RADIX")); - } - assertEquals( - "Nullable difference for " + col.name, - col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, - rs.getInt("NULLABLE")); - assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("COLUMN_DEF")); - assertEquals(0, rs.getInt("SQL_DATA_TYPE")); - assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); - if (col.charOctetLength == null) { - assertEquals(0, rs.getInt("CHAR_OCTET_LENGTH")); - assertTrue(rs.wasNull()); - } else { - assertEquals(col.charOctetLength.intValue(), rs.getInt("CHAR_OCTET_LENGTH")); - } - assertEquals(pos, rs.getInt("ORDINAL_POSITION")); - assertEquals(col.nullable ? "YES" : "NO", rs.getString("IS_NULLABLE")); - assertNull(rs.getString("SCOPE_CATALOG")); - assertNull(rs.getString("SCOPE_SCHEMA")); - assertNull(rs.getString("SCOPE_TABLE")); - assertEquals((short) 0, rs.getShort("SOURCE_DATA_TYPE")); - assertTrue(rs.wasNull()); + assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); + assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + assertEquals(24, rs.getMetaData().getColumnCount()); - assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); - assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); - assertEquals(24, rs.getMetaData().getColumnCount()); - - pos++; + pos++; + } + assertFalse(rs.next()); } - assertFalse(rs.next()); } } } @@ -207,168 +242,170 @@ public void testGetColumns() throws SQLException { @Test public void testGetCrossReferences() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SINGERS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertTrue(rs.next()); - - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("singers", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("albums", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_singers", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - } - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SONGS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("albums", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("songs", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_albums", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + SINGERS_TABLE, + getDefaultCatalog(database), + schema, + ALBUMS_TABLE)) { + assertTrue(rs.next()); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("albums", rs.getString("PKTABLE_NAME")); - assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("songs", rs.getString("FKTABLE_NAME")); - assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 2, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_albums", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("singers", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("albums", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_singers", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + ALBUMS_TABLE, + getDefaultCatalog(database), + schema, + SONGS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("albums", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("songs", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_albums", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("albums", rs.getString("PKTABLE_NAME")); + assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("songs", rs.getString("FKTABLE_NAME")); + assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 2, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_albums", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - SINGERS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - CONCERTS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("singers", rs.getString("PKTABLE_NAME")); - assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("concerts", rs.getString("FKTABLE_NAME")); - assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertNotNull(rs.getString("FK_NAME")); - assertEquals("PK_singers", rs.getString("PK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertFalse(rs.next()); + } - assertFalse(rs.next()); - } + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + SINGERS_TABLE, + getDefaultCatalog(database), + schema, + CONCERTS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("singers", rs.getString("PKTABLE_NAME")); + assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("concerts", rs.getString("FKTABLE_NAME")); + assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertNotNull(rs.getString("FK_NAME")); + assertEquals("PK_singers", rs.getString("PK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - TABLE_WITH_ALL_COLS, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - TABLE_WITH_REF)) { + assertFalse(rs.next()); + } - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); - assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); - assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 1, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + TABLE_WITH_ALL_COLS, + getDefaultCatalog(database), + schema, + TABLE_WITH_REF)) { + + assertTrue(schema, rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); + assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); + assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 1, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); - assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); - assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); - assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); - assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); - assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); - assertEquals((short) 2, rs.getShort("KEY_SEQ")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); - assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); - assertEquals( - (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); + assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); + assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); + assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); + assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); + assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); + assertEquals((short) 2, rs.getShort("KEY_SEQ")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); + assertEquals((short) DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); + assertEquals("fk_tablewithref_tablewithallcolumntypes", rs.getString("FK_NAME")); + assertEquals( + (short) DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); - assertFalse(rs.next()); - } - // try getting self-references - try (ResultSet rs = - connection - .getMetaData() - .getCrossReference( - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE, - getDefaultCatalog(database), - DEFAULT_SCHEMA, - ALBUMS_TABLE)) { - assertFalse(rs.next()); + assertFalse(rs.next()); + } + // try getting self-references + try (ResultSet rs = + connection + .getMetaData() + .getCrossReference( + getDefaultCatalog(database), + schema, + ALBUMS_TABLE, + getDefaultCatalog(database), + schema, + ALBUMS_TABLE)) { + assertFalse(rs.next()); + } } // try getting all cross-references in the database try (ResultSet rs = @@ -377,7 +414,7 @@ public void testGetCrossReferences() throws SQLException { while (rs.next()) { count++; } - assertEquals(6, count); + assertEquals(12, count); } } } @@ -442,36 +479,38 @@ private IndexInfo( @Test public void testGetIndexInfo() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getIndexInfo(getDefaultCatalog(database), DEFAULT_SCHEMA, null, false, false)) { - - for (IndexInfo index : EXPECTED_INDICES) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals(index.tableName, rs.getString("TABLE_NAME")); - assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); - assertEquals(getDefaultCatalog(database), rs.getString("INDEX_QUALIFIER")); - - // Foreign key index names are automatically generated. - if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { - assertEquals(index.indexName, rs.getString("INDEX_NAME")); - } - assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); - assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); - if (index.ordinalPosition == 0) { - assertTrue(rs.wasNull()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getIndexInfo(getDefaultCatalog(database), schema, null, false, false)) { + + for (IndexInfo index : EXPECTED_INDICES) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals(index.tableName, rs.getString("TABLE_NAME")); + assertEquals(index.nonUnique, rs.getBoolean("NON_UNIQUE")); + assertEquals(getDefaultCatalog(database), rs.getString("INDEX_QUALIFIER")); + + // Foreign key index names are automatically generated. + if (!"FOREIGN_KEY".equals(index.indexName) && !"GENERATED".equals(index.indexName)) { + assertEquals(index.indexName, rs.getString("INDEX_NAME")); + } + assertEquals(DatabaseMetaData.tableIndexHashed, rs.getShort("TYPE")); + assertEquals(index.ordinalPosition, rs.getShort("ORDINAL_POSITION")); + if (index.ordinalPosition == 0) { + assertTrue(rs.wasNull()); + } + assertEquals(index.columnName, rs.getString("COLUMN_NAME")); + assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); + assertEquals(-1, rs.getInt("CARDINALITY")); + assertEquals(-1, rs.getInt("PAGES")); + assertNull(rs.getString("FILTER_CONDITION")); } - assertEquals(index.columnName, rs.getString("COLUMN_NAME")); - assertEquals(index.ascDesc, rs.getString("ASC_OR_DESC")); - assertEquals(-1, rs.getInt("CARDINALITY")); - assertEquals(-1, rs.getInt("PAGES")); - assertNull(rs.getString("FILTER_CONDITION")); + // all indices found + assertFalse(rs.next()); } - // all indices found - assertFalse(rs.next()); } } } @@ -479,17 +518,19 @@ public void testGetIndexInfo() throws SQLException { @Test public void testGetExportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertExportedKeysSingers(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getExportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertKeysAlbumsSongs(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getExportedKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertExportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getExportedKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } } } } @@ -497,51 +538,53 @@ public void testGetExportedKeys() throws SQLException { @Test public void testGetImportedKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertImportedKeysSingers(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertImportedKeysAlbums(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, CONCERTS_TABLE)) { - assertImportedKeysConcerts(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SONGS_TABLE)) { - assertKeysAlbumsSongs(rs); - } - try (ResultSet rs = - connection - .getMetaData() - .getImportedKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, TABLE_WITH_REF)) { - assertImportedKeysTableWithRef(rs); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertImportedKeysSingers(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertImportedKeysAlbums(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, CONCERTS_TABLE)) { + assertImportedKeysConcerts(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, SONGS_TABLE)) { + assertKeysAlbumsSongs(schema, rs); + } + try (ResultSet rs = + connection + .getMetaData() + .getImportedKeys(getDefaultCatalog(database), schema, TABLE_WITH_REF)) { + assertImportedKeysTableWithRef(schema, rs); + } } } } - private void assertImportedKeysSingers(ResultSet rs) throws SQLException { + private void assertImportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { + private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colfloat64", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("reffloat", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -553,11 +596,11 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("tablewithallcolumntypes", rs.getString("PKTABLE_NAME")); assertEquals("colstring", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("tablewithref", rs.getString("FKTABLE_NAME")); assertEquals("refstring", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 2, rs.getShort("KEY_SEQ")); @@ -570,14 +613,14 @@ private void assertImportedKeysTableWithRef(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { + private void assertImportedKeysAlbums(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -590,14 +633,14 @@ private void assertImportedKeysAlbums(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { + private void assertImportedKeysConcerts(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -609,14 +652,14 @@ private void assertImportedKeysConcerts(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertExportedKeysSingers(ResultSet rs) throws SQLException { + private void assertExportedKeysSingers(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("albums", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -628,11 +671,11 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("singers", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("concerts", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -645,14 +688,14 @@ private void assertExportedKeysSingers(ResultSet rs) throws SQLException { assertFalse(rs.next()); } - private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { + private void assertKeysAlbumsSongs(String schema, ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("singerid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("singerid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 1, rs.getShort("KEY_SEQ")); @@ -664,11 +707,11 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { assertTrue(rs.next()); assertEquals(getDefaultCatalog(database), rs.getString("PKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("PKTABLE_SCHEM")); + assertEquals(schema, rs.getString("PKTABLE_SCHEM")); assertEquals("albums", rs.getString("PKTABLE_NAME")); assertEquals("albumid", rs.getString("PKCOLUMN_NAME")); assertEquals(getDefaultCatalog(database), rs.getString("FKTABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("FKTABLE_SCHEM")); + assertEquals(schema, rs.getString("FKTABLE_SCHEM")); assertEquals("songs", rs.getString("FKTABLE_NAME")); assertEquals("albumid", rs.getString("FKCOLUMN_NAME")); assertEquals((short) 2, rs.getShort("KEY_SEQ")); @@ -684,58 +727,60 @@ private void assertKeysAlbumsSongs(ResultSet rs) throws SQLException { @Test public void testGetPrimaryKeys() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, SINGERS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("singers", rs.getString("TABLE_NAME")); - assertEquals("singerid", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); - } + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getPrimaryKeys(getDefaultCatalog(database), schema, SINGERS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("singers", rs.getString("TABLE_NAME")); + assertEquals("singerid", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertFalse(rs.next()); + } - try (ResultSet rs = - connection - .getMetaData() - .getPrimaryKeys(getDefaultCatalog(database), DEFAULT_SCHEMA, ALBUMS_TABLE)) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("albums", rs.getString("TABLE_NAME")); - assertEquals("singerid", rs.getString("COLUMN_NAME")); - assertEquals(1, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("albums", rs.getString("TABLE_NAME")); - assertEquals("albumid", rs.getString("COLUMN_NAME")); - assertEquals(2, rs.getInt("KEY_SEQ")); - assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + try (ResultSet rs = + connection + .getMetaData() + .getPrimaryKeys(getDefaultCatalog(database), schema, ALBUMS_TABLE)) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("albums", rs.getString("TABLE_NAME")); + assertEquals("singerid", rs.getString("COLUMN_NAME")); + assertEquals(1, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("albums", rs.getString("TABLE_NAME")); + assertEquals("albumid", rs.getString("COLUMN_NAME")); + assertEquals(2, rs.getInt("KEY_SEQ")); + assertEquals("PRIMARY_KEY", rs.getString("PK_NAME")); - assertFalse(rs.next()); + assertFalse(rs.next()); + } } } } - @Ignore("Views are not yet supported for PostgreSQL") @Test public void testGetViews() throws SQLException { try (Connection connection = createConnection(env, database)) { - try (ResultSet rs = - connection - .getMetaData() - .getTables( - getDefaultCatalog(database), DEFAULT_SCHEMA, null, new String[] {"VIEW"})) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); - assertEquals(DEFAULT_SCHEMA, rs.getString("TABLE_SCHEM")); - assertEquals("SingersView", rs.getString("TABLE_NAME")); - assertFalse(rs.next()); + for (String schema : new String[] {DEFAULT_SCHEMA, "test"}) { + try (ResultSet rs = + connection + .getMetaData() + .getTables(getDefaultCatalog(database), schema, null, new String[] {"VIEW"})) { + assertTrue(rs.next()); + assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CAT")); + assertEquals(schema, rs.getString("TABLE_SCHEM")); + assertEquals("singersview", rs.getString("TABLE_NAME")); + assertFalse(rs.next()); + } } } } @@ -744,24 +789,28 @@ public void testGetViews() throws SQLException { public void testGetSchemas() throws SQLException { try (Connection connection = createConnection(env, database)) { assertEquals("public", connection.getSchema()); - try (ResultSet rs = connection.getMetaData().getSchemas()) { - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("information_schema", rs.getString("TABLE_SCHEM")); + try (ResultSet schemas = connection.getMetaData().getSchemas()) { + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("information_schema", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("pg_catalog", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("pg_catalog", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("public", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("public", schemas.getString("TABLE_SCHEM")); - assertTrue(rs.next()); - assertEquals(getDefaultCatalog(database), rs.getString("TABLE_CATALOG")); - assertEquals("spanner_sys", rs.getString("TABLE_SCHEM")); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("spanner_sys", schemas.getString("TABLE_SCHEM")); - assertFalse(rs.next()); + assertTrue(schemas.next()); + assertEquals(getDefaultCatalog(database), schemas.getString("TABLE_CATALOG")); + assertEquals("test", schemas.getString("TABLE_SCHEM")); + + assertFalse(schemas.next()); } } } @@ -799,8 +848,7 @@ private Table(String name, String type) { new Table("all_nullable_types"), new Table("concerts"), new Table("singers"), - // TODO: Enable when views are supported for PostgreSQL dialect databases. - // new Table("singersview", "VIEW"), + new Table("singersview", "VIEW"), new Table("songs"), new Table("tablewithallcolumntypes"), new Table("tablewithref")); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index abecd9fad368..3aafc5722826 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -26,6 +26,11 @@ CREATE TABLE Singers ( CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName); +CREATE VIEW SingersView SQL SECURITY INVOKER AS +SELECT s.SingerId AS SingerId, s.FirstName AS FirstName, s.LastName AS LastName +FROM Singers s +ORDER BY s.LastName, s.FirstName; + CREATE TABLE Albums ( SingerId BIGINT NOT NULL, AlbumId BIGINT NOT NULL, From d124ee05aee585957cda73edf82b0fa09e350174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 20 Aug 2024 16:51:43 +0200 Subject: [PATCH 1381/1979] chore: update version numbers in README when releasing (#1714) Fixes #1317 --- java-spanner-jdbc/.github/release-please.yml | 2 +- java-spanner-jdbc/README.md | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index cbc451149254..bd201477430d 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -6,4 +6,4 @@ branches: releaseType: java-yoshi bumpMinorPreMajor: true handleGHRelease: true - +extraFiles: ["README.md"] diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index e7c6e9e6c945..6ced7a57e397 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -15,25 +15,32 @@ Java idiomatic client for [Google Cloud Spanner JDBC][product-docs]. If you are using Maven, add this to your pom.xml file: + ```xml com.google.cloud google-cloud-spanner-jdbc - 2.4.1 + 2.20.2 ``` + + If you are using Gradle without BOM, add this to your dependencies + ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.4.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.20.2' ``` + If you are using SBT, add this to your dependencies + ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.4.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.20.2" ``` + ## Authentication From af6ffa0090c0eb79ed275de802b38b47c41d7675 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:08:47 +0200 Subject: [PATCH 1382/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.17.2 (#1715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.fasterxml.jackson.core:jackson-databind](https://togithub.com/FasterXML/jackson) ([source](https://togithub.com/FasterXML/jackson-databind)) | `2.13.4.2` -> `2.17.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.fasterxml.jackson.core:jackson-databind/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.fasterxml.jackson.core:jackson-databind/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.fasterxml.jackson.core:jackson-databind/2.13.4.2/2.17.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index e42e323ef4aa..66380a7572af 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -61,7 +61,7 @@ com.fasterxml.jackson.core jackson-databind - 2.13.4.2 + 2.17.2 From f56759d1be009aa9a65902f1a3aaf3e0ba706331 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:10:23 +0200 Subject: [PATCH 1383/1979] deps: update dependency commons-cli:commons-cli to v1.9.0 (#1716) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [commons-cli:commons-cli](https://commons.apache.org/proper/commons-cli/) ([source](https://gitbox.apache.org/repos/asf?p=commons-cli.git)) | `1.5.0` -> `1.9.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/commons-cli:commons-cli/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/commons-cli:commons-cli/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/commons-cli:commons-cli/1.5.0/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/commons-cli:commons-cli/1.5.0/1.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 66380a7572af..6bb8bc299fd1 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -47,7 +47,7 @@ commons-cli commons-cli - 1.5.0 + 1.9.0 com.google.cloud From 0adf6b43d9ce74b61dd5d3ece55b87070636bb57 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:34:28 +0200 Subject: [PATCH 1384/1979] deps: update dependency org.springframework.boot:spring-boot to v3.3.2 (#1718) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.2.5` -> `3.3.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.2.5/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.2.5/3.3.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.3.2`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.1...v3.3.2) ### [`v3.3.1`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.1) ### [`v3.3.0`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.6...v3.3.0) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.2.8...v3.3.0) ### [`v3.2.8`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.7...v3.2.8) ### [`v3.2.7`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.6...v3.2.7) ### [`v3.2.6`](https://togithub.com/spring-projects/spring-boot/compare/v3.2.5...v3.2.6)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6bb8bc299fd1..f10c1d0c3c6d 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.springframework.boot spring-boot - 3.2.5 + 3.3.2 test From ef94a61e9a42f13246efb857a303c8ca962e931c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 20 Aug 2024 18:36:28 +0200 Subject: [PATCH 1385/1979] deps: update dependency org.apache.commons:commons-lang3 to v3.16.0 (#1717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.commons:commons-lang3](https://commons.apache.org/proper/commons-lang/) ([source](https://gitbox.apache.org/repos/asf?p=commons-lang.git)) | `3.13.0` -> `3.16.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.commons:commons-lang3/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.commons:commons-lang3/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.commons:commons-lang3/3.13.0/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.commons:commons-lang3/3.13.0/3.16.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f10c1d0c3c6d..b1d48dfff145 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -56,7 +56,7 @@ org.apache.commons commons-lang3 - 3.13.0 + 3.16.0 com.fasterxml.jackson.core From 0fa708fa05c50e55c116ebd26bce935bf5ec94b7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:21:59 +0200 Subject: [PATCH 1386/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.73.0 (#1726) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fc46b2952be1..1b76e799c1af 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.72.0 + 6.73.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 6a138bbcf95b..6d65834134d1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.72.0 + 6.73.0 import pom From 7d1679b218e824340c7da6f2998b348de24033fa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:22:15 +0200 Subject: [PATCH 1387/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.48.0 (#1719) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1b76e799c1af..1e75e532d5f5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.47.0 + 2.48.0 test From 9459e2bb69d54ed957fe8ea89852b6d73e364a4a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:36:04 +0200 Subject: [PATCH 1388/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.48.0 (#1720) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1e75e532d5f5..2430f9363c02 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.47.0 + 2.48.0 test From 81d8ecdb78ce484ec97eff98855cde27d1c703c0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:38:23 +0200 Subject: [PATCH 1389/1979] deps: update dependency org.postgresql:postgresql to v42.7.4 (#1722) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 6d65834134d1..81225b5894fa 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -67,7 +67,7 @@ org.postgresql postgresql - 42.7.3 + 42.7.4 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 87793be8d4d0..733957e3a338 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -62,7 +62,7 @@ org.postgresql postgresql - 42.7.3 + 42.7.4 From 2afe9b907837198c34931db3709c479b628fbe74 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:40:22 +0200 Subject: [PATCH 1390/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3 (#1725) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-parent/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-parent/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-parent/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 733957e3a338..8a13c6bb8c03 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.2 + 3.3.3 From 971709bd4080dc96cc5ad5699ff98b9964d0b4e3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:48:21 +0200 Subject: [PATCH 1391/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.7.0 (#1721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.6.2` -> `3.7.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.6.2/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.6.2/3.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2430f9363c02..e8d77e30ad80 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -459,7 +459,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.6.2 + 3.7.0 From 02dd813af2429cc128b64c16e8aecdd519166c30 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:52:18 +0200 Subject: [PATCH 1392/1979] deps: update dependency org.springframework.boot:spring-boot to v3.3.3 (#1723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index b1d48dfff145..181a7639f51d 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.springframework.boot spring-boot - 3.3.2 + 3.3.3 test From 2a9f474b03288781886ff206e45dcfbb4158d771 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Aug 2024 08:52:22 +0200 Subject: [PATCH 1393/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.3 (#1724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-data-jdbc](https://spring.io/projects/spring-boot) ([source](https://togithub.com/spring-projects/spring-boot)) | `3.3.2` -> `3.3.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.3.2/3.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-data-jdbc) ### [`v3.3.3`](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3) [Compare Source](https://togithub.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 81225b5894fa..cf4c573b77d7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.2 + 3.3.3 From 11ce64771dc1b7ffae5a89021a0e4fcbe8289adf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:06:59 +0200 Subject: [PATCH 1394/1979] chore(main): release 2.21.0 (#1706) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 29 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4243899373db..e48516502080 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [2.21.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.2...v2.21.0) (2024-08-23) + + +### Features + +* Add Quickperf for simple performance testing with JDBC ([#1619](https://github.com/googleapis/java-spanner-jdbc/issues/1619)) ([b6bbd8f](https://github.com/googleapis/java-spanner-jdbc/commit/b6bbd8f40c1ce61914e2c7b80be04abbf4e346ab)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.13.4.2 [security] ([#1710](https://github.com/googleapis/java-spanner-jdbc/issues/1710)) ([eff5df2](https://github.com/googleapis/java-spanner-jdbc/commit/eff5df22785e55a8f0974f028678883ef404b4e6)) +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.17.2 ([#1715](https://github.com/googleapis/java-spanner-jdbc/issues/1715)) ([21aa199](https://github.com/googleapis/java-spanner-jdbc/commit/21aa19970cee5ee0525c5eaae8bc334cf81d8f25)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.48.0 ([#1719](https://github.com/googleapis/java-spanner-jdbc/issues/1719)) ([a40606c](https://github.com/googleapis/java-spanner-jdbc/commit/a40606c2ef75388cfa0733c6955329225f28c71b)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.72.0 ([#1702](https://github.com/googleapis/java-spanner-jdbc/issues/1702)) ([31a961d](https://github.com/googleapis/java-spanner-jdbc/commit/31a961d29c7b51e9dcd5aac8a8a66444abbd9088)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.73.0 ([#1726](https://github.com/googleapis/java-spanner-jdbc/issues/1726)) ([f5f8051](https://github.com/googleapis/java-spanner-jdbc/commit/f5f80517425969f4c1bab4ec1c72afa1ccbb842c)) +* Update dependency com.google.cloud:google-cloud-trace to v2.48.0 ([#1720](https://github.com/googleapis/java-spanner-jdbc/issues/1720)) ([c9b646d](https://github.com/googleapis/java-spanner-jdbc/commit/c9b646d1b9c0ccef9cf8ba3bc58da686fae34bc1)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.34.0 ([#1705](https://github.com/googleapis/java-spanner-jdbc/issues/1705)) ([f3f0c10](https://github.com/googleapis/java-spanner-jdbc/commit/f3f0c10394e76389dbc4a62e5702fd5f80c57b1a)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.24 ([#1708](https://github.com/googleapis/java-spanner-jdbc/issues/1708)) ([6881512](https://github.com/googleapis/java-spanner-jdbc/commit/68815128ae2c40c224b4ab155b942e8f5313024f)) +* Update dependency commons-cli:commons-cli to v1.9.0 ([#1716](https://github.com/googleapis/java-spanner-jdbc/issues/1716)) ([6f48065](https://github.com/googleapis/java-spanner-jdbc/commit/6f48065952c2fc2716c911a45959326a6bafaa13)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.41.0 ([#1703](https://github.com/googleapis/java-spanner-jdbc/issues/1703)) ([af58b7a](https://github.com/googleapis/java-spanner-jdbc/commit/af58b7a882edae9a50fbc0d4084cb74b3727d5a6)) +* Update dependency org.apache.commons:commons-lang3 to v3.16.0 ([#1717](https://github.com/googleapis/java-spanner-jdbc/issues/1717)) ([f5229ce](https://github.com/googleapis/java-spanner-jdbc/commit/f5229ce5099b6d2d2b7c099ff4ac1319f21860df)) +* Update dependency org.postgresql:postgresql to v42.7.4 ([#1722](https://github.com/googleapis/java-spanner-jdbc/issues/1722)) ([1328213](https://github.com/googleapis/java-spanner-jdbc/commit/13282136921d0167c19cac38df0a652cc5477faa)) +* Update dependency org.springframework.boot:spring-boot to v3.3.2 ([#1718](https://github.com/googleapis/java-spanner-jdbc/issues/1718)) ([ede7211](https://github.com/googleapis/java-spanner-jdbc/commit/ede72113801de4a27492cf672a4c5e3edb37bc5e)) +* Update dependency org.springframework.boot:spring-boot to v3.3.3 ([#1723](https://github.com/googleapis/java-spanner-jdbc/issues/1723)) ([55112ac](https://github.com/googleapis/java-spanner-jdbc/commit/55112ac5f00d4a8d7726fa8bc5e9428d08d21227)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.3 ([#1724](https://github.com/googleapis/java-spanner-jdbc/issues/1724)) ([db60f4f](https://github.com/googleapis/java-spanner-jdbc/commit/db60f4f4f8713a30c1fe275266ff455fd03d84a4)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.3 ([#1725](https://github.com/googleapis/java-spanner-jdbc/issues/1725)) ([47fda8f](https://github.com/googleapis/java-spanner-jdbc/commit/47fda8f9b8cf639fe11fb3241256490f660e0d8b)) +* Update dependency org.springframework.data:spring-data-bom to v2024.0.3 ([#1704](https://github.com/googleapis/java-spanner-jdbc/issues/1704)) ([e82d839](https://github.com/googleapis/java-spanner-jdbc/commit/e82d8398eede11469c966aa11c2188c671a5f02b)) +* Update dependency org.testcontainers:testcontainers to v1.20.1 ([#1684](https://github.com/googleapis/java-spanner-jdbc/issues/1684)) ([0907305](https://github.com/googleapis/java-spanner-jdbc/commit/09073057df2cff41b7a62f56dc0cf57ed62f4801)) + ## [2.20.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.1...v2.20.2) (2024-08-07) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 6ced7a57e397..80eb441524d5 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.21.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.20.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.21.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.20.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.21.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e8d77e30ad80..220e0dcea0e4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 google-cloud-spanner-jdbc - 2.20.3-SNAPSHOT + 2.21.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fcfad34c952c..751a517e99f8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.3-SNAPSHOT + 2.21.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 716f29f11957..05d8b85f065e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.20.2:2.20.3-SNAPSHOT +google-cloud-spanner-jdbc:2.21.0:2.21.0 From 608887ea8dd60875a7bb97fe442eadca991a191e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 11:48:02 +0200 Subject: [PATCH 1395/1979] chore(main): release 2.21.1-SNAPSHOT (#1728) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 220e0dcea0e4..82f65611ec47 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.21.0 + 2.21.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 751a517e99f8..9b16873f8bfe 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.21.0 + 2.21.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 05d8b85f065e..429e5f3bd7e5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.21.0:2.21.0 +google-cloud-spanner-jdbc:2.21.0:2.21.1-SNAPSHOT From 7c75e2706d2bd60f4197860be62a57447202bd65 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Aug 2024 15:40:41 +0200 Subject: [PATCH 1396/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.21.0 (#1729) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 522c41a61e8a..252c079b14f9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.21.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index cf4c573b77d7..49dd1ee4cb81 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -62,7 +62,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.20.2 + 2.21.0 org.postgresql From 8f87255ed962043bc2f044be783b6190d438f11e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 28 Aug 2024 16:43:12 +0200 Subject: [PATCH 1397/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.74.0 (#1730) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 82f65611ec47..f5f9085393c4 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.73.0 + 6.74.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 49dd1ee4cb81..733e571a1338 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.73.0 + 6.74.0 import pom From 4f7778135f6e48225d60372b722521009ae38f57 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 28 Aug 2024 18:30:22 +0200 Subject: [PATCH 1398/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.45.0 (#1731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:libraries-bom to v26.45.0 * deps: exclude executor for now --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/samples/quickperf/pom.xml | 8 +++++++- java-spanner-jdbc/samples/snippets/pom.xml | 8 +++++++- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 9 +++++++-- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 8 +++++++- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 181a7639f51d..62ee9dbff048 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.44.0 + 26.45.0 pom import @@ -52,6 +52,12 @@ com.google.cloud google-cloud-spanner-jdbc + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + org.apache.commons diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2d0ed281141a..d78984e3ff87 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.44.0 + 26.45.0 pom import @@ -37,6 +37,12 @@ com.google.cloud google-cloud-spanner-jdbc + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 733e571a1338..5a8b4861a5a3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.44.0 + 26.45.0 import pom @@ -62,7 +62,12 @@ com.google.cloud google-cloud-spanner-jdbc - 2.21.0 + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + org.postgresql diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 8a13c6bb8c03..624f8463490c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.44.0 + 26.45.0 import pom @@ -58,6 +58,12 @@ com.google.cloud google-cloud-spanner-jdbc + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + org.postgresql From b9f77c8b2db10a4a85c2ea3bc9aa3a2be008d984 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 31 Aug 2024 13:56:13 +0200 Subject: [PATCH 1399/1979] deps: update dependency org.apache.commons:commons-lang3 to v3.17.0 (#1735) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 62ee9dbff048..4c83a3f68fb7 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -62,7 +62,7 @@ org.apache.commons commons-lang3 - 3.16.0 + 3.17.0 com.fasterxml.jackson.core From d4815407a9467317092251cd1f3abf3bdd6e969e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 2 Sep 2024 08:56:16 +0200 Subject: [PATCH 1400/1979] feat: update DatabaseMetaData to include named schemas (#1733) --- .../cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 12 ++++++------ .../cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 7bafb2f37432..6cb6f3e0881b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -419,27 +419,27 @@ public String getCatalogSeparator() { @Override public boolean supportsSchemasInDataManipulation() { - return false; + return true; } @Override public boolean supportsSchemasInProcedureCalls() { - return false; + return true; } @Override public boolean supportsSchemasInTableDefinitions() { - return false; + return true; } @Override public boolean supportsSchemasInIndexDefinitions() { - return false; + return true; } @Override public boolean supportsSchemasInPrivilegeDefinitions() { - return false; + return true; } @Override @@ -602,7 +602,7 @@ public int getMaxIndexLength() { @Override public int getMaxSchemaNameLength() { - return 0; + return 128; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 64499f40a21a..193fc9605729 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -112,7 +112,7 @@ public void testTrivialMethods() throws SQLException { assertEquals(8000, meta.getMaxIndexLength()); assertEquals(0, meta.getMaxProcedureNameLength()); assertEquals(0, meta.getMaxRowSize()); - assertEquals(0, meta.getMaxSchemaNameLength()); + assertEquals(128, meta.getMaxSchemaNameLength()); assertEquals(1000000, meta.getMaxStatementLength()); assertEquals(0, meta.getMaxStatements()); assertEquals(128, meta.getMaxTableNameLength()); @@ -245,11 +245,11 @@ public void testTrivialMethods() throws SQLException { assertTrue(meta.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT)); assertFalse(meta.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT)); assertFalse(meta.supportsSavepoints()); - assertFalse(meta.supportsSchemasInDataManipulation()); - assertFalse(meta.supportsSchemasInIndexDefinitions()); - assertFalse(meta.supportsSchemasInPrivilegeDefinitions()); - assertFalse(meta.supportsSchemasInProcedureCalls()); - assertFalse(meta.supportsSchemasInTableDefinitions()); + assertTrue(meta.supportsSchemasInDataManipulation()); + assertTrue(meta.supportsSchemasInIndexDefinitions()); + assertTrue(meta.supportsSchemasInPrivilegeDefinitions()); + assertTrue(meta.supportsSchemasInProcedureCalls()); + assertTrue(meta.supportsSchemasInTableDefinitions()); assertFalse(meta.supportsSelectForUpdate()); assertFalse(meta.supportsStatementPooling()); assertFalse(meta.supportsStoredFunctionsUsingCallSyntax()); From 0050958fda41c9bafdd85e5be83279da66bd542d Mon Sep 17 00:00:00 2001 From: Joe Wang <106995533+JoeWang1127@users.noreply.github.com> Date: Tue, 10 Sep 2024 13:32:50 +0000 Subject: [PATCH 1401/1979] chore: remove owlbot check (#1743) --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index a259dc084052..f35f4721f0c2 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -36,7 +36,6 @@ branchProtectionRules: - "units (11)" - "Kokoro - Test: Integration" - "cla/google" - - OwlBot Post Processor - 'Kokoro - Test: Java GraalVM Native Image' - 'Kokoro - Test: Java 17 GraalVM Native Image' - javadoc From aac4cadb41fd65063d00755e7b3a2c997de0f774 Mon Sep 17 00:00:00 2001 From: Joe Wang <106995533+JoeWang1127@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:02:17 +0000 Subject: [PATCH 1402/1979] chore: disable owlbot (#1742) --- java-spanner-jdbc/.github/.OwlBot.lock.yaml | 17 -- java-spanner-jdbc/.github/.OwlBot.yaml | 16 -- .../.github/generated-files-bot.yml | 12 -- java-spanner-jdbc/.readme-partials.yaml | 146 ------------------ java-spanner-jdbc/codecov.yaml | 4 - java-spanner-jdbc/owlbot.py | 30 ---- java-spanner-jdbc/synth.metadata | 90 ----------- 7 files changed, 315 deletions(-) delete mode 100644 java-spanner-jdbc/.github/.OwlBot.lock.yaml delete mode 100644 java-spanner-jdbc/.github/.OwlBot.yaml delete mode 100644 java-spanner-jdbc/.github/generated-files-bot.yml delete mode 100644 java-spanner-jdbc/.readme-partials.yaml delete mode 100644 java-spanner-jdbc/codecov.yaml delete mode 100644 java-spanner-jdbc/owlbot.py delete mode 100644 java-spanner-jdbc/synth.metadata diff --git a/java-spanner-jdbc/.github/.OwlBot.lock.yaml b/java-spanner-jdbc/.github/.OwlBot.lock.yaml deleted file mode 100644 index 359fe71c1964..000000000000 --- a/java-spanner-jdbc/.github/.OwlBot.lock.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -docker: - image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:72f0d373307d128b2cb720c5cb4d90b31f0e86529dd138c632710ae0c69efae3 -# created: 2024-06-05T18:32:21.724930324Z diff --git a/java-spanner-jdbc/.github/.OwlBot.yaml b/java-spanner-jdbc/.github/.OwlBot.yaml deleted file mode 100644 index 54aca963f72c..000000000000 --- a/java-spanner-jdbc/.github/.OwlBot.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2021 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. - -docker: - image: "gcr.io/cloud-devrel-public-resources/owlbot-java:latest" \ No newline at end of file diff --git a/java-spanner-jdbc/.github/generated-files-bot.yml b/java-spanner-jdbc/.github/generated-files-bot.yml deleted file mode 100644 index c644a24e1129..000000000000 --- a/java-spanner-jdbc/.github/generated-files-bot.yml +++ /dev/null @@ -1,12 +0,0 @@ -externalManifests: -- type: json - file: 'synth.metadata' - jsonpath: '$.generatedFiles[*]' -- type: json - file: '.github/readme/synth.metadata/synth.metadata' - jsonpath: '$.generatedFiles[*]' -ignoreAuthors: -- 'renovate-bot' -- 'yoshi-automation' -- 'release-please[bot]' -- 'gcf-owl-bot[bot]' diff --git a/java-spanner-jdbc/.readme-partials.yaml b/java-spanner-jdbc/.readme-partials.yaml deleted file mode 100644 index 1ae28a88f135..000000000000 --- a/java-spanner-jdbc/.readme-partials.yaml +++ /dev/null @@ -1,146 +0,0 @@ -custom_content: | - ### Creating a JDBC Connection - - The following example shows how to create a JDBC connection to Cloud Spanner and execute a simple query. - - ```java - String projectId = "my-project"; - String instanceId = "my-instance"; - String databaseId = "my-database"; - - try (Connection connection = - DriverManager.getConnection( - String.format( - "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", - projectId, instanceId, databaseId))) { - try (Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { - while (rs.next()) { - System.out.printf( - "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); - } - } - } - } - ``` - - ### Connection URL Properties - - The Spanner JDBC driver supports the following connection URL properties. Note that all of - these can also be supplied in a Properties instance that is passed to the - `DriverManager#getConnection(String url, Properties properties)` method. - - #### Commonly Used Properties - - credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json` - - autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. - - readonly (boolean): Sets the initial readonly mode for the connection. Default is false. - - autoConfigEmulator (boolean): Automatically configure the connection to try to connect to the Cloud Spanner emulator. You do not need to specify any host or port in the connection string as long as the emulator is running on the default host/port (localhost:9010). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. This means that you do not need to execute any `gcloud` commands on the emulator to create the instance and database before you can connect to it. Example: `jdbc:cloudspanner:/projects/test-project/instances/test-instance/databases/test-db;autoConfigEmulator=true` - - usePlainText (boolean): Sets whether the JDBC connection should establish an unencrypted connection to a (local) server. This option can only be used when connecting to a local emulator that does not require an encrypted connection, and that does not require authentication. Example: `jdbc:cloudspanner://localhost:9010/projects/test-project/instances/test-instance/databases/test-db;usePlainText=true` - - optimizerVersion (String): Sets the default query optimizer version to use for this connection. See also https://cloud.google.com/spanner/docs/query-optimizer/query-optimizer-versions. - - enableExtendedTracing (boolean): Enables extended OpenTelemetry tracing of queries that are executed by a JDBC connection. When enabled, the SQL string of the query that is executed is added as a property to the trace. - - enableApiTracing (boolean): Enables API OpenTelemetry tracing of all RPCs that are executed by the JDBC driver. When enabled, a trace will be created for each RPC invocation that is executed by the JDBC driver. Enable this to investigate latency problems and/or RPCs that are being retried. - - #### Advanced Properties - - minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. - - maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. - - numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - - retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. - - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. - - ### OpenTelemetry Tracing - The Spanner JDBC driver supports OpenTelemetry tracing. You can configure the OpenTelemetry instance - that should be used in two ways: - 1. Register a global OpenTelemetry instance. This instance will automatically be picked up by the Spanner JDBC driver. - 2. Add an OpenTelemetry instance with the key `openTelemetry` to the `java.util.Properties` instance that is used to create the JDBC connection. - - By default, the traces that are generated by the Spanner JDBC driver do not include the SQL - statement. You can include the SQL statement with the traces by adding the property `enableExtendedTracing=true` - to the JDBC connection URL. - - #### Example Using Global OpenTelemetry - Create and register a global OpenTelemetry object before creating a JDBC connection. - See also the [Spring Data JDBC Sample](samples/spring-data-jdbc) for an example for how to - configure OpenTelemetry in combination with Spring Data. - - See [Latency Debugging Guide](documentation/latency-debugging-guide.md) for more information on how to use these traces. - - ```java - TraceConfiguration traceConfiguration = TraceConfiguration.builder().setProjectId("my-project").build(); - SpanExporter traceExporter = TraceExporter.createWithConfiguration(traceConfiguration); - OpenTelemetry openTelemetry = - OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder() - .setSampler(Sampler.traceIdRatioBased(0.05)) - .setResource( - Resource.builder() - .put("service.name", "my-unique-service-name") - .build()) - .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) - .build()) - .buildAndRegisterGlobal(); - String projectId = "my-project"; - String instanceId = "my-instance"; - String databaseId = "my-database"; - // Setting this to true instructs the JDBC driver to include the SQL statement with the traces. - boolean enableExtendedTracing = true; - // Enabling API tracing includes traces for each individual RPC invocation, including retries. - boolean enableApiTracing = true; - - try (Connection connection = - DriverManager.getConnection( - String.format( - "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?enableExtendedTracing=%s;enableApiTracing=%s", - projectId, instanceId, databaseId, enableExtendedTracing, enableApiTracing))) { - try (Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { - while (rs.next()) { - System.out.printf( - "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); - } - } - } - } - ``` - - #### Example Using an OpenTelemetry instance in Properties - Instead of registering a global `OpenTelemetry` object, you can also provide a specific instance - in the properties for a JDBC connection: - - ```java - Properties info = new Properties(); - info.put(JdbcDriver.OPEN_TELEMETRY_PROPERTY_KEY, openTelemetry); - info.put("enableExtendedTracing", String.valueOf(enableExtendedTracing)); - info.put("enableApiTracing", String.valueOf(enableApiTracing)); - - try (Connection connection = - DriverManager.getConnection( - String.format( - "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", - projectId, instanceId, databaseId))) { - try (Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { - while (rs.next()) { - System.out.printf( - "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); - } - } - } - } - ``` - - ### Jar with Dependencies - A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest - or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). - - ### Creating a Shaded Jar - - A jar with all dependencies included is automatically generated when you execute `mvn package`. - The dependencies in this jar are not shaded. To create a jar with shaded dependencies you must - activate the `shade` profile like this: - - ``` - mvn package -Pshade - ``` - \ No newline at end of file diff --git a/java-spanner-jdbc/codecov.yaml b/java-spanner-jdbc/codecov.yaml deleted file mode 100644 index 5724ea9478d7..000000000000 --- a/java-spanner-jdbc/codecov.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -codecov: - ci: - - source.cloud.google.com diff --git a/java-spanner-jdbc/owlbot.py b/java-spanner-jdbc/owlbot.py deleted file mode 100644 index d470606bff98..000000000000 --- a/java-spanner-jdbc/owlbot.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2018 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. - -"""This script is used to synthesize generated parts of this library.""" - -import synthtool.languages.java as java - -java.common_templates(excludes=[ - 'README.md', - '.github/release-please.yml', - '.github/sync-repo-settings.yaml', - '.github/blunderbuss.yml', - '.kokoro/nightly/integration.cfg', - '.kokoro/build.sh', - '.kokoro/requirements.in', - '.kokoro/requirements.txt', - '.kokoro/presubmit/graalvm-native.cfg', - '.kokoro/presubmit/graalvm-native-17.cfg' -]) diff --git a/java-spanner-jdbc/synth.metadata b/java-spanner-jdbc/synth.metadata deleted file mode 100644 index f877cda09f5f..000000000000 --- a/java-spanner-jdbc/synth.metadata +++ /dev/null @@ -1,90 +0,0 @@ -{ - "sources": [ - { - "git": { - "name": ".", - "remote": "https://github.com/googleapis/java-spanner-jdbc.git", - "sha": "ade66635bd24f9d3fb44867d7f883fc59eb5a2db" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "396d9b84a1e93880f5bf88b59ecd38a0a6dffc5e" - } - } - ], - "generatedFiles": [ - ".github/CODEOWNERS", - ".github/ISSUE_TEMPLATE/bug_report.md", - ".github/ISSUE_TEMPLATE/feature_request.md", - ".github/ISSUE_TEMPLATE/support_request.md", - ".github/PULL_REQUEST_TEMPLATE.md", - ".github/generated-files-bot.yml", - ".github/release-trigger.yml", - ".github/snippet-bot.yml", - ".github/trusted-contribution.yml", - ".github/workflows/approve-readme.yaml", - ".github/workflows/auto-release.yaml", - ".github/workflows/ci.yaml", - ".github/workflows/samples.yaml", - ".kokoro/build.bat", - ".kokoro/build.sh", - ".kokoro/coerce_logs.sh", - ".kokoro/common.cfg", - ".kokoro/common.sh", - ".kokoro/continuous/common.cfg", - ".kokoro/continuous/java8.cfg", - ".kokoro/dependencies.sh", - ".kokoro/nightly/common.cfg", - ".kokoro/nightly/integration.cfg", - ".kokoro/nightly/java11.cfg", - ".kokoro/nightly/java7.cfg", - ".kokoro/nightly/java8-osx.cfg", - ".kokoro/nightly/java8-win.cfg", - ".kokoro/nightly/java8.cfg", - ".kokoro/nightly/samples.cfg", - ".kokoro/populate-secrets.sh", - ".kokoro/presubmit/clirr.cfg", - ".kokoro/presubmit/common.cfg", - ".kokoro/presubmit/dependencies.cfg", - ".kokoro/presubmit/integration.cfg", - ".kokoro/presubmit/java11.cfg", - ".kokoro/presubmit/java7.cfg", - ".kokoro/presubmit/java8-osx.cfg", - ".kokoro/presubmit/java8-win.cfg", - ".kokoro/presubmit/java8.cfg", - ".kokoro/presubmit/linkage-monitor.cfg", - ".kokoro/presubmit/lint.cfg", - ".kokoro/presubmit/samples.cfg", - ".kokoro/readme.sh", - ".kokoro/release/bump_snapshot.cfg", - ".kokoro/release/common.cfg", - ".kokoro/release/common.sh", - ".kokoro/release/drop.cfg", - ".kokoro/release/drop.sh", - ".kokoro/release/promote.cfg", - ".kokoro/release/promote.sh", - ".kokoro/release/publish_javadoc.cfg", - ".kokoro/release/publish_javadoc.sh", - ".kokoro/release/publish_javadoc11.cfg", - ".kokoro/release/publish_javadoc11.sh", - ".kokoro/release/snapshot.cfg", - ".kokoro/release/snapshot.sh", - ".kokoro/release/stage.cfg", - ".kokoro/release/stage.sh", - ".kokoro/trampoline.sh", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.md", - "LICENSE", - "SECURITY.md", - "codecov.yaml", - "java.header", - "license-checks.xml", - "renovate.json", - "samples/install-without-bom/pom.xml", - "samples/pom.xml", - "samples/snapshot/pom.xml" - ] -} \ No newline at end of file From db0654de06ee10216b330275e650c976088c52be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 12 Sep 2024 10:05:01 +0200 Subject: [PATCH 1403/1979] docs: run MyBatis sample on the Emulator and add insert-or-update sample (#1737) * docs: run MyBatis sample on the Emulator Adds an option to the MyBatis sample to also run on the Spanner Emulator, and add a test run that uses this option. * chore: remove commented code * docs: add insert-or-update example * fix: set spanner.emulator property in test * fix: update copy-paste error --- .../workflows/spring-data-mybatis-sample.yaml | 2 +- .../samples/spring-data-mybatis/README.md | 15 +- .../samples/spring-data-mybatis/pom.xml | 12 +- .../cloud/spanner/sample/Application.java | 29 +++- .../spanner/sample/EmulatorInitializer.java | 55 ++++++ .../spanner/sample/mappers/SingerMapper.java | 21 +++ .../main/resources/application-cs.properties | 13 +- .../sample/ApplicationEmulatorTest.java | 31 ++++ .../cloud/spanner/sample/ApplicationTest.java | 159 +++++++++++++++++- .../test/resources/application-cs.properties | 9 - .../test/resources/application-pg.properties | 7 - .../src/test/resources/application.properties | 13 -- 12 files changed, 323 insertions(+), 43 deletions(-) create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java delete mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties delete mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties delete mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index 5267d6f599f2..b19a17290723 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -17,7 +17,7 @@ on: pull_request: name: spring-data-mybatis-sample jobs: - spring-data-jdbc: + spring-data-mybatis: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/README.md b/java-spanner-jdbc/samples/spring-data-mybatis/README.md index 02cf135d49bc..61dc46f48eeb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/README.md +++ b/java-spanner-jdbc/samples/spring-data-mybatis/README.md @@ -17,6 +17,7 @@ This sample shows: 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. +4. How to use the Spanner Emulator for development in combination with Spring Data. __NOTE__: This application does __not require PGAdapter__. Instead, it connects to Cloud Spanner PostgreSQL using the Cloud Spanner JDBC driver. @@ -58,13 +59,16 @@ The default profile is `cs`. You can change the default profile by modifying the ### 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 + `cs`, which runs the application on Cloud Spanner PostgreSQL. +2. The sample by default starts an instance of the Spanner Emulator together with the application and + runs the application against the emulator. +3. Modify the default profile in the [application.properties](src/main/resources/application.properties) + file to run the sample on an open-source PostgreSQL database. +4. 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`. +5. Run the application with `mvn spring-boot:run`. ### Main Application Components @@ -79,6 +83,9 @@ The main application components are: 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. +* [EmulatorInitializer.java](src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java): + This ApplicationListener automatically starts the Spanner emulator as a Docker container if the + sample has been configured to run on the emulator. * [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 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 624f8463490c..7da709105c43 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -39,6 +39,13 @@ import pom + + org.testcontainers + testcontainers-bom + 1.20.1 + import + pom + @@ -70,6 +77,10 @@ postgresql 42.7.4 + + org.testcontainers + testcontainers + com.google.collections @@ -94,7 +105,6 @@ junit junit 4.13.2 - test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java index 04286b5a9757..22d1ba2b2e19 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.sample; +import com.google.cloud.spanner.connection.SpannerPool; import com.google.cloud.spanner.sample.entities.Album; import com.google.cloud.spanner.sample.entities.Singer; import com.google.cloud.spanner.sample.entities.Track; @@ -23,6 +24,7 @@ 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 java.util.concurrent.ThreadLocalRandom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; @@ -34,7 +36,15 @@ 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(); + EmulatorInitializer emulatorInitializer = new EmulatorInitializer(); + try { + SpringApplication application = new SpringApplication(Application.class); + application.addListeners(emulatorInitializer); + application.run(args).close(); + } finally { + SpannerPool.closeSpannerPool(); + emulatorInitializer.stopEmulator(); + } } private final DatabaseSeeder databaseSeeder; @@ -129,5 +139,22 @@ public void run(String... args) { for (Singer singer : singerService.listSingersWithLastNameStartingWith("A", "B", "C")) { logger.info("\t{}", singer.getFullName()); } + + // Execute an insert-or-update for a Singer record. + // For this, we either get a random Singer from the database, or create a new Singer entity + // and assign it a random ID. + logger.info("Executing an insert-or-update statement for a Singer record"); + Singer singer; + if (ThreadLocalRandom.current().nextBoolean()) { + singer = singerMapper.getRandom(); + } else { + singer = new Singer(); + singer.setId(ThreadLocalRandom.current().nextLong()); + } + singer.setFirstName("Beatriz"); + singer.setLastName("Russel"); + singer.setActive(true); + // This executes an INSERT ... ON CONFLICT DO UPDATE statement. + singerMapper.insertOrUpdate(singer); } } diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java new file mode 100644 index 000000000000..ba2c57eb5d24 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java @@ -0,0 +1,55 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.sample; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; + +public class EmulatorInitializer + implements ApplicationListener { + private GenericContainer emulator; + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + ConfigurableEnvironment environment = event.getEnvironment(); + boolean useEmulator = + Boolean.TRUE.equals(environment.getProperty("spanner.emulator", Boolean.class)); + if (!useEmulator) { + return; + } + + emulator = + new GenericContainer<>(DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator")); + emulator.withImagePullPolicy(PullPolicy.alwaysPull()); + emulator.addExposedPort(9010); + emulator.setWaitStrategy(Wait.forListeningPorts(9010)); + emulator.start(); + + System.setProperty("spanner.endpoint", "//localhost:" + emulator.getMappedPort(9010)); + } + + public void stopEmulator() { + if (this.emulator != null) { + this.emulator.stop(); + } + } +} diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java index 7f55466fe8e8..e7a0c5f98f99 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java @@ -31,6 +31,9 @@ public interface SingerMapper { @Select("SELECT * FROM singers WHERE id = #{singerId}") Singer get(@Param("singerId") long singerId); + @Select("SELECT * FROM singers ORDER BY sha256(last_name::bytea) LIMIT 1") + Singer getRandom(); + @Select("SELECT * FROM singers ORDER BY last_name, first_name, id") List findAll(); @@ -47,6 +50,24 @@ public interface SingerMapper { @Options(useGeneratedKeys = true, keyProperty = "id,fullName") int insert(Singer singer); + /** + * Executes an insert-or-update statement for a Singer record. Note that the id must have been set + * manually on the Singer entity before calling this method, and that Spanner requires that all + * columns for the INSERT statement must also be included in the UPDATE statement, including the + * 'id' column. The statement only returns the 'fullName' property, because the 'id' is already + * known. + */ + @Insert( + "INSERT INTO singers (id, first_name, last_name, active) " + + "VALUES (#{id}, #{firstName}, #{lastName}, #{active}) " + + "ON CONFLICT (id) DO UPDATE SET " + + "id=excluded.id, " + + "first_name=excluded.first_name, " + + "last_name=excluded.last_name, " + + "active=excluded.active") + @Options(useGeneratedKeys = true, keyProperty = "fullName") + int insertOrUpdate(Singer singer); + /** Updates an existing singer and returns the generated full name. */ @Update( "UPDATE singers SET " diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties index cf70836d219b..602c8da7c517 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties @@ -1,9 +1,20 @@ # This profile uses a Cloud Spanner PostgreSQL database. +# The sample by default uses the Spanner emulator. +# Disable this flag to run the sample on a real Spanner instance. +spanner.emulator=true +# This property is automatically set to point to the Spanner emulator that is automatically +# started together with the application. It remains empty if the application is executed +# against a real Spanner instance. +spanner.endpoint= +# Used for testing +spanner.additional_properties= + +# Update these properties to match your project, instance, and 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.url=jdbc:cloudspanner:${spanner.endpoint}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database};dialect=POSTGRESQL;autoConfigEmulator=${spanner.emulator};${spanner.additional_properties} spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java new file mode 100644 index 000000000000..9c6c900a3949 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.sample; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ApplicationEmulatorTest { + + @Test + public void testRunApplicationOnEmulator() { + System.setProperty("spanner.emulator", "true"); + Application.main(new String[] {}); + } +} diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java index 677e086ecdb5..4a60d9339570 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -49,6 +49,7 @@ import com.google.spanner.v1.TypeAnnotationCode; import com.google.spanner.v1.TypeCode; import java.util.List; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.LongStream; @@ -56,7 +57,6 @@ 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 { @@ -352,6 +352,76 @@ public static void setupQueryResults() { .collect(Collectors.toList())) .build())); } + int singerIndex = ThreadLocalRandom.current().nextInt(INITIAL_SINGERS.size()); + Singer randomSinger = INITIAL_SINGERS.get(singerIndex); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("SELECT * FROM singers ORDER BY sha256(last_name::bytea) 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("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(singerIndex + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder().setStringValue(randomSinger.getLastName()).build()) + .addValues( + Value.newBuilder() + .setStringValue( + randomSinger.getFirstName() + " " + randomSinger.getLastName()) + .build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomSinger.getFirstName()).build()) + .build()) + .build())); + mockSpanner.putStatementResult( StatementResult.query( Statement.newBuilder( @@ -726,21 +796,98 @@ public static void setupQueryResults() { .build()) .collect(Collectors.toList())) .build())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT INTO singers (id, first_name, last_name, active) VALUES ($1, $2, $3, $4) ON CONFLICT (id) DO UPDATE SET id=excluded.id, first_name=excluded.first_name, last_name=excluded.last_name, active=excluded.active\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("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(ThreadLocalRandom.current().nextLong())) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues(Value.newBuilder().setStringValue("Russel").build()) + .addValues(Value.newBuilder().setStringValue("Beatriz Russel").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue("Beatriz").build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); } } @Test public void testRunApplication() { - System.setProperty("port", String.valueOf(getPort())); - SpringApplication.run(Application.class).close(); + System.setProperty("spanner.emulator", "false"); + System.setProperty("spanner.endpoint", "//localhost:" + getPort()); + System.setProperty("spanner.additional_properties", "usePlainText=true"); + Application.main(new String[] {}); assertEquals( - 39, + 40, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() - .filter(request -> !request.getSql().equals("SELECT 1")) + .filter( + request -> + !request.getSql().equals("SELECT 1") + && !request + .getSql() + .equals( + "SELECT * FROM singers ORDER BY sha256(last_name::bytea) LIMIT 1")) .count()); assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); - assertEquals(5, mockSpanner.countRequestsOfType(CommitRequest.class)); + assertEquals(6, mockSpanner.countRequestsOfType(CommitRequest.class)); // Verify that the service methods use transactions. String insertSingerSql = diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties deleted file mode 100644 index 05f7cfa92186..000000000000 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-cs.properties +++ /dev/null @@ -1,9 +0,0 @@ - -# 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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties deleted file mode 100644 index 894f63ebae0d..000000000000 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application-pg.properties +++ /dev/null @@ -1,7 +0,0 @@ - -# 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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties deleted file mode 100644 index a6900a8ef0c6..000000000000 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/resources/application.properties +++ /dev/null @@ -1,13 +0,0 @@ - -# 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 35139464f9a827265cf4a95d95623c7000dfff96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 12 Sep 2024 10:05:29 +0200 Subject: [PATCH 1404/1979] docs: simplify dialect detection in Spring Data JDBC sample (#1738) Simplify the dialect detection for the Spring Data JDBC sample to use the built-in function for getting the dialect of a Spanner database. --- .../spanner/sample/JdbcConfiguration.java | 51 ++++--------------- .../cloud/spanner/sample/ApplicationTest.java | 2 +- 2 files changed, 10 insertions(+), 43 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java index 5b7120196183..e0310420edd2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -16,17 +16,14 @@ package com.google.cloud.spanner.sample; -import com.google.cloud.spanner.jdbc.JdbcSqlException; -import com.google.rpc.Code; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import io.opentelemetry.api.OpenTelemetry; -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.ConnectionCallback; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; @@ -48,42 +45,12 @@ public Dialect jdbcDialect(@Nonnull NamedParameterJdbcOperations 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.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; + return Boolean.TRUE.equals( + operations.execute( + (ConnectionCallback) + connection -> + connection.isWrapperFor(CloudSpannerJdbcConnection.class) + && com.google.cloud.spanner.Dialect.POSTGRESQL.equals( + connection.unwrap(CloudSpannerJdbcConnection.class).getDialect()))); } } diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java index 49d6eec94f83..c597b75d5e3c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -817,7 +817,7 @@ public void testRunApplication() { SpringApplication.run(Application.class).close(); assertEquals( - 44, + 42, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() .filter(request -> !request.getSql().equals("SELECT 1")) .count()); From f6a3f309933e97f4969b3348c7bdd5a4b1a961f8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 12 Sep 2024 10:32:11 +0200 Subject: [PATCH 1405/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.42.1 (#1740) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5a8b4861a5a3..67b3fdb91499 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.41.0 + 1.42.1 pom import From dce40356e9986d3f7a05267bb363d46c84cbf058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 12 Sep 2024 10:46:16 +0200 Subject: [PATCH 1406/1979] docs: simplify dialect detection for MyBatis sample (#1739) --- .../spanner/sample/JdbcConfiguration.java | 51 ++++--------------- .../cloud/spanner/sample/ApplicationTest.java | 2 +- 2 files changed, 10 insertions(+), 43 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java index 2398add31a43..7480d80c0cbb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -16,12 +16,9 @@ package com.google.cloud.spanner.sample; -import com.google.cloud.spanner.jdbc.JdbcSqlException; -import com.google.rpc.Code; -import java.util.Objects; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.JdbcOperations; @Configuration @@ -29,42 +26,12 @@ 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; + return Boolean.TRUE.equals( + operations.execute( + (ConnectionCallback) + connection -> + connection.isWrapperFor(CloudSpannerJdbcConnection.class) + && com.google.cloud.spanner.Dialect.POSTGRESQL.equals( + connection.unwrap(CloudSpannerJdbcConnection.class).getDialect()))); } } diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java index 4a60d9339570..f0cc17f2f783 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -876,7 +876,7 @@ public void testRunApplication() { Application.main(new String[] {}); assertEquals( - 40, + 39, mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() .filter( request -> From e61159a1ff4613f8ea094429cce427b39caee7cb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Sep 2024 21:17:31 +0200 Subject: [PATCH 1407/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.49.0 (#1744) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f5f9085393c4..7923c65914f2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.48.0 + 2.49.0 test From e633f8e0d9301600e81b6259e52af41a3071572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 16 Sep 2024 08:50:52 +0200 Subject: [PATCH 1408/1979] chore: use default schema from Dialect (#1745) --- .../com/google/cloud/spanner/jdbc/JdbcConnection.java | 9 +-------- .../google/cloud/spanner/jdbc/JdbcConnectionTest.java | 2 ++ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index db692b7d109b..9b5d5e88e16e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -523,14 +523,7 @@ public String getSchema() throws SQLException { @Nonnull String getDefaultSchema() { - // TODO: Update to use getDialect()#getDefaultSchema() when available. - switch (getDialect()) { - case POSTGRESQL: - return "public"; - case GOOGLE_STANDARD_SQL: - default: - return ""; - } + return getDialect().getDefaultSchema(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index 5a9618e9acaf..a54c179b6053 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -738,6 +738,8 @@ public void testSchema() throws SQLException { // The default schema is the empty string for GoogleSQL databases. // The default schema is 'public' for PostgreSQL databases. assertEquals(connection.getDefaultSchema(), connection.getSchema()); + String expectedDefaultSchema = dialect == Dialect.POSTGRESQL ? "public" : ""; + assertEquals(expectedDefaultSchema, connection.getSchema()); // This should be allowed. connection.setSchema(connection.getDefaultSchema()); JdbcSqlExceptionImpl exception = From c27d3367036fc2060693a7e933d1ded7d8dcca73 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Sep 2024 09:31:22 +0200 Subject: [PATCH 1409/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.49.0 (#1747) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7923c65914f2..1c51148268dc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.48.0 + 2.49.0 test From 30e1543b1047a0f9146b8129f7742fd3b02b070b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Sep 2024 09:31:35 +0200 Subject: [PATCH 1410/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.4 (#1746) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 67b3fdb91499..514e001be40b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.3 + 2024.0.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 7da709105c43..44432bd959e6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.3 + 2024.0.4 import pom From 3eee6cd6f65314bbd6656cd24e2334bab60b9978 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Sep 2024 11:21:02 +0200 Subject: [PATCH 1411/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.35.0 (#1741) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 8d462abb5838..e916464b2f1a 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.34.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.35.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 53cd15405a61..ec11dece6110 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.34.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.35.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index e211e47fc692..85ab5c49b1ee 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.34.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.35.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1c51148268dc..806af3b872f2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.34.0 + 3.35.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4c83a3f68fb7..2f16ea14a3ba 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.34.0 + 3.35.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d78984e3ff87..bde9b58b07ef 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.34.0 + 3.35.0 From b82ca1f2072945229333407261ac3f57bc2b0c58 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 16 Sep 2024 11:55:57 +0200 Subject: [PATCH 1412/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.74.1 (#1748) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.74.1 * chore: update priority name --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 806af3b872f2..e6a246c12ac7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.74.0 + 6.74.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 514e001be40b..7f87fd913529 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.74.0 + 6.74.1 import pom diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java index 44a95e3dc9a2..837235698bfa 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcQueryOptionsTest.java @@ -153,7 +153,7 @@ public void testSetOptions() throws SQLException { try (java.sql.ResultSet rs = connection.createStatement().executeQuery("SHOW VARIABLE RPC_PRIORITY")) { assertThat(rs.next()).isTrue(); - assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("PRIORITY_UNSPECIFIED"); + assertThat(rs.getString("RPC_PRIORITY")).isEqualTo("UNSPECIFIED"); assertThat(rs.next()).isFalse(); } } From 35de2c5d6cbfd42e468e35442c242f2b840db080 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:51:38 +0200 Subject: [PATCH 1413/1979] chore(main): release 2.22.0 (#1732) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 26 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e48516502080..4f640b66533a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [2.22.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.21.0...v2.22.0) (2024-09-16) + + +### Features + +* Update DatabaseMetaData to include named schemas ([#1733](https://github.com/googleapis/java-spanner-jdbc/issues/1733)) ([b162e2a](https://github.com/googleapis/java-spanner-jdbc/commit/b162e2ad8fbcaff5c0453b20ac103cab3207a0d9)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.49.0 ([#1744](https://github.com/googleapis/java-spanner-jdbc/issues/1744)) ([25f7f61](https://github.com/googleapis/java-spanner-jdbc/commit/25f7f6104806e701ed884eaba60c676c24a0ce61)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.74.0 ([#1730](https://github.com/googleapis/java-spanner-jdbc/issues/1730)) ([c257ea5](https://github.com/googleapis/java-spanner-jdbc/commit/c257ea54b9cda17ca2f0b9f8ff77a854669314b5)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.74.1 ([#1748](https://github.com/googleapis/java-spanner-jdbc/issues/1748)) ([794ca47](https://github.com/googleapis/java-spanner-jdbc/commit/794ca4790cec8ef34c651593c7fadde366533fdb)) +* Update dependency com.google.cloud:google-cloud-trace to v2.49.0 ([#1747](https://github.com/googleapis/java-spanner-jdbc/issues/1747)) ([32defb7](https://github.com/googleapis/java-spanner-jdbc/commit/32defb7bddf3bdc91da3f131ba15ed665fef3004)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.35.0 ([#1741](https://github.com/googleapis/java-spanner-jdbc/issues/1741)) ([8e168eb](https://github.com/googleapis/java-spanner-jdbc/commit/8e168eb9bb1720f431b4f76d6ceda2d338c39715)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.42.1 ([#1740](https://github.com/googleapis/java-spanner-jdbc/issues/1740)) ([f229a62](https://github.com/googleapis/java-spanner-jdbc/commit/f229a6259a3c4fce001c26780d5182a32e7e5ffe)) +* Update dependency org.apache.commons:commons-lang3 to v3.17.0 ([#1735](https://github.com/googleapis/java-spanner-jdbc/issues/1735)) ([5dbf223](https://github.com/googleapis/java-spanner-jdbc/commit/5dbf22358c7d69481d8a568483ef340149e414c8)) +* Update dependency org.springframework.data:spring-data-bom to v2024.0.4 ([#1746](https://github.com/googleapis/java-spanner-jdbc/issues/1746)) ([e9d8cab](https://github.com/googleapis/java-spanner-jdbc/commit/e9d8cab337fbc3f3e0d98edd71bd42c9fe46b8b7)) + + +### Documentation + +* Run MyBatis sample on the Emulator and add insert-or-update sample ([#1737](https://github.com/googleapis/java-spanner-jdbc/issues/1737)) ([02534d7](https://github.com/googleapis/java-spanner-jdbc/commit/02534d72824a7a7ccb7756797163fa011d1e5e49)) +* Simplify dialect detection for MyBatis sample ([#1739](https://github.com/googleapis/java-spanner-jdbc/issues/1739)) ([01eade8](https://github.com/googleapis/java-spanner-jdbc/commit/01eade8bb6a59d169cb06e945dcf2c20be8a0c82)) +* Simplify dialect detection in Spring Data JDBC sample ([#1738](https://github.com/googleapis/java-spanner-jdbc/issues/1738)) ([44202fc](https://github.com/googleapis/java-spanner-jdbc/commit/44202fce324dafbc3538a3792986cbbaadf97209)) + ## [2.21.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.20.2...v2.21.0) (2024-08-23) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 80eb441524d5..3c482bac450e 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.21.0 + 2.22.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.21.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.22.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.21.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.22.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e6a246c12ac7..e72e08bdc978 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.21.1-SNAPSHOT + 2.22.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9b16873f8bfe..d8ac7520037f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.21.1-SNAPSHOT + 2.22.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 429e5f3bd7e5..74e8b7e5ec1d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.21.0:2.21.1-SNAPSHOT +google-cloud-spanner-jdbc:2.22.0:2.22.0 From de635e5cb2dce367ab2e288dc3a4c3c0226a438f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:57:51 +0200 Subject: [PATCH 1414/1979] chore(main): release 2.22.1-SNAPSHOT (#1749) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e72e08bdc978..7e7646cab765 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.22.0 + 2.22.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d8ac7520037f..84544c178c85 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.0 + 2.22.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 74e8b7e5ec1d..29e60fa63cda 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.22.0:2.22.0 +google-cloud-spanner-jdbc:2.22.0:2.22.1-SNAPSHOT From 6e907f69ddb8965828bcea66d649c87dcb1a0a0e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 15:58:11 +0200 Subject: [PATCH 1415/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.22.0 (#1750) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 252c079b14f9..d99c00fdb6b9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.21.0 + 2.22.0 From b580e8aca8c8f4d883be77169706213ee029b7d2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 16:30:47 +0200 Subject: [PATCH 1416/1979] chore(deps): update dependency com.google.cloud.samples:shared-configuration to v1.2.2 (#1753) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d99c00fdb6b9..9acebaf6ffec 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.2.0 + 1.2.2 diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index 39d5d24c8a61..bfe9954b2ed3 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -18,7 +18,7 @@ com.google.cloud.samples shared-configuration - 1.2.0 + 1.2.2 diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 84544c178c85..0fea3a2ef9a3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.2.0 + 1.2.2 From 58bed8216609428b5843cfd3927351bcedf3d8b2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 17:33:32 +0200 Subject: [PATCH 1417/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.47.0 (#1752) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2f16ea14a3ba..c9c8fb80efea 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.45.0 + 26.47.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index bde9b58b07ef..ccba64375690 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.45.0 + 26.47.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 7f87fd913529..55eb45c7d057 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.45.0 + 26.47.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 44432bd959e6..eddd3cde6bc3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.45.0 + 26.47.0 import pom From e1b75540bf356c6908a36616440d50c0511c3ff3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 17:33:47 +0200 Subject: [PATCH 1418/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.75.0 (#1757) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7e7646cab765..dfc2b8c5a630 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.74.1 + 6.75.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 55eb45c7d057..2d978f78e058 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.74.1 + 6.75.0 import pom From 5723c126863cec170717483b882c13b626d5a300 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 17:34:10 +0200 Subject: [PATCH 1419/1979] deps: update dependency org.springframework.boot:spring-boot to v3.3.4 (#1754) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index c9c8fb80efea..ff908a21e8ed 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.3.3 + 3.3.4 test From 66b67cd49b760449bd7ccd4c2f6ff2366648b5ed Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 17:35:50 +0200 Subject: [PATCH 1420/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.4 (#1756) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index eddd3cde6bc3..0014a467426b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.3 + 3.3.4 From 8e43f9b8cdb6640c69c46260c4a51d160dce1740 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Sep 2024 17:36:08 +0200 Subject: [PATCH 1421/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.4 (#1755) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2d978f78e058..1d63b59676d3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.3 + 3.3.4 From 7aa9df6acdc3c4390ca1f56edace9ce3d71cea74 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Sep 2024 11:06:57 +0200 Subject: [PATCH 1422/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.36.0 (#1759) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index e916464b2f1a..f441d76c97ad 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.35.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.36.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index ec11dece6110..1f52e93ed7ae 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.35.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.36.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 85ab5c49b1ee..bf7743f744f8 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.35.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.36.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dfc2b8c5a630..287c52a0dd93 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.35.0 + 3.36.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ff908a21e8ed..9116241fb7d8 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.35.0 + 3.36.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ccba64375690..bd3ad7560b38 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.35.0 + 3.36.0 From f2a51101d684a354b9816246b48d4535f8654fa3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Sep 2024 11:07:25 +0200 Subject: [PATCH 1423/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.32.0 (#1760) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 287c52a0dd93..869a1b1772cb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.31.0 + 0.32.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 1d63b59676d3..7792b6230ebc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.31.0 + 0.32.0 From 31d43603f73ee0e35053bedacd5336db414b2e8f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Sep 2024 18:23:57 +0200 Subject: [PATCH 1424/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.36.1 (#1761) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index f441d76c97ad..cc7985420ce8 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.36.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.36.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 1f52e93ed7ae..0effa03c5227 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.36.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.36.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index bf7743f744f8..96a8059b9b9b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.36.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.36.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 869a1b1772cb..3d9158c76521 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.36.0 + 3.36.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 9116241fb7d8..2e663a66d98c 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.36.0 + 3.36.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index bd3ad7560b38..c3783dbdc945 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.36.0 + 3.36.1 From d7d51c8a6798ff429d294d4efb2d67b945ff47db Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Sep 2024 18:24:19 +0200 Subject: [PATCH 1425/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.0 (#1762) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2e663a66d98c..304f8697d475 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.17.2 + 2.18.0 From 75c7637243ba4d3e6a840bff9115f9bbff880e77 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 30 Sep 2024 16:47:47 +0200 Subject: [PATCH 1426/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.76.0 (#1764) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3d9158c76521..e08f2de4f90e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.75.0 + 6.76.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 7792b6230ebc..a3590477e296 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.75.0 + 6.76.0 import pom From dc5e65719f2292f22fb4e8eb635661a461605077 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 30 Sep 2024 17:02:52 +0200 Subject: [PATCH 1427/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.51.0 (#1765) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e08f2de4f90e..38ab38770d5f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.49.0 + 2.51.0 test From c23197c5b1aa4f6644ee9233c3707c48699a1527 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 30 Sep 2024 17:04:27 +0200 Subject: [PATCH 1428/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.51.0 (#1766) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 38ab38770d5f..83f95b6e0f48 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.49.0 + 2.51.0 test From b3b158478a0520a0579c4a51c9e6bf6f51d16619 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 30 Sep 2024 17:04:46 +0200 Subject: [PATCH 1429/1979] deps: update dependency net.datafaker:datafaker to v2.4.0 (#1767) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 304f8697d475..6a8c4ac070b8 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -38,7 +38,7 @@ net.datafaker datafaker - 2.3.1 + 2.4.0 com.google.cloud From ceeabbc941d098e6886ce53ef3c5993eb4fdc43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 1 Oct 2024 09:45:25 +0200 Subject: [PATCH 1430/1979] fix: remove connection-id from metrics (#1763) * fix: remove connection-id from metrics The OpenTelemetry metrics that were gathered by the JDBC driver also included a unique Connection ID for each connection. This creats too many time series. * chore: run code formatter --- .../cloud/spanner/jdbc/JdbcConnection.java | 16 +++-- .../spanner/jdbc/it/ITOpenTelemetryTest.java | 64 ++++++++++++++++--- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 9b5d5e88e16e..26b381dd27a5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -91,14 +91,14 @@ class JdbcConnection extends AbstractJdbcConnection { private final Metrics metrics; - private final Attributes openTelemetryAttributes; + private final Attributes openTelemetryMetricsAttributes; JdbcConnection(String connectionUrl, ConnectionOptions options) throws SQLException { super(connectionUrl, options); this.useLegacyIsValidCheck = useLegacyValidCheck(); OpenTelemetry openTelemetry = getSpanner().getOptions().getOpenTelemetry(); - this.openTelemetryAttributes = - createOpenTelemetryAttributes(getConnectionOptions().getDatabaseId()); + this.openTelemetryMetricsAttributes = + createOpenTelemetryAttributes(getConnectionOptions().getDatabaseId(), false); this.metrics = new Metrics(openTelemetry); } @@ -114,9 +114,13 @@ static boolean useLegacyValidCheck() { } @VisibleForTesting - static Attributes createOpenTelemetryAttributes(DatabaseId databaseId) { + static Attributes createOpenTelemetryAttributes( + DatabaseId databaseId, boolean includeConnectionId) { AttributesBuilder attributesBuilder = Attributes.builder(); - attributesBuilder.put("connection_id", UUID.randomUUID().toString()); + // A unique connection ID should only be included for tracing and not for metrics. + if (includeConnectionId) { + attributesBuilder.put("connection_id", UUID.randomUUID().toString()); + } attributesBuilder.put("database", databaseId.getDatabase()); attributesBuilder.put("instance_id", databaseId.getInstanceId().getInstance()); attributesBuilder.put("project_id", databaseId.getInstanceId().getProject()); @@ -124,7 +128,7 @@ static Attributes createOpenTelemetryAttributes(DatabaseId databaseId) { } public void recordClientLibLatencyMetric(long value) { - metrics.recordClientLibLatency(value, openTelemetryAttributes); + metrics.recordClientLibLatency(value, openTelemetryMetricsAttributes); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java index bbbbaf344a76..83cfab81c9ff 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java @@ -51,8 +51,14 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import org.junit.AfterClass; @@ -125,21 +131,21 @@ public void setup() { } @Test - public void testGlobalOpenTelemetry() throws SQLException, IOException, InterruptedException { + public void testGlobalOpenTelemetry() throws Exception { GlobalOpenTelemetry.resetForTest(); GlobalOpenTelemetry.set(openTelemetry); Properties info = new Properties(); info.put("enableExtendedTracing", "true"); try (Connection connection = createConnection(env, database, info)) { testOpenTelemetry(connection); + testOpenTelemetryConcurrency(() -> createConnection(env, database, info)); } finally { GlobalOpenTelemetry.resetForTest(); } } @Test - public void testOpenTelemetryInProperties() - throws SQLException, IOException, InterruptedException { + public void testOpenTelemetryInProperties() throws Exception { // Make sure there is no Global OpenTelemetry. GlobalOpenTelemetry.resetForTest(); Properties info = new Properties(); @@ -148,6 +154,7 @@ public void testOpenTelemetryInProperties() try (Connection connection = createConnection(env, database, info)) { testOpenTelemetry(connection); } + testOpenTelemetryConcurrency(() -> createConnection(env, database, info)); } private void testOpenTelemetry(Connection connection) @@ -159,14 +166,14 @@ private void testOpenTelemetry(Connection connection) // Test executeQuery(String) try (ResultSet resultSet = statement.executeQuery(sql)) { - assertQueryResult(resultSet, sql, uuid); + assertQueryResult(resultSet, sql, uuid, true); } // Test execute(String) uuid = UUID.randomUUID(); sql = "select '" + uuid + "'"; assertTrue(statement.execute(sql)); - assertQueryResult(statement.getResultSet(), sql, uuid); + assertQueryResult(statement.getResultSet(), sql, uuid, true); // Test executeUpdate(String) uuid = UUID.randomUUID(); @@ -189,7 +196,7 @@ private void testOpenTelemetry(Connection connection) String sql = "select '" + uuid + "'"; try (PreparedStatement statement = connection.prepareStatement(sql)) { try (ResultSet resultSet = statement.executeQuery()) { - assertQueryResult(resultSet, sql, uuid); + assertQueryResult(resultSet, sql, uuid, true); } } @@ -197,7 +204,7 @@ private void testOpenTelemetry(Connection connection) sql = "select '" + uuid + "'"; try (PreparedStatement statement = connection.prepareStatement(sql)) { assertTrue(statement.execute()); - assertQueryResult(statement.getResultSet(), sql, uuid); + assertQueryResult(statement.getResultSet(), sql, uuid, true); } uuid = UUID.randomUUID(); @@ -217,14 +224,53 @@ private void testOpenTelemetry(Connection connection) } } - private void assertQueryResult(ResultSet resultSet, String sql, UUID uuid) + private interface ConnectionProducer { + Connection createConnection() throws SQLException; + } + + private void testOpenTelemetryConcurrency(ConnectionProducer connectionProducer) + throws Exception { + int numThreads = 16; + int numIterations = 1000; + ExecutorService executor = Executors.newFixedThreadPool(16); + List> futures = new ArrayList<>(numThreads); + for (int n = 0; n < numThreads; n++) { + futures.add( + executor.submit( + (Callable) + () -> { + try (Connection connection = connectionProducer.createConnection(); + Statement statement = connection.createStatement()) { + for (int i = 0; i < numIterations; i++) { + UUID uuid = UUID.randomUUID(); + String sql = "select '" + uuid + "'"; + + try (ResultSet resultSet = statement.executeQuery(sql)) { + assertQueryResult(resultSet, sql, uuid, false); + } + } + } + return null; + })); + } + executor.shutdown(); + assertTrue(executor.awaitTermination(600L, TimeUnit.SECONDS)); + for (Future future : futures) { + // Just verify that we did not get an exception. + future.get(); + } + } + + private void assertQueryResult(ResultSet resultSet, String sql, UUID uuid, boolean assertTrace) throws SQLException, IOException, InterruptedException { assertTrue(resultSet.next()); assertEquals(uuid.toString(), resultSet.getString(1)); assertFalse(resultSet.next()); flushOpenTelemetry(); - assertTrace(sql); + if (assertTrace) { + assertTrace(sql); + } } private void assertUpdateResult(long updateCount, String sql) From 2881af995910eb12f02e3579403ec47353434927 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Oct 2024 21:29:05 +0200 Subject: [PATCH 1431/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.2 (#1768) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 83f95b6e0f48..4b5bd62be5e3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.1 + 1.20.2 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6a8c4ac070b8..99466d2b0ba9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.1 + 1.20.2 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c3783dbdc945..380654c479b7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.1 + 1.20.2 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a3590477e296..e093ceeb6b3d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -114,7 +114,7 @@ org.testcontainers testcontainers - 1.20.1 + 1.20.2 test From 5166f563baf763caf8a9f27314379ff247ebffea Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Oct 2024 21:29:20 +0200 Subject: [PATCH 1432/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.20.2 (#1769) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 0014a467426b..1854d7828bba 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.1 + 1.20.2 import pom From b0caecd7d0822e211275df302c2da7495aff2cb4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 3 Oct 2024 06:52:23 +0200 Subject: [PATCH 1433/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.77.0 (#1771) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-bom](https://redirect.github.com/googleapis/java-spanner) | `6.76.0` -> `6.77.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.77.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.77.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.76.0/6.77.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.76.0/6.77.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.77.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6770-2024-10-02) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.76.0...v6.77.0) ##### Features - Add INTERVAL API ([c078ac3](https://redirect.github.com/googleapis/java-spanner/commit/c078ac34c3d14b13bbd4a507de4f0013975dca4e)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-monitoring-v3 to v3.52.0 ([#​3291](https://redirect.github.com/googleapis/java-spanner/issues/3291)) ([9241063](https://redirect.github.com/googleapis/java-spanner/commit/92410638b0ba88f8e89e28bd12dd58830f7aaeb3)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.52.0 ([#​3292](https://redirect.github.com/googleapis/java-spanner/issues/3292)) ([da27a19](https://redirect.github.com/googleapis/java-spanner/commit/da27a1992e40b1b4591f0232f687d8031387e749)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.52.0 ([#​3293](https://redirect.github.com/googleapis/java-spanner/issues/3293)) ([c6dbdb2](https://redirect.github.com/googleapis/java-spanner/commit/c6dbdb255eb4cd231a2dc7cef94bf3353fa7e837)) - Update dependency com.google.cloud:google-cloud-trace to v2.51.0 ([#​3294](https://redirect.github.com/googleapis/java-spanner/issues/3294)) ([a269747](https://redirect.github.com/googleapis/java-spanner/commit/a269747889ea0b2380f07e1efef3b288a9c4fd04)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.36.1 ([#​3355](https://redirect.github.com/googleapis/java-spanner/issues/3355)) ([5191e71](https://redirect.github.com/googleapis/java-spanner/commit/5191e71a83a316b41564ce2604980c8f33135f2f)) - Update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.32.0 ([#​3371](https://redirect.github.com/googleapis/java-spanner/issues/3371)) ([d5b5ca0](https://redirect.github.com/googleapis/java-spanner/commit/d5b5ca0cccc6cf73d759245d2bd72f33c7d39830)) - Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.32.0 ([#​3372](https://redirect.github.com/googleapis/java-spanner/issues/3372)) ([aa9a71d](https://redirect.github.com/googleapis/java-spanner/commit/aa9a71d38dabd8d1974bb553761e93735ade5c26)) - Update dependency commons-io:commons-io to v2.17.0 ([#​3349](https://redirect.github.com/googleapis/java-spanner/issues/3349)) ([7c21164](https://redirect.github.com/googleapis/java-spanner/commit/7c21164f2b8e75afab268f2fb8e132a372ac0d67)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.42.1 ([#​3323](https://redirect.github.com/googleapis/java-spanner/issues/3323)) ([95dfc02](https://redirect.github.com/googleapis/java-spanner/commit/95dfc02ae2d65f99219dcced66cf4e74d1c4975b)) - Update dependency ubuntu to v24 ([#​3356](https://redirect.github.com/googleapis/java-spanner/issues/3356)) ([042c294](https://redirect.github.com/googleapis/java-spanner/commit/042c294cc5f83eebd2e3600cffb165e5b467d63e)) - Update googleapis/sdk-platform-java action to v2.46.1 ([#​3354](https://redirect.github.com/googleapis/java-spanner/issues/3354)) ([378f5cf](https://redirect.github.com/googleapis/java-spanner/commit/378f5cfb08d4e5ee80b21007bfc829de61bfbdbe)) - Update junixsocket.version to v2.10.1 ([#​3367](https://redirect.github.com/googleapis/java-spanner/issues/3367)) ([5f94915](https://redirect.github.com/googleapis/java-spanner/commit/5f94915941c4e4132f8460a04dde0643fa63ab99)) - Update opentelemetry.version to v1.42.1 ([#​3330](https://redirect.github.com/googleapis/java-spanner/issues/3330)) ([7b05e43](https://redirect.github.com/googleapis/java-spanner/commit/7b05e4301953364617691e8ae225cea823e3a323)) ##### Documentation - Update comment for PROFILE QueryMode ([c078ac3](https://redirect.github.com/googleapis/java-spanner/commit/c078ac34c3d14b13bbd4a507de4f0013975dca4e))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4b5bd62be5e3..16f60c43b357 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.76.0 + 6.77.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e093ceeb6b3d..a4d075144fed 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.76.0 + 6.77.0 import pom From b8eb1559342a25162eed81813a39de451efb8e26 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:28:03 +0200 Subject: [PATCH 1434/1979] chore(main): release 2.22.1 (#1758) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 26 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4f640b66533a..e64db9c2e8e5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [2.22.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.22.0...v2.22.1) (2024-10-03) + + +### Bug Fixes + +* Remove connection-id from metrics ([#1763](https://github.com/googleapis/java-spanner-jdbc/issues/1763)) ([0e54363](https://github.com/googleapis/java-spanner-jdbc/commit/0e543635d2deb1ddb133e57604adc9f88bae4dbf)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.0 ([#1762](https://github.com/googleapis/java-spanner-jdbc/issues/1762)) ([c1fa2c3](https://github.com/googleapis/java-spanner-jdbc/commit/c1fa2c34fbc6b12ca8d602a48bb02eea4fa62b2a)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.51.0 ([#1765](https://github.com/googleapis/java-spanner-jdbc/issues/1765)) ([30f22dd](https://github.com/googleapis/java-spanner-jdbc/commit/30f22ddb75c531098a04171048e38647a1a49aec)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.75.0 ([#1757](https://github.com/googleapis/java-spanner-jdbc/issues/1757)) ([02dac46](https://github.com/googleapis/java-spanner-jdbc/commit/02dac46299b566c30d8399585c2d22b0ac2a4d59)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.76.0 ([#1764](https://github.com/googleapis/java-spanner-jdbc/issues/1764)) ([3fc8344](https://github.com/googleapis/java-spanner-jdbc/commit/3fc83449f93f7a0a4604751fe9d6326242b107d9)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.77.0 ([#1771](https://github.com/googleapis/java-spanner-jdbc/issues/1771)) ([4050b9c](https://github.com/googleapis/java-spanner-jdbc/commit/4050b9c2dedd2a40dac628ad82a414d9e68ae1ba)) +* Update dependency com.google.cloud:google-cloud-trace to v2.51.0 ([#1766](https://github.com/googleapis/java-spanner-jdbc/issues/1766)) ([9b04219](https://github.com/googleapis/java-spanner-jdbc/commit/9b042197c20be094930c087f7ff674f28a8d5980)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.36.0 ([#1759](https://github.com/googleapis/java-spanner-jdbc/issues/1759)) ([7276ea5](https://github.com/googleapis/java-spanner-jdbc/commit/7276ea5e8358170304ad55d28cee5cd5167fb56d)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.36.1 ([#1761](https://github.com/googleapis/java-spanner-jdbc/issues/1761)) ([add2a22](https://github.com/googleapis/java-spanner-jdbc/commit/add2a2239705e6447b729008aca09fb71e2609f6)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.32.0 ([#1760](https://github.com/googleapis/java-spanner-jdbc/issues/1760)) ([7768a6b](https://github.com/googleapis/java-spanner-jdbc/commit/7768a6b2c0c744ae6a36d222e798dfc8faaf634d)) +* Update dependency net.datafaker:datafaker to v2.4.0 ([#1767](https://github.com/googleapis/java-spanner-jdbc/issues/1767)) ([7b2d639](https://github.com/googleapis/java-spanner-jdbc/commit/7b2d639b8e0834b7bec359d8f0fe234b228323dd)) +* Update dependency org.springframework.boot:spring-boot to v3.3.4 ([#1754](https://github.com/googleapis/java-spanner-jdbc/issues/1754)) ([a3f10d7](https://github.com/googleapis/java-spanner-jdbc/commit/a3f10d7faa313d9ec924fe03575c7a114d2d9d35)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.4 ([#1755](https://github.com/googleapis/java-spanner-jdbc/issues/1755)) ([ccf5c3c](https://github.com/googleapis/java-spanner-jdbc/commit/ccf5c3c3b31358029392a11d9f58dffec62212fd)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.4 ([#1756](https://github.com/googleapis/java-spanner-jdbc/issues/1756)) ([6515992](https://github.com/googleapis/java-spanner-jdbc/commit/65159923685836bfd0416b16eae01a0b9bbd0b55)) +* Update dependency org.testcontainers:testcontainers to v1.20.2 ([#1768](https://github.com/googleapis/java-spanner-jdbc/issues/1768)) ([bb65d4f](https://github.com/googleapis/java-spanner-jdbc/commit/bb65d4f7b57918edb28013c41a35efbdb8513b56)) +* Update dependency org.testcontainers:testcontainers-bom to v1.20.2 ([#1769](https://github.com/googleapis/java-spanner-jdbc/issues/1769)) ([7d32ed7](https://github.com/googleapis/java-spanner-jdbc/commit/7d32ed7dadb01c53f2962b90ffa62b904c78db7c)) + ## [2.22.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.21.0...v2.22.0) (2024-09-16) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 3c482bac450e..34a80deadbfa 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.22.0 + 2.22.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.22.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.22.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.22.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.22.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 16f60c43b357..9449f722ab8a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.22.1-SNAPSHOT + 2.22.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0fea3a2ef9a3..53ebd707fcdc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.1-SNAPSHOT + 2.22.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 29e60fa63cda..5aa42cee5c79 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.22.0:2.22.1-SNAPSHOT +google-cloud-spanner-jdbc:2.22.1:2.22.1 From 5821e29c9aee7ccea18f1695c8bc68d11450592b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:02:49 +0200 Subject: [PATCH 1435/1979] chore(main): release 2.22.2-SNAPSHOT (#1772) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9449f722ab8a..7c3121a4982e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.22.1 + 2.22.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 53ebd707fcdc..f7cb0214e6e7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.1 + 2.22.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5aa42cee5c79..894c1a0cdabc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.22.1:2.22.1 +google-cloud-spanner-jdbc:2.22.1:2.22.2-SNAPSHOT From da0f619b91bab758b52c611daf0147cd8bd81b6f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 3 Oct 2024 14:03:01 +0200 Subject: [PATCH 1436/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.22.1 (#1773) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9acebaf6ffec..70c163d82a32 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.0 + 2.22.1 From 3e8f51e354f16972832477e5dcd2036dd855432b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 4 Oct 2024 12:52:24 +0200 Subject: [PATCH 1437/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.48.0 (#1774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.47.0` -> `26.48.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.47.0/26.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.47.0/26.48.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.48.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26480-2024-10-03) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.47.0...v26.48.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.36.1 ([#​6763](https://redirect.github.com/googleapis/java-cloud-bom/issues/6763)) ([77afd40](https://redirect.github.com/googleapis/java-cloud-bom/commit/77afd40862b5b36ed803995a55c3767f21c17925)) - update dependency com.google.cloud:gapic-libraries-bom to v1.45.0 ([#​6774](https://redirect.github.com/googleapis/java-cloud-bom/issues/6774)) ([a224091](https://redirect.github.com/googleapis/java-cloud-bom/commit/a224091eb130b684e1f908bd2b43902b9118e20b)) - update dependency com.google.cloud:google-cloud-bigquery to v2.42.4 ([#​6770](https://redirect.github.com/googleapis/java-cloud-bom/issues/6770)) ([c03a54a](https://redirect.github.com/googleapis/java-cloud-bom/commit/c03a54a69fc031766865579ba029b231a106c68b)) - update dependency com.google.cloud:google-cloud-bigquery to v2.43.0 ([#​6780](https://redirect.github.com/googleapis/java-cloud-bom/issues/6780)) ([0f6b4f4](https://redirect.github.com/googleapis/java-cloud-bom/commit/0f6b4f45f9a6fe7dc8234ed9d5e75ba907cfa74b)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.9.2 ([#​6771](https://redirect.github.com/googleapis/java-cloud-bom/issues/6771)) ([97a7ff0](https://redirect.github.com/googleapis/java-cloud-bom/commit/97a7ff084610a230ecea621991de324d1a86fe87)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.44.1 ([#​6769](https://redirect.github.com/googleapis/java-cloud-bom/issues/6769)) ([3d567f5](https://redirect.github.com/googleapis/java-cloud-bom/commit/3d567f5c32dd75f9d6e670a8c98a60d3daa1fb02)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.22.0 ([#​6775](https://redirect.github.com/googleapis/java-cloud-bom/issues/6775)) ([3aed099](https://redirect.github.com/googleapis/java-cloud-bom/commit/3aed0998d6b962da0372038ff72aff974a1b8ff2)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.26.5 ([#​6768](https://redirect.github.com/googleapis/java-cloud-bom/issues/6768)) ([3a1c7c2](https://redirect.github.com/googleapis/java-cloud-bom/commit/3a1c7c2f6f36a3fe647336dfb0910f96271c4667)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.20.3 ([#​6777](https://redirect.github.com/googleapis/java-cloud-bom/issues/6777)) ([e648e82](https://redirect.github.com/googleapis/java-cloud-bom/commit/e648e82d45863d655b3bbea339794b74efd775f6)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.13-alpha ([#​6781](https://redirect.github.com/googleapis/java-cloud-bom/issues/6781)) ([0cd97b7](https://redirect.github.com/googleapis/java-cloud-bom/commit/0cd97b7151b36465390bd5e31d017ec015a4bae9)) - update dependency com.google.cloud:google-cloud-nio to v0.127.24 ([#​6778](https://redirect.github.com/googleapis/java-cloud-bom/issues/6778)) ([8a7988d](https://redirect.github.com/googleapis/java-cloud-bom/commit/8a7988ddad1bbdc1c27d030f3305e9fe47b16a1e)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.132.3 ([#​6767](https://redirect.github.com/googleapis/java-cloud-bom/issues/6767)) ([8ed4f05](https://redirect.github.com/googleapis/java-cloud-bom/commit/8ed4f0523b818fa7ac7ff75c9fc2506a6d6c5256)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.132.4 ([#​6776](https://redirect.github.com/googleapis/java-cloud-bom/issues/6776)) ([f00726b](https://redirect.github.com/googleapis/java-cloud-bom/commit/f00726b73ea820f81bba4d1af872269882bdc2ef)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.133.0 ([#​6779](https://redirect.github.com/googleapis/java-cloud-bom/issues/6779)) ([ffe8e37](https://redirect.github.com/googleapis/java-cloud-bom/commit/ffe8e37c2ca2d7d2068572fd30d91d6a6dc786f1)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.14.3 ([#​6773](https://redirect.github.com/googleapis/java-cloud-bom/issues/6773)) ([5424d5d](https://redirect.github.com/googleapis/java-cloud-bom/commit/5424d5df207a70df386a9eadd51d75a0af253458)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.76.0 ([#​6762](https://redirect.github.com/googleapis/java-cloud-bom/issues/6762)) ([d1846f7](https://redirect.github.com/googleapis/java-cloud-bom/commit/d1846f77320d415c947fc80a0b98063547a79c3b)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.77.0 ([#​6783](https://redirect.github.com/googleapis/java-cloud-bom/issues/6783)) ([a979ad3](https://redirect.github.com/googleapis/java-cloud-bom/commit/a979ad3a2d7602f31a137b0fb18fed016f3c80d0)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.22.1 ([#​6784](https://redirect.github.com/googleapis/java-cloud-bom/issues/6784)) ([cfff92d](https://redirect.github.com/googleapis/java-cloud-bom/commit/cfff92df9351470235a7519c3fe35f6a097fab9c)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.43.1 ([#​6766](https://redirect.github.com/googleapis/java-cloud-bom/issues/6766)) ([7589d67](https://redirect.github.com/googleapis/java-cloud-bom/commit/7589d676116a555460ae2da0ac9d3e17f4962b15)) - update dependency commons-io:commons-io to v2.17.0 ([#​6758](https://redirect.github.com/googleapis/java-cloud-bom/issues/6758)) ([6f2fe9b](https://redirect.github.com/googleapis/java-cloud-bom/commit/6f2fe9bb75c5212f5a6058e93c4a67f4ccc66d84)) - update dependency ubuntu to v24 ([#​6765](https://redirect.github.com/googleapis/java-cloud-bom/issues/6765)) ([8faee82](https://redirect.github.com/googleapis/java-cloud-bom/commit/8faee82da6aca1b33b10604c247fb1e25da6034f))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 99466d2b0ba9..e4cfbb20be34 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.47.0 + 26.48.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 380654c479b7..91ea57a45ee6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.47.0 + 26.48.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a4d075144fed..13e4887593fe 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.47.0 + 26.48.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 1854d7828bba..3838d128272f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.47.0 + 26.48.0 import pom From bc2c85d0332699075af312b39682045adb961942 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 19:55:34 +0200 Subject: [PATCH 1438/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.52.0 (#1780) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7c3121a4982e..3688d03f39b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.51.0 + 2.52.0 test From eb2b3bb1b8fb2813b52c9cc2b67d9aa3271367ac Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 19:55:47 +0200 Subject: [PATCH 1439/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.52.0 (#1779) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3688d03f39b5..457cf1d1b4a6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.51.0 + 2.52.0 test From 91e3f2d31b74209799ae62856578ab27382f32f5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 19:56:05 +0200 Subject: [PATCH 1440/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.33.0 (#1778) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 457cf1d1b4a6..f9c3b63456ee 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.32.0 + 0.33.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 13e4887593fe..5b481dad47f4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.32.0 + 0.33.0 From 5d133009bcb2c9ccc38749662379820ed4443319 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 19:57:26 +0200 Subject: [PATCH 1441/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.25 (#1776) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5b481dad47f4..8fd3ef42e0ff 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -124,7 +124,7 @@ com.spotify.fmt fmt-maven-plugin - 2.24 + 2.25 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 3838d128272f..97545b6b9b95 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -113,7 +113,7 @@ com.spotify.fmt fmt-maven-plugin - 2.24 + 2.25 From c43769e53687fe37d73bfbe7f38cd10bfe69f29f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 20:20:23 +0200 Subject: [PATCH 1442/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.43.0 (#1782) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://redirect.github.com/open-telemetry/opentelemetry-java) | `1.42.1` -> `1.43.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.42.1/1.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.42.1/1.43.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.43.0`](https://redirect.github.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1430-2024-10-11) ##### API - Add helper class to capture context using ScheduledExecutorService ([#​6712](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6712)) - Adds Baggage.getEntry(String key) ([#​6765](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6765)) ##### Extensions - Fix ottracepropagation for short span ids ([#​6734](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6734)) ##### SDK ##### Metrics - Optimize advice with FilteredAttributes ([#​6633](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6633)) ##### Exporters - Add experimental stdout log, metric, trace exporters for printing records to stdout in standard OTLP JSON format. ([#​6675](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6675), [#​6750](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6750)) - Add Marshalers for profiling signal type ([#​6680](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6680)) ##### Extensions - Add `*Model` suffix to declarative config generated classes. ([#​6721](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6721)) - Use autoconfigured ClassLoader to load declarative config ([#​6725](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6725)) - Update declarative config to use opentelemetry-configuration v0.3.0 ([#​6733](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6733)) - Add `StructuredConfigProperties#getStructured` default method, add `StructuredConfigProperties.empty()` ([#​6759](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6759)) ##### Testing - Add context info about wrong span or trace. ([#​6703](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6703))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 8fd3ef42e0ff..a4401c3c3225 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.42.1 + 1.43.0 pom import From 408546bfbfb3d9530fbf14cdca9106141ef56cb8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 11 Oct 2024 20:21:57 +0200 Subject: [PATCH 1443/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.78.0 (#1781) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f9c3b63456ee..f1909bd2cc1e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.77.0 + 6.78.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a4401c3c3225..40077f65ebbd 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.77.0 + 6.78.0 import pom From ee18cc2c72006138d8abbc29491495bedb05d31d Mon Sep 17 00:00:00 2001 From: Szabolcs Rozsnyai Date: Fri, 11 Oct 2024 20:22:10 +0200 Subject: [PATCH 1444/1979] fix:Fixed transaction tagging and reset datafaker version (#1777) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- .../java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index e4cfbb20be34..d7c368de3869 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -38,7 +38,7 @@ net.datafaker datafaker - 2.4.0 + 1.7.0 com.google.cloud diff --git a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java index 84e2bc9ac812..6b91fa1c824c 100644 --- a/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java +++ b/java-spanner-jdbc/samples/quickperf/src/main/java/com/google/cloud/jdbc/quickperf/QuickPerfRunner.java @@ -163,6 +163,9 @@ public void run() { boolean hasResults = statement.execute(); if (!connection.getAutoCommit()) { connection.commit(); + connection + .createStatement() + .execute(String.format("SET %sTRANSACTION_TAG = '%s'", tagPrefix, config.DEFAULT_TAG)); } long stop = System.nanoTime() - start; From 666141051660008aabe457f7da49d330718278c1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 12 Oct 2024 09:03:59 +0200 Subject: [PATCH 1445/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.79.0 (#1786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.79.0 * chore: rename methods to avoid name clash --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 4 +- .../samples/spring-data-jdbc/pom.xml | 2 +- .../jdbc/ClientSideStatementHintsTest.java | 7 ++- .../spanner/jdbc/ExecuteMockServerTest.java | 55 ++++++++++--------- .../MultiplexedSessionsMockServerTest.java | 11 ++-- .../jdbc/PartitionedQueryMockServerTest.java | 13 +++-- ...mentReturnGeneratedKeysMockServerTest.java | 15 ++--- .../spanner/jdbc/SavepointMockServerTest.java | 37 +++++++------ ...mentReturnGeneratedKeysMockServerTest.java | 15 ++--- .../cloud/spanner/jdbc/TagMockServerTest.java | 13 +++-- .../jdbc/TransactionMockServerTest.java | 11 ++-- 11 files changed, 96 insertions(+), 87 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f1909bd2cc1e..56a405e3068d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.36.1 + 3.37.0 @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.78.0 + 6.79.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 40077f65ebbd..ca8c81d1be76 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.78.0 + 6.79.0 import pom diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java index 9a69ba2623ab..97bcd74b33b3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ClientSideStatementHintsTest.java @@ -68,13 +68,14 @@ private String createUrl() { getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testStatementTagInHint() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { try (ResultSet resultSet = connection .createStatement() @@ -94,7 +95,7 @@ public void testStatementTagInHint() throws SQLException { @Test public void testRpcPriorityInHint() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { try (ResultSet resultSet = connection .createStatement() diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index d85c4f8a5b03..f3c22d03cfee 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -205,13 +205,14 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testStatementExecuteQuery() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { try (ResultSet resultSet = statement.executeQuery(query)) { verifyResultSet(resultSet); @@ -231,7 +232,7 @@ public void testStatementExecuteQuery() throws SQLException { @Test public void testStatementExecuteUpdate() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml)); assertEquals(0, statement.executeUpdate(DDL)); @@ -249,7 +250,7 @@ public void testStatementExecuteUpdate() throws SQLException { @Test public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals(1, statement.executeUpdate(dml, Statement.NO_GENERATED_KEYS)); @@ -265,7 +266,7 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException @Test public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"})); @@ -283,7 +284,7 @@ public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { @Test public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeUpdate(DDL, new int[] {1})); @@ -297,7 +298,7 @@ public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException @Test public void testStatementLargeExecuteUpdate() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1L, statement.executeLargeUpdate(dml)); assertEquals(0L, statement.executeLargeUpdate(DDL)); @@ -311,7 +312,7 @@ public void testStatementLargeExecuteUpdate() throws SQLException { @Test public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals(1, statement.executeLargeUpdate(dml, Statement.NO_GENERATED_KEYS)); @@ -329,7 +330,7 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep @Test public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeLargeUpdate(dml, new String[] {"id"})); assertEquals(0, statement.executeLargeUpdate(DDL, new String[] {"id"})); @@ -346,7 +347,7 @@ public void testStatementExecuteLargeUpdateReturnColumnNames() throws SQLExcepti @Test public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeLargeUpdate(dml, new int[] {1})); assertEquals(0, statement.executeLargeUpdate(DDL, new int[] {1})); @@ -360,7 +361,7 @@ public void testStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLExcep @Test public void testStatementExecute() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { verifyUpdateCount(statement, () -> statement.execute(dml), 1L); verifyUpdateCount(statement, () -> statement.execute(largeDml), LARGE_UPDATE_COUNT); @@ -375,7 +376,7 @@ public void testStatementExecute() throws SQLException { @Test public void testStatementExecuteReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); 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); @@ -401,7 +402,7 @@ public void testStatementExecuteReturnGeneratedKeys() throws SQLException { @Test public void testStatementExecuteReturnColumnNames() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { verifyUpdateCount(statement, () -> statement.execute(dml, new String[] {"id"}), 1L); verifyUpdateCount( @@ -420,7 +421,7 @@ public void testStatementExecuteReturnColumnNames() throws SQLException { @Test public void testStatementExecuteReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { verifyUpdateCount(statement, () -> statement.execute(dml, new int[] {1}), 1L); verifyUpdateCount( @@ -439,7 +440,7 @@ public void testStatementExecuteReturnColumnIndexes() throws SQLException { @Test public void testPreparedStatementExecuteQuery() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { try (ResultSet resultSet = connection.prepareStatement(query).executeQuery()) { verifyResultSet(resultSet); } @@ -458,7 +459,7 @@ public void testPreparedStatementExecuteQuery() throws SQLException { @Test public void testPreparedStatementExecuteUpdate() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1, connection.prepareStatement(dml).executeUpdate()); assertEquals(0, connection.prepareStatement(DDL).executeUpdate()); assertEquals(0, connection.prepareStatement(clientSideUpdate).executeUpdate()); @@ -472,7 +473,7 @@ public void testPreparedStatementExecuteUpdate() throws SQLException { @Test public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals( 1, connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS).executeUpdate()); @@ -503,7 +504,7 @@ public void testPreparedStatementExecuteUpdateReturnGeneratedKeys() throws SQLEx @Test public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1, connection.prepareStatement(dml, new String[] {"id"}).executeUpdate()); assertEquals(0, connection.prepareStatement(DDL, new String[] {"id"}).executeUpdate()); assertEquals( @@ -523,7 +524,7 @@ public void testPreparedStatementExecuteUpdateReturnColumnNames() throws SQLExce @Test public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1, connection.prepareStatement(dml, new int[] {1}).executeUpdate()); assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeUpdate()); assertEquals(0, connection.prepareStatement(clientSideUpdate, new int[] {1}).executeUpdate()); @@ -539,7 +540,7 @@ public void testPreparedStatementExecuteUpdateReturnColumnIndexes() throws SQLEx @Test public void testPreparedStatementLargeExecuteUpdate() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1L, connection.prepareStatement(dml).executeLargeUpdate()); assertEquals(0L, connection.prepareStatement(DDL).executeLargeUpdate()); assertEquals(0L, connection.prepareStatement(clientSideUpdate).executeLargeUpdate()); @@ -554,7 +555,7 @@ public void testPreparedStatementLargeExecuteUpdate() throws SQLException { @Test public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals( 1, connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS).executeLargeUpdate()); @@ -587,7 +588,7 @@ public void testPreparedStatementExecuteLargeUpdateReturnGeneratedKeys() throws @Test public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1, connection.prepareStatement(dml, new String[] {"id"}).executeLargeUpdate()); assertEquals(0, connection.prepareStatement(DDL, new String[] {"id"}).executeLargeUpdate()); assertEquals( @@ -612,7 +613,7 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnNames() throws SQ @Test public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertEquals(1, connection.prepareStatement(dml, new int[] {1}).executeLargeUpdate()); assertEquals(0, connection.prepareStatement(DDL, new int[] {1}).executeLargeUpdate()); assertEquals( @@ -631,7 +632,7 @@ public void testPreparedStatementExecuteLargeUpdateReturnColumnIndexes() throws @Test public void testPreparedStatementExecute() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { verifyPreparedUpdateCount(connection.prepareStatement(dml), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( connection.prepareStatement(largeDml), PreparedStatement::execute, LARGE_UPDATE_COUNT); @@ -651,7 +652,7 @@ public void testPreparedStatementExecute() throws SQLException { @Test public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. verifyPreparedUpdateCount( connection.prepareStatement(dml, Statement.NO_GENERATED_KEYS), @@ -683,7 +684,7 @@ public void testPreparedStatementExecuteReturnGeneratedKeys() throws SQLExceptio @Test public void testPreparedStatementExecuteReturnColumnNames() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { verifyPreparedUpdateCount( connection.prepareStatement(dml, new String[] {"id"}), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( @@ -711,7 +712,7 @@ public void testPreparedStatementExecuteReturnColumnNames() throws SQLException @Test public void testPreparedStatementExecuteReturnColumnIndexes() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { verifyPreparedUpdateCount( connection.prepareStatement(dml, new int[] {1}), PreparedStatement::execute, 1L); verifyPreparedUpdateCount( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java index 8415f1a3794e..251dc34f3534 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -77,13 +77,14 @@ private String createUrl() { getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testUsesMultiplexedSessionForQueryInAutoCommit() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertTrue(connection.getAutoCommit()); try (ResultSet resultSet = connection.createStatement().executeQuery(SELECT_RANDOM_SQL)) { //noinspection StatementWithEmptyBody @@ -106,7 +107,7 @@ public void testUsesMultiplexedSessionForQueryInAutoCommit() throws SQLException @Test public void testUsesMultiplexedSessionForQueryInReadOnlyTransaction() throws SQLException { int numQueries = 2; - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setReadOnly(true); connection.setAutoCommit(false); @@ -137,7 +138,7 @@ public void testUsesMultiplexedSessionForQueryInReadOnlyTransaction() throws SQL @Test public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { assertTrue(connection.getAutoCommit()); assertEquals(1, connection.createStatement().executeUpdate(INSERT_SQL)); } @@ -158,7 +159,7 @@ public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { @Test public void testUsesRegularSessionForQueryInTransaction() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(false); assertFalse(connection.getAutoCommit()); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index 5b521b6218ca..1ee80983bf6a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -83,7 +83,8 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @@ -103,7 +104,7 @@ public void testPartitionedQueryUsingSql() throws SQLException { mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); String prefix = dialect == Dialect.POSTGRESQL ? "spanner." : ""; - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { // 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)); @@ -199,7 +200,7 @@ public void testPartitionedQueryStatement() throws SQLException { Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { CloudSpannerJdbcConnection cloudSpannerJdbcConnection = connection.unwrap(CloudSpannerJdbcConnection.class); // This will automatically enable Data Boost for any partitioned query that is executed on @@ -288,7 +289,7 @@ public void testPartitionedQueryPreparedStatement() throws SQLException { .build(); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { CloudSpannerJdbcConnection cloudSpannerJdbcConnection = connection.unwrap(CloudSpannerJdbcConnection.class); // This will automatically enable Data Boost for any partitioned query that is executed on @@ -372,7 +373,7 @@ public void testAutoPartitionMode() throws SQLException { Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { CloudSpannerJdbcConnection cloudSpannerJdbcConnection = connection.unwrap(CloudSpannerJdbcConnection.class); // This will automatically enable Data Boost for any partitioned query that is executed on @@ -478,7 +479,7 @@ public void testAutoPartitionModeEmptyResult() throws SQLException { Statement statement = Statement.of("select * from my_table where active=true"); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { CloudSpannerJdbcConnection cloudSpannerJdbcConnection = connection.unwrap(CloudSpannerJdbcConnection.class); // This will automatically enable Data Boost for any partitioned query that is executed on diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java index b88428bdfb1e..cfb2c8a12c42 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementReturnGeneratedKeysMockServerTest.java @@ -81,7 +81,8 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @@ -121,7 +122,7 @@ public void testReturnAutoGeneratedKeys() throws SQLException { .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) { for (SqlRunnable runnable : @@ -180,7 +181,7 @@ public void testReturnColumnNames() throws SQLException { .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, new String[] {"id"})) { for (SqlRunnable runnable : ImmutableList.of( @@ -213,7 +214,7 @@ 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(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, new int[] {1})) { // The JDBC driver silently ignores the request for column indices. for (SqlRunnable runnable : @@ -238,7 +239,7 @@ public void testReturnGeneratedKeysForQuery() throws SQLException { RandomResultSetGenerator generator = new RandomResultSetGenerator(1); mockSpanner.putStatementResult(StatementResult.query(Statement.of(sql), generator.generate())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) { assertTrue(statement.execute()); @@ -256,7 +257,7 @@ public void testReturnGeneratedKeysForDdl() throws SQLException { String sql = "create table test"; addDdlResponseToSpannerAdmin(); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) { assertFalse(statement.execute()); @@ -293,7 +294,7 @@ public void testReturnAutoGeneratedKeysForStatementWithReturning() throws SQLExc .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); PreparedStatement statement = connection.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS)) { assertTrue(statement.execute()); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java index d8b438abb8b5..5f2fc8466626 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/SavepointMockServerTest.java @@ -85,13 +85,14 @@ private String createUrl() { getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testCreateSavepoint() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setSavepoint("s1"); if (dialect == Dialect.POSTGRESQL) { @@ -112,7 +113,7 @@ public void testCreateSavepoint() throws SQLException { @Test public void testCreateSavepointWhenDisabled() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.DISABLED); @@ -122,7 +123,7 @@ public void testCreateSavepointWhenDisabled() throws SQLException { @Test public void testReleaseSavepoint() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { Savepoint s1 = connection.setSavepoint("s1"); connection.releaseSavepoint(s1); assertThrows(SQLException.class, () -> connection.releaseSavepoint(s1)); @@ -150,7 +151,7 @@ public void testReleaseSavepoint() throws SQLException { public void testRollbackToSavepoint() throws SQLException { for (SavepointSupport savepointSupport : new SavepointSupport[] {SavepointSupport.ENABLED, SavepointSupport.FAIL_AFTER_ROLLBACK}) { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); Savepoint s1 = connection.setSavepoint("s1"); @@ -181,7 +182,7 @@ public void testRollbackToSavepoint() throws SQLException { @Test public void testSavepointInAutoCommit() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(true); assertThrows(SQLException.class, () -> connection.setSavepoint("s1")); @@ -196,7 +197,7 @@ public void testSavepointInAutoCommit() throws SQLException { public void testRollbackToSavepointInReadOnlyTransaction() throws SQLException { for (SavepointSupport savepointSupport : new SavepointSupport[] {SavepointSupport.ENABLED, SavepointSupport.FAIL_AFTER_ROLLBACK}) { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); connection.setReadOnly(true); @@ -237,7 +238,7 @@ public void testRollbackToSavepointInReadOnlyTransaction() throws SQLException { @Test public void testRollbackToSavepointInReadWriteTransaction() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.ENABLED); @@ -288,7 +289,7 @@ public void testRollbackToSavepointInReadWriteTransaction() throws SQLException @Test public void testRollbackToSavepointWithDmlStatements() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.ENABLED); @@ -344,7 +345,7 @@ public void testRollbackToSavepointFails() throws SQLException { int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.ENABLED); @@ -401,7 +402,7 @@ public void testRollbackToSavepointWithFailAfterRollback() throws SQLException { int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.FAIL_AFTER_ROLLBACK); @@ -442,7 +443,7 @@ public void testRollbackToSavepointSucceedsWithRollback() throws SQLException { int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.unwrap(CloudSpannerJdbcConnection.class).setSavepointSupport(savepointSupport); try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { @@ -477,7 +478,7 @@ public void testMultipleRollbacksWithChangedResults() throws SQLException { int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { try (ResultSet resultSet = connection.createStatement().executeQuery(statement.getSql())) { int count = 0; while (resultSet.next()) { @@ -512,7 +513,7 @@ public void testMultipleRollbacks() throws SQLException { int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.ENABLED); @@ -561,7 +562,7 @@ public void testMultipleRollbacks() throws SQLException { @Test public void testRollbackMutations() throws SQLException { - try (Connection con = createConnection()) { + try (Connection con = createJdbcConnection()) { CloudSpannerJdbcConnection connection = con.unwrap(CloudSpannerJdbcConnection.class); connection.setSavepointSupport(SavepointSupport.ENABLED); @@ -589,7 +590,7 @@ public void testRollbackMutations() throws SQLException { @Test public void testRollbackBatchDml() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .unwrap(CloudSpannerJdbcConnection.class) .setSavepointSupport(SavepointSupport.ENABLED); @@ -649,7 +650,7 @@ public void testRollbackToSavepointWithoutInternalRetries() throws SQLException int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.unwrap(CloudSpannerJdbcConnection.class).setRetryAbortsInternally(false); Savepoint s1 = connection.setSavepoint("s1"); @@ -676,7 +677,7 @@ public void testRollbackToSavepointWithoutInternalRetriesInReadOnlyTransaction() int numRows = 10; RandomResultSetGenerator generator = new RandomResultSetGenerator(numRows); mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate())); - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.unwrap(CloudSpannerJdbcConnection.class).setRetryAbortsInternally(false); connection.setReadOnly(true); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java index 9cd9068dcd00..ea727f14b7d7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/StatementReturnGeneratedKeysMockServerTest.java @@ -80,7 +80,8 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @@ -120,7 +121,7 @@ public void testReturnAutoGeneratedKeys() throws SQLException { .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); java.sql.Statement statement = connection.createStatement()) { for (SqlRunnable runnable : ImmutableList.of( @@ -183,7 +184,7 @@ public void testReturnColumnNames() throws SQLException { .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); java.sql.Statement statement = connection.createStatement()) { for (SqlRunnable runnable : ImmutableList.of( @@ -216,7 +217,7 @@ 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(); + try (Connection connection = createJdbcConnection(); java.sql.Statement statement = connection.createStatement()) { // The JDBC driver silently ignores the request for column indices. for (SqlRunnable runnable : @@ -241,7 +242,7 @@ public void testReturnGeneratedKeysForQuery() throws SQLException { RandomResultSetGenerator generator = new RandomResultSetGenerator(1); mockSpanner.putStatementResult(StatementResult.query(Statement.of(sql), generator.generate())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); java.sql.Statement statement = connection.createStatement()) { assertTrue(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS)); try (ResultSet resultSet = statement.getResultSet()) { @@ -258,7 +259,7 @@ public void testReturnGeneratedKeysForDdl() throws SQLException { String sql = "create table test"; addDdlResponseToSpannerAdmin(); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); 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()); @@ -294,7 +295,7 @@ public void testReturnAutoGeneratedKeysForStatementWithReturning() throws SQLExc .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); - try (Connection connection = createConnection(); + try (Connection connection = createJdbcConnection(); java.sql.Statement statement = connection.createStatement()) { assertTrue(statement.execute(sql, java.sql.Statement.RETURN_GENERATED_KEYS)); try (ResultSet resultSet = statement.getResultSet()) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java index 8401297c097b..832b42c6a0cf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TagMockServerTest.java @@ -77,13 +77,14 @@ private String createUrl() { getPort(), "proj", "inst", "db" + (dialect == Dialect.POSTGRESQL ? "pg" : "")); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testStatementTagForQuery() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .createStatement() .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); @@ -107,7 +108,7 @@ public void testStatementTagForQuery() throws SQLException { @Test public void testTransactionTagForQuery() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .createStatement() .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); @@ -142,7 +143,7 @@ public void testTransactionTagForQuery() throws SQLException { @Test public void testStatementTagForBatchDml() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .createStatement() .execute(String.format("set %sstatement_tag='my-tag'", getVariablePrefix())); @@ -172,7 +173,7 @@ public void testStatementTagForBatchDml() throws SQLException { @Test public void testTransactionTagForBatchDml() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection .createStatement() .execute(String.format("set %stransaction_tag='my-tag'", getVariablePrefix())); @@ -214,7 +215,7 @@ public void testTransactionTagForBatchDml() throws SQLException { @Test public void testStatementTagInHint() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { try (ResultSet resultSet = connection .createStatement() diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java index a514995491af..954d12e80baf 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java @@ -50,13 +50,14 @@ private String createUrl() { getPort(), "proj", "inst", "db"); } - private Connection createConnection() throws SQLException { + @Override + protected Connection createJdbcConnection() throws SQLException { return DriverManager.getConnection(createUrl()); } @Test public void testCommittingEmptyTransactionIsNoOp() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.commit(); } @@ -65,7 +66,7 @@ public void testCommittingEmptyTransactionIsNoOp() throws SQLException { @Test public void testCommittingEmptyExplicitTransactionIsNoOp() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(true); try (Statement statement = connection.createStatement()) { statement.execute("begin transaction"); @@ -78,7 +79,7 @@ public void testCommittingEmptyExplicitTransactionIsNoOp() throws SQLException { @Test public void testRollingBackEmptyTransactionIsNoOp() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.rollback(); } @@ -87,7 +88,7 @@ public void testRollingBackEmptyTransactionIsNoOp() throws SQLException { @Test public void testRollingBackEmptyExplicitTransactionIsNoOp() throws SQLException { - try (Connection connection = createConnection()) { + try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(true); try (Statement statement = connection.createStatement()) { statement.execute("begin transaction"); From 66d6f03ec59b6b9ebebee99cd507593cee0999db Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 12 Oct 2024 09:42:01 +0200 Subject: [PATCH 1446/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.37.0 (#1775) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index cc7985420ce8..514cb3ada267 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.36.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.37.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 0effa03c5227..0f8b919c91f6 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.36.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.37.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 96a8059b9b9b..e6553bd6e418 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.36.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.37.0" } env_vars: { diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d7c368de3869..2a52bdbb3626 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.36.1 + 3.37.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 91ea57a45ee6..27a4d4e228f2 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.36.1 + 3.37.0 From 3cc459afef6ea72dd8c5c903ec1d14964836db93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 12 Oct 2024 10:06:04 +0200 Subject: [PATCH 1447/1979] feat: auto_batch_dml connection property (#1787) * feat: auto_batch_dml connection property The `auto_batch_dml` connection property enables automatic batching of DML statements, for example when using Hibernate. When this connection variable has been enabled, a JDBC connection will automatically buffer DML statements in memory, and send all buffered DML statements to Spanner as one batch when a query is executed or when the transaction is committed. This can significantly reduce the number of round-trips to Spanner, especially when using an ORM like Hibernate that generates many small single-row DML statements. * test: add test for auto_batch_dml --- java-spanner-jdbc/README.md | 5 ++++ .../spanner/jdbc/ExecuteMockServerTest.java | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 34a80deadbfa..cacea9e4225b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -118,6 +118,11 @@ these can also be supplied in a Properties instance that is passed to the - maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. - numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. +- auto_batch_dml (boolean): Automatically buffer DML statements and execute them as one batch, + instead of executing them on Spanner directly. The buffered DML statements are executed on Spanner + in one batch when a query is executed, or when the transaction is committed. This option can for + example be used in combination with Hibernate to automatically group more (small) DML statements + into one batch. - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index f3c22d03cfee..d7d72f76f2ef 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -36,6 +36,8 @@ import com.google.protobuf.Value; import com.google.rpc.Code; 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.ResultSetMetadata; import com.google.spanner.v1.ResultSetStats; import com.google.spanner.v1.StructType; @@ -844,4 +846,28 @@ public void testInvalidExecuteUpdate_shouldNotLeakSession() throws SQLException } } } + + private String getExtension() { + return dialect == Dialect.POSTGRESQL ? "spanner." : ""; + } + + @Test + public void testExecuteAutoBatchDml() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + connection.setAutoCommit(false); + + assertFalse(statement.execute(String.format("set %sauto_batch_dml = true", getExtension()))); + for (int i = 0; i < 3; i++) { + assertFalse(statement.execute(dml)); + assertEquals(1, statement.getUpdateCount()); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + ExecuteBatchDmlRequest request = + mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0); + assertEquals(3, request.getStatementsCount()); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + } } From 4f80ab48f78c8e9ae3ff0b966792f368a10735a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 12 Oct 2024 10:14:42 +0200 Subject: [PATCH 1448/1979] chore(ci): remove auto-release workflow (#1788) --- .../.github/workflows/auto-release.yaml | 103 ------------------ 1 file changed, 103 deletions(-) delete mode 100644 java-spanner-jdbc/.github/workflows/auto-release.yaml diff --git a/java-spanner-jdbc/.github/workflows/auto-release.yaml b/java-spanner-jdbc/.github/workflows/auto-release.yaml deleted file mode 100644 index c6577b779110..000000000000 --- a/java-spanner-jdbc/.github/workflows/auto-release.yaml +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2022 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: auto-release -jobs: - approve: - runs-on: ubuntu-latest - if: contains(github.head_ref, 'release-please') - steps: - - uses: actions/github-script@v7 - with: - github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} - debug: true - script: | - // only approve PRs from release-please[bot] - if (context.payload.pull_request.user.login !== "release-please[bot]") { - return; - } - - // only approve PRs like "chore(main): release " - if ( !context.payload.pull_request.title.startsWith("chore(main): release") ) { - return; - } - - // only approve PRs with pom.xml and versions.txt changes - const filesPromise = github.rest.pulls.listFiles.endpoint({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number, - }); - const changed_files = await github.paginate(filesPromise) - - if ( changed_files.length < 1 ) { - console.log( "Not proceeding since PR is empty!" ) - return; - } - - if ( !changed_files.some(v => v.filename.includes("pom")) || !changed_files.some(v => v.filename.includes("versions.txt")) ) { - console.log( "PR file changes do not have pom.xml or versions.txt -- something is wrong. PTAL!" ) - return; - } - - // trigger auto-release when - // 1) it is a SNAPSHOT release (auto-generated post regular release) - // 2) there are dependency updates only - // 3) there are no open dependency update PRs in this repo (to avoid multiple releases) - if ( - context.payload.pull_request.body.includes("Fix") || - context.payload.pull_request.body.includes("Build") || - context.payload.pull_request.body.includes("Documentation") || - context.payload.pull_request.body.includes("BREAKING CHANGES") || - context.payload.pull_request.body.includes("Features") - ) { - console.log( "Not auto-releasing since it is not a dependency-update-only release." ); - return; - } - - const promise = github.rest.pulls.list.endpoint({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open' - }); - const open_pulls = await github.paginate(promise) - - if ( open_pulls.length > 1 && !context.payload.pull_request.title.includes("SNAPSHOT") ) { - for ( const pull of open_pulls ) { - if ( pull.title.startsWith("deps: update dependency") ) { - console.log( "Not auto-releasing yet since there are dependency update PRs open in this repo." ); - return; - } - } - } - - // approve release PR - await github.rest.pulls.createReview({ - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Rubber stamped release!', - pull_number: context.payload.pull_request.number, - event: 'APPROVE' - }); - - // attach kokoro:force-run and automerge labels - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - labels: ['kokoro:force-run'] - }); From b8a644e06da82315a3c7ccf391f6b4d4aa6db680 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 12 Oct 2024 10:38:37 +0200 Subject: [PATCH 1449/1979] chore(main): release 2.23.0 (#1783) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 24 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e64db9c2e8e5..3f5be174e84a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [2.23.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.22.1...v2.23.0) (2024-10-12) + + +### Features + +* Auto_batch_dml connection property ([#1787](https://github.com/googleapis/java-spanner-jdbc/issues/1787)) ([8aa0edb](https://github.com/googleapis/java-spanner-jdbc/commit/8aa0edbca8545348066cdcee511f2fc692987075)) + + +### Bug Fixes + +* Fixed transaction tagging and reset datafaker version ([#1777](https://github.com/googleapis/java-spanner-jdbc/issues/1777)) ([3b117c0](https://github.com/googleapis/java-spanner-jdbc/commit/3b117c0723fb44d82170b5ab766afd6ff2c0c347)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.52.0 ([#1779](https://github.com/googleapis/java-spanner-jdbc/issues/1779)) ([ba661fe](https://github.com/googleapis/java-spanner-jdbc/commit/ba661fe9a29935b2683988c968f23dbd171c6e0f)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.78.0 ([#1781](https://github.com/googleapis/java-spanner-jdbc/issues/1781)) ([dcebfff](https://github.com/googleapis/java-spanner-jdbc/commit/dcebfffa8eb71aa5711774873dd8e451de7e9bf5)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.79.0 ([#1786](https://github.com/googleapis/java-spanner-jdbc/issues/1786)) ([2cb6c99](https://github.com/googleapis/java-spanner-jdbc/commit/2cb6c99db5c96842b08a303f59b3669deb03fb9a)) +* Update dependency com.google.cloud:google-cloud-trace to v2.52.0 ([#1780](https://github.com/googleapis/java-spanner-jdbc/issues/1780)) ([7a81155](https://github.com/googleapis/java-spanner-jdbc/commit/7a811556a6203006e6e40c54a5a8017d68db3664)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.37.0 ([#1775](https://github.com/googleapis/java-spanner-jdbc/issues/1775)) ([db48aa5](https://github.com/googleapis/java-spanner-jdbc/commit/db48aa571e913bd892708507a9da758a9a9790c0)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.33.0 ([#1778](https://github.com/googleapis/java-spanner-jdbc/issues/1778)) ([1e5428f](https://github.com/googleapis/java-spanner-jdbc/commit/1e5428f0a5cfdbd983b99c5fd3fa59833c9ddada)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.25 ([#1776](https://github.com/googleapis/java-spanner-jdbc/issues/1776)) ([fe47f12](https://github.com/googleapis/java-spanner-jdbc/commit/fe47f12a87a048f794980c871ebb79cbc971cfc5)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.43.0 ([#1782](https://github.com/googleapis/java-spanner-jdbc/issues/1782)) ([7c3c46e](https://github.com/googleapis/java-spanner-jdbc/commit/7c3c46edf0ecccbb2dcdb8c54a665815c184e34a)) + ## [2.22.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.22.0...v2.22.1) (2024-10-03) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index cacea9e4225b..394ea4e53610 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.22.1 + 2.23.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.22.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.23.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.22.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.23.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 56a405e3068d..67c1795c4dfb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.22.2-SNAPSHOT + 2.23.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f7cb0214e6e7..4fbeb9fb0342 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.2-SNAPSHOT + 2.23.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 894c1a0cdabc..c5d3a599947e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.22.1:2.22.2-SNAPSHOT +google-cloud-spanner-jdbc:2.23.0:2.23.0 From 186e4fc52623fa8e86cfa85400ab3ad5bdc43aab Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 12 Oct 2024 09:04:17 +0000 Subject: [PATCH 1450/1979] chore(main): release 2.23.1-SNAPSHOT (#1789) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 67c1795c4dfb..094ed7cc61e1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.23.0 + 2.23.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 4fbeb9fb0342..fe356998317b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.23.0 + 2.23.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c5d3a599947e..aecd67200b3f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.23.0:2.23.0 +google-cloud-spanner-jdbc:2.23.0:2.23.1-SNAPSHOT From 5bbeba548a05e40066f0e40befa3718fadba2ef5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 15 Oct 2024 17:01:58 +0200 Subject: [PATCH 1451/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.23.0 (#1790) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 70c163d82a32..223c797a6c22 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.22.1 + 2.23.0 From 1cb757d6cffdd14fb749cdb4e66c78e34d91ade9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 16 Oct 2024 13:23:54 +0200 Subject: [PATCH 1452/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.49.0 (#1791) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2a52bdbb3626..b1b7d057a723 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.48.0 + 26.49.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 27a4d4e228f2..5efd8b88d231 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.48.0 + 26.49.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ca8c81d1be76..c6afa15d522b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.48.0 + 26.49.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 97545b6b9b95..0ceee55a969d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.48.0 + 26.49.0 import pom From cf21b2f3fcb6dba71da8e2912802e36b550155dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 18 Oct 2024 12:52:01 +0200 Subject: [PATCH 1453/1979] test: enable integration tests for float32 (#1792) * test: enable integration tests for float32 * fix: add missing test column definitions * fix: the type name returned by Spanner is 'real' * test: also enable float32 null test --- .../jdbc/DatabaseMetaData_GetColumns.sql | 4 ++ .../DatabaseMetaData_GetColumns.sql | 4 ++ .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 2 + .../jdbc/it/ITJdbcPgDatabaseMetaDataTest.java | 1 + .../spanner/jdbc/it/ITJdbcPgNumericTest.java | 8 +--- .../jdbc/it/ITJdbcPreparedStatementTest.java | 40 +++++++++++++------ .../spanner/jdbc/it/CreateMusicTables.sql | 4 ++ .../spanner/jdbc/it/CreateMusicTables_PG.sql | 3 ++ 8 files changed, 48 insertions(+), 18 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index e5226a83f240..94d2a0e61cf0 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -21,6 +21,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE LIKE 'BYTES%' THEN -2 WHEN SPANNER_TYPE = 'DATE' THEN 91 WHEN SPANNER_TYPE = 'FLOAT64' THEN 8 + WHEN SPANNER_TYPE = 'FLOAT32' THEN 7 WHEN SPANNER_TYPE = 'INT64' THEN -5 WHEN SPANNER_TYPE = 'NUMERIC' THEN 2 WHEN SPANNER_TYPE LIKE 'STRING%' THEN -9 @@ -34,6 +35,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE = 'INT64' OR SPANNER_TYPE = 'ARRAY' THEN 19 WHEN SPANNER_TYPE = 'NUMERIC' OR SPANNER_TYPE = 'ARRAY' THEN 15 WHEN SPANNER_TYPE = 'FLOAT64' OR SPANNER_TYPE = 'ARRAY' THEN 15 + WHEN SPANNER_TYPE = 'FLOAT32' OR SPANNER_TYPE = 'ARRAY' THEN 15 WHEN SPANNER_TYPE = 'BOOL' OR SPANNER_TYPE = 'ARRAY' THEN NULL WHEN SPANNER_TYPE = 'DATE' OR SPANNER_TYPE = 'ARRAY' THEN 10 WHEN SPANNER_TYPE = 'TIMESTAMP' OR SPANNER_TYPE = 'ARRAY' THEN 35 @@ -45,12 +47,14 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU 0 AS BUFFER_LENGTH, CASE WHEN SPANNER_TYPE LIKE '%FLOAT64%' THEN 16 + WHEN SPANNER_TYPE LIKE '%FLOAT32%' THEN 16 ELSE NULL END AS DECIMAL_DIGITS, CASE WHEN SPANNER_TYPE LIKE '%INT64%' THEN 10 WHEN SPANNER_TYPE LIKE '%NUMERIC%' THEN 10 WHEN SPANNER_TYPE LIKE '%FLOAT64%' THEN 2 + WHEN SPANNER_TYPE LIKE '%FLOAT32%' THEN 2 ELSE NULL END AS NUM_PREC_RADIX, CASE diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index 5b37e32ecad4..38c105108864 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -21,6 +21,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE LIKE 'bytea' THEN -2 WHEN DATA_TYPE = 'date' THEN 91 WHEN DATA_TYPE = 'double precision' THEN 8 + WHEN DATA_TYPE = 'real' THEN 7 WHEN DATA_TYPE = 'bigint' THEN -5 WHEN DATA_TYPE = 'numeric' THEN 2 WHEN DATA_TYPE LIKE 'character varying' THEN -9 @@ -34,6 +35,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE LIKE 'bytea' THEN 10485760 WHEN DATA_TYPE = 'date' THEN 10 WHEN DATA_TYPE = 'double precision' THEN 15 + WHEN DATA_TYPE = 'real' THEN 15 WHEN DATA_TYPE = 'bigint' THEN 19 WHEN DATA_TYPE = 'numeric' THEN 15 WHEN DATA_TYPE LIKE 'character varying' THEN CHARACTER_MAXIMUM_LENGTH @@ -43,6 +45,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A 0 AS "BUFFER_LENGTH", CASE WHEN DATA_TYPE LIKE 'double precision' THEN 16 + WHEN DATA_TYPE LIKE 'real' THEN 16 WHEN DATA_TYPE LIKE 'numeric' THEN 16383 ELSE NULL END AS "DECIMAL_DIGITS", @@ -50,6 +53,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE LIKE 'bigint' THEN 10 WHEN DATA_TYPE LIKE 'numeric' THEN 10 WHEN DATA_TYPE LIKE 'double precision' THEN 2 + WHEN DATA_TYPE LIKE 'real' THEN 2 ELSE NULL END AS "NUM_PREC_RADIX", CASE diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index efc3934d3da3..94d9ad1403ea 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -149,6 +149,7 @@ private Column( Arrays.asList( new Column("ColInt64", Types.BIGINT, "INT64", 19, null, 10, false, null), new Column("ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null), + new Column("ColFloat32", Types.REAL, "FLOAT32", 15, 16, 2, false, null), new Column("ColBool", Types.BOOLEAN, "BOOL", null, null, null, false, null), new Column("ColString", Types.NVARCHAR, "STRING(100)", 100, null, null, false, 100), new Column( @@ -162,6 +163,7 @@ private Column( new Column("ColJson", Types.NVARCHAR, "JSON", 2621440, null, null, false, 2621440), new Column("ColInt64Array", Types.ARRAY, "ARRAY", 19, null, 10, true, null), new Column("ColFloat64Array", Types.ARRAY, "ARRAY", 15, 16, 2, true, null), + new Column("ColFloat32Array", Types.ARRAY, "ARRAY", 15, 16, 2, true, null), new Column("ColBoolArray", Types.ARRAY, "ARRAY", null, null, null, true, null), new Column( "ColStringArray", Types.ARRAY, "ARRAY", 100, null, null, true, 100), diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java index 033ff27e45de..1984ccb51392 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgDatabaseMetaDataTest.java @@ -148,6 +148,7 @@ private Column( Arrays.asList( new Column("colint64", Types.BIGINT, "bigint", 19, null, 10, false, null), new Column("colfloat64", Types.DOUBLE, "double precision", 15, 16, 2, false, null), + new Column("colfloat32", Types.REAL, "real", 15, 16, 2, false, null), new Column("colbool", Types.BOOLEAN, "boolean", null, null, null, false, null), new Column("colstring", Types.NVARCHAR, "character varying", 100, null, null, false, 100), new Column( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index 35dd2dfda35c..a7c7a206dbf1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -226,9 +226,7 @@ public void testPreparedStatement() throws Exception { preparedStatement.setShort(3, (short) 1); preparedStatement.setInt(4, 1); preparedStatement.setLong(5, 1L); - // TODO: Change to setFloat(..) when float32 is supported. - // preparedStatement.setFloat(6, 1f); - preparedStatement.setDouble(6, 1d); + preparedStatement.setFloat(6, 1f); preparedStatement.setDouble(7, 1D); preparedStatement.setBigDecimal(8, new BigDecimal("1")); preparedStatement.setObject(9, (byte) 1); @@ -240,9 +238,7 @@ public void testPreparedStatement() throws Exception { preparedStatement.setObject(15, new BigDecimal("1")); preparedStatement.setObject(16, Value.pgNumeric("1")); - // TODO: Change to setFloat(..) when float32 is supported. - // preparedStatement.setFloat(17, Float.NaN); - preparedStatement.setDouble(17, Double.NaN); + preparedStatement.setFloat(17, Float.NaN); preparedStatement.setDouble(18, Double.NaN); preparedStatement.setObject(19, Value.pgNumeric("NaN")); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 2fb170a98da4..31a1a7f1766f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -922,16 +922,17 @@ public void test08_InsertAllColumnTypes() throws SQLException { dialect.dialect == Dialect.POSTGRESQL); String sql = "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "ColInt64, ColFloat64, ColFloat32, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColFloat32Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { ParameterMetaData metadata = ps.getParameterMetaData(); - assertEquals(22, metadata.getParameterCount()); + assertEquals(24, metadata.getParameterCount()); int index = 0; assertEquals(Types.BIGINT, metadata.getParameterType(++index)); assertEquals(Types.DOUBLE, metadata.getParameterType(++index)); + assertEquals(Types.REAL, metadata.getParameterType(++index)); assertEquals(Types.BOOLEAN, metadata.getParameterType(++index)); assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); assertEquals(Types.NVARCHAR, metadata.getParameterType(++index)); @@ -952,10 +953,12 @@ public void test08_InsertAllColumnTypes() throws SQLException { assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals(Types.ARRAY, metadata.getParameterType(++index)); + assertEquals(Types.ARRAY, metadata.getParameterType(++index)); index = 0; ps.setLong(++index, 1L); ps.setDouble(++index, 2D); + ps.setFloat(++index, 3.14f); ps.setBoolean(++index, true); ps.setString(++index, "test"); ps.setObject(++index, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); @@ -968,6 +971,7 @@ public void test08_InsertAllColumnTypes() throws SQLException { ps.setArray(++index, con.createArrayOf("INT64", new Long[] {1L, 2L, 3L})); ps.setArray(++index, con.createArrayOf("FLOAT64", new Double[] {1.1D, 2.2D, 3.3D})); + ps.setArray(++index, con.createArrayOf("FLOAT32", new Float[] {1.1f, 2.2f, 3.3f})); ps.setArray( ++index, con.createArrayOf("BOOL", new Boolean[] {Boolean.TRUE, null, Boolean.FALSE})); ps.setArray(++index, con.createArrayOf("STRING", new String[] {"1", "2", "3"})); @@ -1006,6 +1010,7 @@ public void test08_InsertAllColumnTypes() throws SQLException { assertTrue(rs.next()); assertEquals(1L, rs.getLong(++index)); assertEquals(2d, rs.getDouble(++index), 0.0d); + assertEquals(3.14f, rs.getFloat(++index), 0.0f); assertTrue(rs.getBoolean(++index)); assertEquals("test", rs.getString(++index)); assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(++index)); @@ -1020,6 +1025,8 @@ public void test08_InsertAllColumnTypes() throws SQLException { assertArrayEquals(new Long[] {1L, 2L, 3L}, (Long[]) rs.getArray(++index).getArray()); assertArrayEquals( new Double[] {1.1D, 2.2D, 3.3D}, (Double[]) rs.getArray(++index).getArray()); + assertArrayEquals( + new Float[] {1.1f, 2.2f, 3.3f}, (Float[]) rs.getArray(++index).getArray()); assertArrayEquals( new Boolean[] {true, null, false}, (Boolean[]) rs.getArray(++index).getArray()); assertArrayEquals(new String[] {"1", "2", "3"}, (String[]) rs.getArray(++index).getArray()); @@ -1049,13 +1056,14 @@ public void test08_PGInsertAllColumnTypes() throws SQLException { String sql = "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "ColInt64, ColFloat64, ColFloat32, ColBool, ColString, ColStringMax, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { int index = 0; ps.setLong(++index, 1L); ps.setDouble(++index, 2D); + ps.setFloat(++index, 3.14f); ps.setBoolean(++index, true); ps.setString(++index, "test"); ps.setObject(++index, UUID.fromString("2d37f522-e0a5-4f22-8e09-4d77d299c967")); @@ -1074,6 +1082,7 @@ public void test08_PGInsertAllColumnTypes() throws SQLException { assertTrue(rs.next()); assertEquals(1L, rs.getLong(++index)); assertEquals(2d, rs.getDouble(++index), 0.0d); + assertEquals(3.14f, rs.getFloat(++index), 0.0f); assertTrue(rs.getBoolean(++index)); assertEquals("test", rs.getString(++index)); assertEquals("2d37f522-e0a5-4f22-8e09-4d77d299c967", rs.getString(++index)); @@ -1097,10 +1106,11 @@ public void test09_MetaData_FromQuery() throws SQLException { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { ResultSetMetaData metadata = ps.getMetaData(); - assertEquals(24, metadata.getColumnCount()); + assertEquals(26, metadata.getColumnCount()); int index = 0; assertEquals("ColInt64", metadata.getColumnLabel(++index)); assertEquals("ColFloat64", metadata.getColumnLabel(++index)); + assertEquals("ColFloat32", metadata.getColumnLabel(++index)); assertEquals("ColBool", metadata.getColumnLabel(++index)); assertEquals("ColString", metadata.getColumnLabel(++index)); assertEquals("ColStringMax", metadata.getColumnLabel(++index)); @@ -1113,6 +1123,7 @@ public void test09_MetaData_FromQuery() throws SQLException { assertEquals("ColJson", metadata.getColumnLabel(++index)); assertEquals("ColInt64Array", metadata.getColumnLabel(++index)); assertEquals("ColFloat64Array", metadata.getColumnLabel(++index)); + assertEquals("ColFloat32Array", metadata.getColumnLabel(++index)); assertEquals("ColBoolArray", metadata.getColumnLabel(++index)); assertEquals("ColStringArray", metadata.getColumnLabel(++index)); assertEquals("ColStringMaxArray", metadata.getColumnLabel(++index)); @@ -1149,14 +1160,15 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { dialect.dialect == Dialect.POSTGRESQL); String sql = "INSERT INTO TableWithAllColumnTypes (" - + "ColInt64, ColFloat64, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " - + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" - + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "ColInt64, ColFloat64, ColFloat32, ColBool, ColString, ColStringMax, ColBytes, ColBytesMax, ColDate, ColTimestamp, ColCommitTS, ColNumeric, ColJson, " + + "ColInt64Array, ColFloat64Array, ColFloat32Array, ColBoolArray, ColStringArray, ColStringMaxArray, ColBytesArray, ColBytesMaxArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray" + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, PENDING_COMMIT_TIMESTAMP(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; try (Connection con = createConnection(env, database)) { try (PreparedStatement ps = con.prepareStatement(sql)) { int index = 1; ps.setObject(index++, Value.int64(2L)); ps.setObject(index++, Value.float64(2D)); + ps.setObject(index++, Value.float32(3.14f)); ps.setObject(index++, Value.bool(true)); ps.setObject(index++, Value.string("testvalues")); ps.setObject(index++, Value.string("2d37f522-e0a5-4f22-8e09-4d77d299c967")); @@ -1170,6 +1182,7 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { ps.setObject(index++, Value.int64Array(new long[] {1L, 2L, 3L})); ps.setObject(index++, Value.float64Array(new double[] {1.1D, 2.2D, 3.3D})); + ps.setObject(index++, Value.float32Array(new float[] {1.1f, 2.2f, 3.3f})); ps.setObject(index++, Value.boolArray(Arrays.asList(Boolean.TRUE, null, Boolean.FALSE))); ps.setObject(index++, Value.stringArray(Arrays.asList("1", "2", "3"))); ps.setObject(index++, Value.stringArray(Arrays.asList("3", "2", "1"))); @@ -1207,6 +1220,7 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { int index = 1; assertEquals(Value.int64(2L), rs.getObject(index++, Value.class)); assertEquals(Value.float64(2d), rs.getObject(index++, Value.class)); + assertEquals(Value.float32(3.14f), rs.getObject(index++, Value.class)); assertEquals(Value.bool(true), rs.getObject(index++, Value.class)); assertEquals(Value.string("testvalues"), rs.getObject(index++, Value.class)); assertEquals( @@ -1229,6 +1243,8 @@ public void test11_InsertDataUsingSpannerValue() throws SQLException { assertEquals( Value.float64Array(new double[] {1.1D, 2.2D, 3.3D}), rs.getObject(index++, Value.class)); + assertEquals( + Value.float32Array(new float[] {1.1f, 2.2f, 3.3f}), rs.getObject(index++, Value.class)); assertEquals( Value.boolArray(Arrays.asList(true, null, false)), rs.getObject(index++, Value.class)); assertEquals( @@ -1448,9 +1464,9 @@ public void test13_InsertUntypedNullValues() throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement( "insert into all_nullable_types (" - + "ColInt64, ColFloat64, ColBool, ColString, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson, " + + "ColInt64, ColFloat64, ColFloat32, ColBool, ColString, ColBytes, ColDate, ColTimestamp, ColNumeric, ColJson, " + "ColInt64Array, ColFloat64Array, ColBoolArray, ColStringArray, ColBytesArray, ColDateArray, ColTimestampArray, ColNumericArray, ColJsonArray) " - + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { for (int param = 1; param <= preparedStatement.getParameterMetaData().getParameterCount(); param++) { diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 153dd773d297..51f7d1ea12e7 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -70,6 +70,7 @@ CREATE TABLE Concerts ( CREATE TABLE TableWithAllColumnTypes ( ColInt64 INT64 NOT NULL, ColFloat64 FLOAT64 NOT NULL, + ColFloat32 FLOAT32 NOT NULL, ColBool BOOL NOT NULL, ColString STRING(100) NOT NULL, ColStringMax STRING(MAX) NOT NULL, @@ -83,6 +84,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColInt64Array ARRAY, ColFloat64Array ARRAY, + ColFloat32Array ARRAY, ColBoolArray ARRAY, ColStringArray ARRAY, ColStringMaxArray ARRAY, @@ -100,6 +102,7 @@ CREATE TABLE TableWithAllColumnTypes ( CREATE TABLE all_nullable_types ( ColInt64 INT64, ColFloat64 FLOAT64, + ColFloat32 FLOAT32, ColBool BOOL, ColString STRING(100), ColBytes BYTES(100), @@ -110,6 +113,7 @@ CREATE TABLE all_nullable_types ( ColInt64Array ARRAY, ColFloat64Array ARRAY, + ColFloat32Array ARRAY, ColBoolArray ARRAY, ColStringArray ARRAY, ColBytesArray ARRAY, diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql index 3aafc5722826..43b16bb50f73 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables_PG.sql @@ -71,6 +71,7 @@ CREATE TABLE Concerts ( CREATE TABLE TableWithAllColumnTypes ( ColInt64 BIGINT PRIMARY KEY, ColFloat64 FLOAT8 NOT NULL, + ColFloat32 FLOAT4 NOT NULL, ColBool BOOL NOT NULL, ColString VARCHAR(100) NOT NULL, ColStringMax TEXT, @@ -83,6 +84,7 @@ CREATE TABLE TableWithAllColumnTypes ( CREATE TABLE all_nullable_types ( ColInt64 bigint primary key, ColFloat64 float8, + ColFloat32 float4, ColBool boolean, ColString varchar(100), ColBytes bytea, @@ -93,6 +95,7 @@ CREATE TABLE all_nullable_types ( ColInt64Array bigint[], ColFloat64Array float8[], + ColFloat32Array float4[], ColBoolArray boolean[], ColStringArray varchar(100)[], ColBytesArray bytea[], From 98caf42b17248ae023cc434012003a2f7b4c7b61 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 18 Oct 2024 13:12:24 +0200 Subject: [PATCH 1454/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.0.5 (#1793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.data:spring-data-bom](https://redirect.github.com/spring-projects/spring-data-bom) | `2024.0.4` -> `2024.0.5` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.data:spring-data-bom/2024.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.data:spring-data-bom/2024.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.data:spring-data-bom/2024.0.4/2024.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.data:spring-data-bom/2024.0.4/2024.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-data-bom (org.springframework.data:spring-data-bom) ### [`v2024.0.5`](https://redirect.github.com/spring-projects/spring-data-bom/releases/tag/2024.0.5) [Compare Source](https://redirect.github.com/spring-projects/spring-data-bom/compare/2024.0.4...2024.0.5) ##### :shipit: Participating Modules - [Spring Data BOM 2024.0.5](https://redirect.github.com/spring-projects/spring-data-bom/releases/tag/2024.0.5) - [Spring Data Build 3.3.5](https://redirect.github.com/spring-projects/spring-data-build/releases/tag/3.3.5) - [Spring Data Cassandra 4.3.5](https://redirect.github.com/spring-projects/spring-data-cassandra/releases/tag/4.3.5) - [Spring Data Commons 3.3.5](https://redirect.github.com/spring-projects/spring-data-commons/releases/tag/3.3.5) - [Spring Data Couchbase 5.3.5](https://redirect.github.com/spring-projects/spring-data-couchbase/releases/tag/5.3.5) - [Spring Data Elasticsearch 5.3.5](https://redirect.github.com/spring-projects/spring-data-elasticsearch/releases/tag/5.3.5) - [Spring Data JPA 3.3.5](https://redirect.github.com/spring-projects/spring-data-jpa/releases/tag/3.3.5) - [Spring Data KeyValue 3.3.5](https://redirect.github.com/spring-projects/spring-data-keyvalue/releases/tag/3.3.5) - [Spring Data LDAP 3.3.5](https://redirect.github.com/spring-projects/spring-data-ldap/releases/tag/3.3.5) - [Spring Data MongoDB 4.3.5](https://redirect.github.com/spring-projects/spring-data-mongodb/releases/tag/4.3.5) - [Spring Data Neo4j 7.3.5](https://redirect.github.com/spring-projects/spring-data-neo4j/releases/tag/7.3.5) - [Spring Data REST 4.3.5](https://redirect.github.com/spring-projects/spring-data-rest/releases/tag/4.3.5) - [Spring Data Redis 3.3.5](https://redirect.github.com/spring-projects/spring-data-redis/releases/tag/3.3.5) - [Spring Data Relational 3.3.5](https://redirect.github.com/spring-projects/spring-data-relational/releases/tag/3.3.5)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c6afa15d522b..bc66cd31f906 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.4 + 2024.0.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 0ceee55a969d..7aece5e12991 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.4 + 2024.0.5 import pom From 9fe1355f87f0d78a7e8803526fb2533da7a612e5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 22 Oct 2024 11:21:10 +0200 Subject: [PATCH 1455/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.8.0 (#1796) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 094ed7cc61e1..33d7e798dea6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -459,7 +459,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.7.0 + 3.8.0 From c4726ce2ed6465e9e0a201114b14ca92959dba65 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Oct 2024 08:08:19 +0200 Subject: [PATCH 1456/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.0 (#1797) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index b1b7d057a723..12bd5b0924ee 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.4.1 + 3.5.0 com.google.cloud.jdbc.quickperf.QuickPerf From fac650d8af3299d44d4f8633e92e2993cd875d68 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Oct 2024 08:08:32 +0200 Subject: [PATCH 1457/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.3 (#1798) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 33d7e798dea6..180a187a7b5a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.2 + 1.20.3 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 12bd5b0924ee..c577bf4278b5 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.2 + 1.20.3 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5efd8b88d231..a93c28a1f3a4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.2 + 1.20.3 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index bc66cd31f906..4ea50f09c468 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -114,7 +114,7 @@ org.testcontainers testcontainers - 1.20.2 + 1.20.3 test From 5c382cdc79ca99357a7f642c03941bdc6ac21ce9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Oct 2024 08:08:46 +0200 Subject: [PATCH 1458/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.20.3 (#1799) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 7aece5e12991..80ebd18000b6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.2 + 1.20.3 import pom From 36b3606952778b0d3c48ef7f07a0526d56e3242e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Oct 2024 21:45:40 +0200 Subject: [PATCH 1459/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.38.0 (#1800) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 514cb3ada267..df0f89410508 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.37.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.38.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 0f8b919c91f6..9a49f7df62e7 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.37.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.38.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index e6553bd6e418..e434ee684728 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.37.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.38.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 180a187a7b5a..9defc60392f9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.37.0 + 3.38.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index c577bf4278b5..4ab006e03807 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.37.0 + 3.38.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a93c28a1f3a4..16d2dce5c6f5 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.37.0 + 3.38.0 From 79ab5f6f48d77a3595382632b05020555fabad85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 25 Oct 2024 11:24:07 +0200 Subject: [PATCH 1460/1979] feat: auto_batch_dml methods + combination with JDBC batching (#1795) * feat: auto_batch_dml methods + combination with JDBC batching Adds methods for enabling/disabling auto_batch_dml. Also enables the use of this feature in combination with other JDBC batches. This again allows PreparedStatement#addBatch() and Statement#addBatch(String) to be used in combination with auto_batch_dml. This again makes it usable in combination with frameworks like Hibernate. * test: remove expected error from test * chore: add clirr diffs --- .../clirr-ignored-differences.xml | 32 ++ .../jdbc/CloudSpannerJdbcConnection.java | 51 +++ .../cloud/spanner/jdbc/JdbcConnection.java | 30 ++ .../cloud/spanner/jdbc/JdbcStatement.java | 12 - .../jdbc/AutoBatchDmlMockServerTest.java | 332 ++++++++++++++++++ .../jdbc/it/ITJdbcSimpleStatementsTest.java | 25 +- 6 files changed, 455 insertions(+), 27 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutoBatchDmlMockServerTest.java diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index 431f54069b84..e82c99291022 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -76,4 +76,36 @@ 8001 com/google/cloud/spanner/connection/ConnectionHelper + + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isAutoBatchDml() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setAutoBatchDml(boolean) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + long getAutoBatchDmlUpdateCount() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setAutoBatchDmlUpdateCount(long) + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + boolean isAutoBatchDmlUpdateCountVerification() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + void setAutoBatchDmlUpdateCountVerification(boolean) + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 6795054d99fc..b8491d12c52f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -406,6 +406,57 @@ default int getMaxPartitionedParallelism() throws SQLException { throw new UnsupportedOperationException(); } + /** + * Enables or disables automatic batching of DML statements. When enabled, DML statements that are + * executed on this connection will be buffered in memory instead of actually being executed. The + * buffered DML statements are flushed to Spanner when a statement that cannot be part of a DML + * batch is executed on the connection. This can be a query, a DDL statement with a THEN RETURN + * clause, or a Commit call. The update count that is returned for DML statements that are + * buffered is determined by the value that has been set with {@link + * #setAutoBatchDmlUpdateCount(long)}. The default is 1. The connection verifies that the update + * counts that were returned while buffering DML statements match the actual update counts that + * are returned by Spanner when the batch is executed. This verification can be disabled by + * calling {@link #setAutoBatchDmlUpdateCountVerification(boolean)}. + */ + default void setAutoBatchDml(boolean autoBatchDml) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** Returns whether automatic DML batching is enabled on this connection. */ + default boolean isAutoBatchDml() throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets the update count that is returned for DML statements that are buffered during an automatic + * DML batch. This value is only used if {@link #isAutoBatchDml()} is enabled. + */ + default void setAutoBatchDmlUpdateCount(long updateCount) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Returns the update count that is returned for DML statements that are buffered during an + * automatic DML batch. + */ + default long getAutoBatchDmlUpdateCount() throws SQLException { + throw new UnsupportedOperationException(); + } + + /** + * Sets whether the update count that is returned by Spanner after executing an automatic DML + * batch should be verified against the update counts that were returned during the buffering of + * those statements. + */ + default void setAutoBatchDmlUpdateCountVerification(boolean verification) throws SQLException { + throw new UnsupportedOperationException(); + } + + /** Indicates whether the update counts of automatic DML batches should be verified. */ + default boolean isAutoBatchDmlUpdateCountVerification() throws SQLException { + throw new UnsupportedOperationException(); + } + /** * @see * com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index 26b381dd27a5..e603c29ac2fb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -770,6 +770,36 @@ public int getMaxPartitionedParallelism() throws SQLException { return get(Connection::getMaxPartitionedParallelism); } + @Override + public void setAutoBatchDml(boolean autoBatchDml) throws SQLException { + set(Connection::setAutoBatchDml, autoBatchDml); + } + + @Override + public boolean isAutoBatchDml() throws SQLException { + return get(Connection::isAutoBatchDml); + } + + @Override + public void setAutoBatchDmlUpdateCount(long updateCount) throws SQLException { + set(Connection::setAutoBatchDmlUpdateCount, updateCount); + } + + @Override + public long getAutoBatchDmlUpdateCount() throws SQLException { + return get(Connection::getAutoBatchDmlUpdateCount); + } + + @Override + public void setAutoBatchDmlUpdateCountVerification(boolean verification) throws SQLException { + set(Connection::setAutoBatchDmlUpdateCountVerification, verification); + } + + @Override + public boolean isAutoBatchDmlUpdateCountVerification() throws SQLException { + return get(Connection::isAutoBatchDmlUpdateCountVerification); + } + @SuppressWarnings("deprecation") private static final class JdbcToSpannerTransactionRetryListener implements com.google.cloud.spanner.connection.TransactionRetryListener { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 19b32565419f..5d8dfd9ee26b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -391,7 +391,6 @@ private BatchType determineStatementBatchType(String sql) throws SQLException { * client side statement) or if the connection of this statement has an active batch. */ void checkAndSetBatchType(String sql) throws SQLException { - checkConnectionHasNoActiveBatch(); BatchType type = determineStatementBatchType(sql); if (this.currentBatchType == BatchType.NONE) { this.currentBatchType = type; @@ -401,15 +400,6 @@ void checkAndSetBatchType(String sql) throws SQLException { } } - private void checkConnectionHasNoActiveBatch() throws SQLException { - if (getConnection().getSpannerConnection().isDdlBatchActive() - || getConnection().getSpannerConnection().isDmlBatchActive()) { - throw JdbcSqlExceptionFactory.of( - "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection.", - Code.FAILED_PRECONDITION); - } - } - @Override public void addBatch(String sql) throws SQLException { checkClosed(); @@ -420,7 +410,6 @@ public void addBatch(String sql) throws SQLException { @Override public void clearBatch() throws SQLException { checkClosed(); - checkConnectionHasNoActiveBatch(); batchedStatements.clear(); this.currentBatchType = BatchType.NONE; } @@ -436,7 +425,6 @@ public long[] executeLargeBatch() throws SQLException { private long[] executeBatch(boolean large) throws SQLException { checkClosed(); - checkConnectionHasNoActiveBatch(); StatementTimeout originalTimeout = setTemporaryStatementTimeout(); try { switch (this.currentBatchType) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutoBatchDmlMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutoBatchDmlMockServerTest.java new file mode 100644 index 000000000000..8ba1a3c0bc8b --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AutoBatchDmlMockServerTest.java @@ -0,0 +1,332 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.concurrent.ThreadLocalRandom; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AutoBatchDmlMockServerTest extends AbstractMockServerTest { + private static final String NON_PARAMETERIZED_INSERT = + "insert into foo (id, value) values (1, 'One')"; + private static final String NON_PARAMETERIZED_UPDATE = "update foo set value='Zero' where id=0"; + private static final String PARAMETERIZED_INSERT = + "insert into foo (id, value) values (@p1, @p2)"; + private static final String PARAMETERIZED_UPDATE = "update foo set value=@p1 where id=@p2"; + + @BeforeClass + public static void setup() { + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.of(NON_PARAMETERIZED_INSERT), 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.of(NON_PARAMETERIZED_UPDATE), 1L)); + + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.newBuilder(PARAMETERIZED_INSERT) + .bind("p1") + .to(1L) + .bind("p2") + .to("One") + .build(), + 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.newBuilder(PARAMETERIZED_INSERT) + .bind("p1") + .to(2L) + .bind("p2") + .to("Two") + .build(), + 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.newBuilder(PARAMETERIZED_UPDATE) + .bind("p2") + .to(1L) + .bind("p1") + .to("One") + .build(), + 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.newBuilder(PARAMETERIZED_UPDATE) + .bind("p2") + .to(2L) + .bind("p1") + .to("Two") + .build(), + 1L)); + } + + @After + public void clearRequests() { + mockSpanner.clearRequests(); + } + + @Test + public void testStatementExecute() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (Statement statement = connection.createStatement()) { + assertFalse(statement.execute(NON_PARAMETERIZED_INSERT)); + assertFalse(statement.execute(NON_PARAMETERIZED_UPDATE)); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testStatementExecuteUpdate() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeUpdate(NON_PARAMETERIZED_INSERT)); + assertEquals(1, statement.executeUpdate(NON_PARAMETERIZED_UPDATE)); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testStatementBatch() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (Statement statement = connection.createStatement()) { + repeat( + () -> { + statement.addBatch(NON_PARAMETERIZED_INSERT); + statement.addBatch(NON_PARAMETERIZED_UPDATE); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + }, + 2); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testStatementCombination() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (Statement statement = connection.createStatement()) { + statement.executeUpdate(NON_PARAMETERIZED_UPDATE); + repeat( + () -> { + statement.addBatch(NON_PARAMETERIZED_INSERT); + statement.addBatch(NON_PARAMETERIZED_UPDATE); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + }, + ThreadLocalRandom.current().nextInt(1, 5)); + repeat( + () -> { + statement.execute(NON_PARAMETERIZED_INSERT); + statement.executeUpdate(NON_PARAMETERIZED_UPDATE); + }, + ThreadLocalRandom.current().nextInt(1, 5)); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testPreparedStatementExecute() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + assertFalse(statement.execute()); + statement.setLong(1, 2L); + statement.setString(2, "Two"); + assertFalse(statement.execute()); + } + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_UPDATE)) { + statement.setLong(2, 1L); + statement.setString(1, "One"); + assertFalse(statement.execute()); + statement.setLong(2, 2L); + statement.setString(1, "Two"); + assertFalse(statement.execute()); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testPreparedStatementExecuteUpdate() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + assertEquals(1, statement.executeUpdate()); + statement.setLong(1, 2L); + statement.setString(2, "Two"); + assertEquals(1, statement.executeUpdate()); + } + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_UPDATE)) { + statement.setLong(2, 1L); + statement.setString(1, "One"); + assertEquals(1, statement.executeUpdate()); + statement.setLong(2, 2L); + statement.setString(1, "Two"); + assertEquals(1, statement.executeUpdate()); + } + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testPreparedStatementBatch() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + repeat( + () -> { + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + statement.addBatch(); + statement.setLong(1, 2L); + statement.setString(2, "Two"); + statement.addBatch(); + statement.executeBatch(); + } + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_UPDATE)) { + statement.setLong(2, 1L); + statement.setString(1, "One"); + statement.addBatch(); + statement.setLong(2, 2L); + statement.setString(1, "Two"); + statement.addBatch(); + statement.executeBatch(); + } + }, + 2); + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testPreparedStatementCombination() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + connection.unwrap(CloudSpannerJdbcConnection.class).setAutoBatchDml(true); + + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + assertFalse(statement.execute()); + } + repeat( + () -> { + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + statement.addBatch(); + statement.setLong(1, 2L); + statement.setString(2, "Two"); + statement.addBatch(); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_UPDATE)) { + statement.setLong(2, 1L); + statement.setString(1, "One"); + statement.addBatch(); + statement.setLong(2, 2L); + statement.setString(1, "Two"); + statement.addBatch(); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + }, + ThreadLocalRandom.current().nextInt(1, 5)); + repeat( + () -> { + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_INSERT)) { + statement.setLong(1, 1L); + statement.setString(2, "One"); + assertEquals(1, statement.executeUpdate()); + } + try (PreparedStatement statement = connection.prepareStatement(PARAMETERIZED_UPDATE)) { + statement.setLong(2, 2L); + statement.setString(1, "Two"); + assertFalse(statement.execute()); + } + }, + ThreadLocalRandom.current().nextInt(1, 5)); + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + interface SQLRunnable { + void run() throws SQLException; + } + + static void repeat(SQLRunnable runnable, int count) throws SQLException { + for (int i = 0; i < count; i++) { + runnable.run(); + } + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java index f6948a9c2942..7dd7153e4507 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcSimpleStatementsTest.java @@ -17,11 +17,11 @@ package com.google.cloud.spanner.jdbc.it; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; 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.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; @@ -102,12 +102,6 @@ public void testSelect1PreparedStatement() throws SQLException { @Test public void testPreparedStatement() throws SQLException { - // skipping the test when dialect is POSTGRESQL because of exception below - // INVALID_ARGUMENT: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Statements with set - // operations in subqueries are not supported - assumeFalse( - "select array of structs is not supported on POSTGRESQL", - dialect.dialect == Dialect.POSTGRESQL); String sql = "select * from (select 1 as number union all select 2 union all select 3) numbers where number=?"; try (Connection connection = createConnection(env, database)) { @@ -188,15 +182,16 @@ public void testBatchedDdlStatements() throws SQLException { } @Test - public void testAddBatchWhenAlreadyInBatch() { + public void testAddBatchWhenAlreadyInBatch() throws SQLException { try (Connection connection = createConnection(env, database)) { - connection.createStatement().execute("START BATCH DML"); - connection.createStatement().addBatch("INSERT INTO Singers (SingerId) VALUES (-1)"); - fail("missing expected exception"); - } catch (SQLException e) { - assertThat(e.getMessage()) - .contains( - "Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection."); + try (Statement statement = connection.createStatement()) { + statement.execute("START BATCH DML"); + statement.addBatch("INSERT INTO Singers (SingerId) VALUES (-1)"); + statement.addBatch("INSERT INTO Singers (SingerId) VALUES (-2)"); + // The returned update count for DML statements in a batch is -1. + assertArrayEquals(new int[] {-1, -1}, statement.executeBatch()); + // Note: The 'Singers' table does not actually exist, so we're not executing the batch. + } } } From 72da7317b28d80d2be06d75ebff52c7c7d3ba181 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 11:42:18 +0200 Subject: [PATCH 1461/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.0 (#1804) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9defc60392f9..130335dd3b15 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.79.0 + 6.80.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 4ea50f09c468..0ad39967c6be 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.79.0 + 6.80.0 import pom From 7347fde241be8d780690e9707baec9904ffe7bb8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 11:42:31 +0200 Subject: [PATCH 1462/1979] deps: update dependency org.springframework.boot:spring-boot to v3.3.5 (#1801) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4ab006e03807..98efb3eaf758 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.3.4 + 3.3.5 test From a302f0cdf452c8c9a005d4509a6364abc8da0027 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 11:42:45 +0200 Subject: [PATCH 1463/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.5 (#1802) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 0ad39967c6be..bd11b7f51373 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.4 + 3.3.5 From 6bf78aff6f8c0c1fa3c826b414fe572ba2e3dbc5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 11:42:57 +0200 Subject: [PATCH 1464/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.5 (#1803) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 80ebd18000b6..c41cc3664688 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.4 + 3.3.5 From 4338f0dfac8c912b51116664f26083b16fadf60d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:10:24 +0000 Subject: [PATCH 1465/1979] chore(main): release 2.24.0 (#1794) :robot: I have created a release *beep* *boop* --- ## [2.24.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.23.0...v2.24.0) (2024-10-25) ### Features * Auto_batch_dml methods + combination with JDBC batching ([#1795](https://togithub.com/googleapis/java-spanner-jdbc/issues/1795)) ([79ab5f6](https://togithub.com/googleapis/java-spanner-jdbc/commit/79ab5f6f48d77a3595382632b05020555fabad85)) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.0 ([#1804](https://togithub.com/googleapis/java-spanner-jdbc/issues/1804)) ([72da731](https://togithub.com/googleapis/java-spanner-jdbc/commit/72da7317b28d80d2be06d75ebff52c7c7d3ba181)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.38.0 ([#1800](https://togithub.com/googleapis/java-spanner-jdbc/issues/1800)) ([36b3606](https://togithub.com/googleapis/java-spanner-jdbc/commit/36b3606952778b0d3c48ef7f07a0526d56e3242e)) * Update dependency org.springframework.boot:spring-boot to v3.3.5 ([#1801](https://togithub.com/googleapis/java-spanner-jdbc/issues/1801)) ([7347fde](https://togithub.com/googleapis/java-spanner-jdbc/commit/7347fde241be8d780690e9707baec9904ffe7bb8)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.5 ([#1802](https://togithub.com/googleapis/java-spanner-jdbc/issues/1802)) ([a302f0c](https://togithub.com/googleapis/java-spanner-jdbc/commit/a302f0cdf452c8c9a005d4509a6364abc8da0027)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.5 ([#1803](https://togithub.com/googleapis/java-spanner-jdbc/issues/1803)) ([6bf78af](https://togithub.com/googleapis/java-spanner-jdbc/commit/6bf78aff6f8c0c1fa3c826b414fe572ba2e3dbc5)) * Update dependency org.springframework.data:spring-data-bom to v2024.0.5 ([#1793](https://togithub.com/googleapis/java-spanner-jdbc/issues/1793)) ([98caf42](https://togithub.com/googleapis/java-spanner-jdbc/commit/98caf42b17248ae023cc434012003a2f7b4c7b61)) * Update dependency org.testcontainers:testcontainers to v1.20.3 ([#1798](https://togithub.com/googleapis/java-spanner-jdbc/issues/1798)) ([fac650d](https://togithub.com/googleapis/java-spanner-jdbc/commit/fac650d8af3299d44d4f8633e92e2993cd875d68)) * Update dependency org.testcontainers:testcontainers-bom to v1.20.3 ([#1799](https://togithub.com/googleapis/java-spanner-jdbc/issues/1799)) ([5c382cd](https://togithub.com/googleapis/java-spanner-jdbc/commit/5c382cdc79ca99357a7f642c03941bdc6ac21ce9)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 19 +++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 3f5be174e84a..6fe726c517d2 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [2.24.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.23.0...v2.24.0) (2024-10-25) + + +### Features + +* Auto_batch_dml methods + combination with JDBC batching ([#1795](https://github.com/googleapis/java-spanner-jdbc/issues/1795)) ([98f01bb](https://github.com/googleapis/java-spanner-jdbc/commit/98f01bba45ec299182d0501c8f43e161d14cf78b)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.0 ([#1804](https://github.com/googleapis/java-spanner-jdbc/issues/1804)) ([55d6eef](https://github.com/googleapis/java-spanner-jdbc/commit/55d6eef81026d3dd94d80c4cab004152a82e2e67)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.38.0 ([#1800](https://github.com/googleapis/java-spanner-jdbc/issues/1800)) ([f52a087](https://github.com/googleapis/java-spanner-jdbc/commit/f52a087f72b0fab8193ecaec454c52ee71ebcda3)) +* Update dependency org.springframework.boot:spring-boot to v3.3.5 ([#1801](https://github.com/googleapis/java-spanner-jdbc/issues/1801)) ([44b756d](https://github.com/googleapis/java-spanner-jdbc/commit/44b756db18c79d2ae7fc01150cea33c411f5afbc)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.3.5 ([#1802](https://github.com/googleapis/java-spanner-jdbc/issues/1802)) ([7709c98](https://github.com/googleapis/java-spanner-jdbc/commit/7709c988043e06b15e6ace6a6759594bbfeeace8)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.3.5 ([#1803](https://github.com/googleapis/java-spanner-jdbc/issues/1803)) ([c452a37](https://github.com/googleapis/java-spanner-jdbc/commit/c452a375be26f2d43e1d76056bd45d486340c73f)) +* Update dependency org.springframework.data:spring-data-bom to v2024.0.5 ([#1793](https://github.com/googleapis/java-spanner-jdbc/issues/1793)) ([5bd5a0a](https://github.com/googleapis/java-spanner-jdbc/commit/5bd5a0a086a8e38709a851cdd2fbb2bc28dbe3a5)) +* Update dependency org.testcontainers:testcontainers to v1.20.3 ([#1798](https://github.com/googleapis/java-spanner-jdbc/issues/1798)) ([c643c33](https://github.com/googleapis/java-spanner-jdbc/commit/c643c3365f435db2b04a001ce0b9bbb997e2b4f3)) +* Update dependency org.testcontainers:testcontainers-bom to v1.20.3 ([#1799](https://github.com/googleapis/java-spanner-jdbc/issues/1799)) ([da1acfc](https://github.com/googleapis/java-spanner-jdbc/commit/da1acfc1e63d8afe4a4c5a51e2f155cd42d89e1d)) + ## [2.23.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.22.1...v2.23.0) (2024-10-12) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 394ea4e53610..71634a47b883 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.23.0 + 2.24.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.23.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.23.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 130335dd3b15..0a53dee60170 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.23.1-SNAPSHOT + 2.24.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fe356998317b..92c3a941ed8e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.23.1-SNAPSHOT + 2.24.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index aecd67200b3f..95d9f226d0a9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.23.0:2.23.1-SNAPSHOT +google-cloud-spanner-jdbc:2.24.0:2.24.0 From fd56dad244e3064247111ad89df52b8d056abc12 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:42:24 +0000 Subject: [PATCH 1466/1979] chore(main): release 2.24.1-SNAPSHOT (#1805) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0a53dee60170..6a6cde2d3c26 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.0 + 2.24.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 92c3a941ed8e..876b905cacbe 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.0 + 2.24.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 95d9f226d0a9..8d8ae2625859 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.0:2.24.0 +google-cloud-spanner-jdbc:2.24.0:2.24.1-SNAPSHOT From 78d7877ddd3f4d1b95a583ce96f9ee6302845009 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Oct 2024 15:37:21 +0200 Subject: [PATCH 1467/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.24.0 (#1806) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 223c797a6c22..201d023603eb 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.23.0 + 2.24.0 From cd1be3124f843146d8a6d867908e730cae566b39 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 26 Oct 2024 11:26:35 +0200 Subject: [PATCH 1468/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.39.0 (#1808) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index df0f89410508..60caac52f468 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.38.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.39.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 9a49f7df62e7..5f84dd393a1b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.38.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.39.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index e434ee684728..418a399b7599 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.38.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.39.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6a6cde2d3c26..a541e6146340 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.38.0 + 3.39.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 98efb3eaf758..a00a0325dfdc 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.38.0 + 3.39.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 16d2dce5c6f5..c411d64089a5 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.38.0 + 3.39.0 From 83a90b865c277c0a356e5f3b460a36e6054793b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 28 Oct 2024 09:57:51 +0100 Subject: [PATCH 1469/1979] docs: add metrics exporter to sample app (#1809) Add a metrics exporter to the sample application to show how to export both traces and metrics when using the JDBC driver. --- .../samples/spring-data-jdbc/pom.xml | 5 +++++ .../sample/OpenTelemetryConfiguration.java | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index bd11b7f51373..9985d0937c09 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -85,6 +85,11 @@ exporter-trace 0.33.0 + + com.google.cloud.opentelemetry + exporter-metrics + 0.33.0 + com.google.collections diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java index 27614a2fec3e..b833e48b7c50 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java @@ -17,12 +17,17 @@ package com.google.cloud.spanner.sample; import com.google.auth.oauth2.GoogleCredentials; +import com.google.cloud.opentelemetry.metric.GoogleCloudMetricExporter; +import com.google.cloud.opentelemetry.metric.MetricConfiguration; import com.google.cloud.opentelemetry.trace.TraceConfiguration; import com.google.cloud.opentelemetry.trace.TraceExporter; import com.google.cloud.spanner.SpannerOptions; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; @@ -51,6 +56,7 @@ public OpenTelemetry openTelemetry() { // Enable OpenTelemetry tracing in Spanner. SpannerOptions.enableOpenTelemetryTraces(); + SpannerOptions.enableOpenTelemetryMetrics(); if (!hasDefaultCredentials()) { // Create a no-op OpenTelemetry object if this environment does not have any default @@ -63,6 +69,17 @@ public OpenTelemetry openTelemetry() { TraceConfiguration traceConfiguration = traceConfigurationBuilder.setProjectId(project).build(); SpanExporter traceExporter = TraceExporter.createWithConfiguration(traceConfiguration); + MetricConfiguration.Builder metricConfigurationBuilder = MetricConfiguration.builder(); + MetricConfiguration metricConfiguration = + metricConfigurationBuilder.setProjectId(project).build(); + MetricExporter metricExporter = + GoogleCloudMetricExporter.createWithConfiguration(metricConfiguration); + + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .registerMetricReader(PeriodicMetricReader.builder(metricExporter).build()) + .build(); + // Create an OpenTelemetry object and register it as the global OpenTelemetry object. This // will automatically be picked up by the Spanner libraries and used for tracing. return OpenTelemetrySdk.builder() @@ -81,6 +98,7 @@ public OpenTelemetry openTelemetry() { .build()) .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) .build()) + .setMeterProvider(sdkMeterProvider) .buildAndRegisterGlobal(); } From 72554d21ebecadc75c6a7a7fc21da1e3be71736f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Oct 2024 16:37:40 +0100 Subject: [PATCH 1470/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.1 (#1811) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a541e6146340..91d12f2571ee 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.80.0 + 6.80.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 9985d0937c09..8b0e2d102ede 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.80.0 + 6.80.1 import pom From d17ca6512fedb0d73d317f60ebc26e8b6a19cecf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:43:41 +0100 Subject: [PATCH 1471/1979] chore(main): release 2.24.1 (#1810) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 6fe726c517d2..e5832379e243 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.24.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.0...v2.24.1) (2024-10-28) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.1 ([#1811](https://github.com/googleapis/java-spanner-jdbc/issues/1811)) ([d6ee2e9](https://github.com/googleapis/java-spanner-jdbc/commit/d6ee2e98b067f6b1e35d07e8f7bf0a371649f5ee)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.39.0 ([#1808](https://github.com/googleapis/java-spanner-jdbc/issues/1808)) ([efdd859](https://github.com/googleapis/java-spanner-jdbc/commit/efdd8596fe716ec925bf5dcc87a84a2bf2cdc9a2)) + + +### Documentation + +* Add metrics exporter to sample app ([#1809](https://github.com/googleapis/java-spanner-jdbc/issues/1809)) ([9b89f20](https://github.com/googleapis/java-spanner-jdbc/commit/9b89f20183783c9e169fbad408b3df93291fd18c)) + ## [2.24.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.23.0...v2.24.0) (2024-10-25) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 71634a47b883..10a587c79a3e 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.24.0 + 2.24.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 91d12f2571ee..38e5b3cc9f59 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.1-SNAPSHOT + 2.24.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 876b905cacbe..0a561b6fc175 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.1-SNAPSHOT + 2.24.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 8d8ae2625859..9fc28952c917 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.0:2.24.1-SNAPSHOT +google-cloud-spanner-jdbc:2.24.1:2.24.1 From 98253feaaad703150f053fd2befdb4f49a48f07c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Oct 2024 08:40:52 +0100 Subject: [PATCH 1472/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.24.1 (#1814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.24.0` -> `2.24.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.24.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.24.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.24.0/2.24.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.24.0/2.24.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.24.1`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2241-2024-10-28) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.24.0...v2.24.1) ##### Dependencies - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.1 ([#​1811](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1811)) ([72554d2](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/72554d21ebecadc75c6a7a7fc21da1e3be71736f)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.39.0 ([#​1808](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1808)) ([cd1be31](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/cd1be3124f843146d8a6d867908e730cae566b39)) ##### Documentation - Add metrics exporter to sample app ([#​1809](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1809)) ([83a90b8](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/83a90b865c277c0a356e5f3b460a36e6054793b0))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 201d023603eb..af50a928d3fa 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.0 + 2.24.1 From 2a1f9531fb348640e0b87dec58abf60f524140be Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Oct 2024 08:42:26 +0100 Subject: [PATCH 1473/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.53.0 (#1816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.52.0` -> `2.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.52.0/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.52.0/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 38e5b3cc9f59..5cfdc0306145 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -238,7 +238,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.52.0 + 2.53.0 test From 6e2ddb7ef9d73d40effaed7947c754782e35696b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Oct 2024 08:44:26 +0100 Subject: [PATCH 1474/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.53.0 (#1817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.52.0` -> `2.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.52.0/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.52.0/2.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5cfdc0306145..27720a97fd2d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -232,7 +232,7 @@ com.google.cloud google-cloud-trace - 2.52.0 + 2.53.0 test From 5b81a8c78f8717fabcd2d29453ff532806deb7a7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Oct 2024 21:32:46 +0100 Subject: [PATCH 1475/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.1 (#1815) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index a00a0325dfdc..2bf7a078b46a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.18.0 + 2.18.1 From cd213dec847610af638a6a9084807b5b76940e90 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:44:27 +0000 Subject: [PATCH 1476/1979] chore(main): release 2.24.2-SNAPSHOT (#1813) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 27720a97fd2d..0aaa283c733d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.1 + 2.24.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0a561b6fc175..aef391185f64 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.1 + 2.24.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9fc28952c917..04ca2cf9d80f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.1:2.24.1 +google-cloud-spanner-jdbc:2.24.1:2.24.2-SNAPSHOT From ecb53eeb27cc1304d36c1a31ce0bd44452551b24 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 9 Nov 2024 08:02:21 +0100 Subject: [PATCH 1477/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.44.0 (#1822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://redirect.github.com/open-telemetry/opentelemetry-java) | `1.43.0` -> `1.44.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.43.0/1.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.43.0/1.44.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.44.0`](https://redirect.github.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1440-2024-11-08) ##### API - Fix ConfigUtil#getString ConcurrentModificationException ([#​6841](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6841)) ##### SDK ##### Traces - Stabilize ExceptionEventData ([#​6795](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6795)) ##### Metrics - Stabilize metric cardinality limits ([#​6794](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6794)) - Refactor metrics internals to remove MeterSharedState ([#​6845](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6845)) ##### Exporters - Add memory mode option to stdout exporters ([#​6774](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6774)) - Log a warning if OTLP endpoint port is likely incorrect given the protocol ([#​6813](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6813)) - Fix OTLP gRPC retry mechanism for unsuccessful HTTP responses ([#​6829](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6829)) - Add ByteBuffer field type marshaling support ([#​6686](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6686)) - Fix stdout exporter format by adding newline after each export ([#​6848](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6848)) - Enable `reusuable_data` memory mode by default for `OtlpGrpc{Signal}Exporter`, `OtlpHttp{Signal}Exporter`, `OtlpStdout{Signal}Exporter`, and `PrometheusHttpServer` ([#​6799](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6799)) ##### Extension - Rebrand file configuration to declarative configuration in documentation ([#​6812](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6812)) - Fix declarative config `file_format` validation ([#​6786](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6786)) - Fix declarative config env substitution by disallowing '}' in default value ([#​6793](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6793)) - Set declarative config default OTLP protocol to http/protobuf ([#​6800](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6800)) - Stabilize autoconfigure disabling of resource keys via `otel.resource.disabled.keys` ([#​6809](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6809)) ##### Tooling - Run tests on Java 23 ([#​6825](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6825)) - Test Windows in CI ([#​6824](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6824)) - Add error prone checks for internal javadoc and private constructors ([#​6844](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6844))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 8b0e2d102ede..9ef4b1ace605 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.43.0 + 1.44.0 pom import From 576cc75fdc5d13a9a6db6d60a8169bc2ffb2768d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 9 Nov 2024 08:04:21 +0100 Subject: [PATCH 1478/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.50.0 (#1820) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.49.0` -> `26.50.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.49.0/26.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.49.0/26.50.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.50.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26500-2024-10-31) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.49.0...v26.50.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.38.0 ([#​6812](https://redirect.github.com/googleapis/java-cloud-bom/issues/6812)) ([73ea7ac](https://redirect.github.com/googleapis/java-cloud-bom/commit/73ea7ac7e9f214a69c1bfd7fd9e8e1bf1880c02f)) - update dependency com.google.cloud:first-party-dependencies to v3.39.0 ([#​6820](https://redirect.github.com/googleapis/java-cloud-bom/issues/6820)) ([6746f15](https://redirect.github.com/googleapis/java-cloud-bom/commit/6746f15cf20ae2be92fdece7ee4573b684e922b4)) - update dependency com.google.cloud:gapic-libraries-bom to v1.47.0 ([#​6811](https://redirect.github.com/googleapis/java-cloud-bom/issues/6811)) ([95d68ee](https://redirect.github.com/googleapis/java-cloud-bom/commit/95d68ee4ebd05041e2a6ec7534a0fe6c1a9d946a)) - update dependency com.google.cloud:google-cloud-bigquery to v2.43.2 ([#​6825](https://redirect.github.com/googleapis/java-cloud-bom/issues/6825)) ([eb611f0](https://redirect.github.com/googleapis/java-cloud-bom/commit/eb611f06321d57c653b9d48142cecd25dd0a6c2b)) - update dependency com.google.cloud:google-cloud-bigquery to v2.43.3 ([#​6830](https://redirect.github.com/googleapis/java-cloud-bom/issues/6830)) ([6df5fd2](https://redirect.github.com/googleapis/java-cloud-bom/commit/6df5fd2455aa3f33a9adaf2352f41024028aa016)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.10.0 ([#​6815](https://redirect.github.com/googleapis/java-cloud-bom/issues/6815)) ([c8586d6](https://redirect.github.com/googleapis/java-cloud-bom/commit/c8586d6b574e85712136390ebe41321fa8f11d8d)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.10.1 ([#​6822](https://redirect.github.com/googleapis/java-cloud-bom/issues/6822)) ([cd4c57b](https://redirect.github.com/googleapis/java-cloud-bom/commit/cd4c57b770cd374957138a71a0c9c54cc95cbd43)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.10.2 ([#​6826](https://redirect.github.com/googleapis/java-cloud-bom/issues/6826)) ([39c5c2f](https://redirect.github.com/googleapis/java-cloud-bom/commit/39c5c2f2328776ce12ede33a86e7279a6d252fa5)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.46.0 ([#​6833](https://redirect.github.com/googleapis/java-cloud-bom/issues/6833)) ([9cc59ba](https://redirect.github.com/googleapis/java-cloud-bom/commit/9cc59baf594b47ea7737a75ff1ea9f53a93ce2c7)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.24.1 ([#​6831](https://redirect.github.com/googleapis/java-cloud-bom/issues/6831)) ([af20e1e](https://redirect.github.com/googleapis/java-cloud-bom/commit/af20e1eb638ec185e307fead9749b584d9155648)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.27.4 ([#​6808](https://redirect.github.com/googleapis/java-cloud-bom/issues/6808)) ([cf24d46](https://redirect.github.com/googleapis/java-cloud-bom/commit/cf24d465ef16d32eb408756226f848700dc0f6a7)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.28.0 ([#​6834](https://redirect.github.com/googleapis/java-cloud-bom/issues/6834)) ([2d2b829](https://redirect.github.com/googleapis/java-cloud-bom/commit/2d2b829aa741fa7b13c894cbfc89e92b80267489)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.20.5 ([#​6814](https://redirect.github.com/googleapis/java-cloud-bom/issues/6814)) ([7bdfa93](https://redirect.github.com/googleapis/java-cloud-bom/commit/7bdfa930a25dc04f671057920c58327f3c477814)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.20.6 ([#​6823](https://redirect.github.com/googleapis/java-cloud-bom/issues/6823)) ([87ef81e](https://redirect.github.com/googleapis/java-cloud-bom/commit/87ef81e750effd5e2bbaf58535590874728daaf3)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.131.16-alpha ([#​6827](https://redirect.github.com/googleapis/java-cloud-bom/issues/6827)) ([476cc06](https://redirect.github.com/googleapis/java-cloud-bom/commit/476cc06f117d7967cb079f4e591983d512da61f1)) - update dependency com.google.cloud:google-cloud-nio to v0.127.26 ([#​6835](https://redirect.github.com/googleapis/java-cloud-bom/issues/6835)) ([2c49bcf](https://redirect.github.com/googleapis/java-cloud-bom/commit/2c49bcfe0a415e8255a7c9b3cc94951177a1da92)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.134.0 ([#​6816](https://redirect.github.com/googleapis/java-cloud-bom/issues/6816)) ([9efd1b0](https://redirect.github.com/googleapis/java-cloud-bom/commit/9efd1b0777c06fd85d2be4b70bfa86f3855bcb6b)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.134.1 ([#​6828](https://redirect.github.com/googleapis/java-cloud-bom/issues/6828)) ([d02b9b5](https://redirect.github.com/googleapis/java-cloud-bom/commit/d02b9b5e6ceb6ab46d93716800180f0695fa0ee6)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.14.7 ([#​6838](https://redirect.github.com/googleapis/java-cloud-bom/issues/6838)) ([88b0c80](https://redirect.github.com/googleapis/java-cloud-bom/commit/88b0c809fbae4ec42cd8f3a204c4e8c4264e64b3)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.0 ([#​6818](https://redirect.github.com/googleapis/java-cloud-bom/issues/6818)) ([e5ca0c9](https://redirect.github.com/googleapis/java-cloud-bom/commit/e5ca0c9c0e2d1492ac363d37d38ae1857bf7b085)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.80.1 ([#​6829](https://redirect.github.com/googleapis/java-cloud-bom/issues/6829)) ([0401269](https://redirect.github.com/googleapis/java-cloud-bom/commit/04012696b2e7ef516e39bcd5c5fb0005b6ace817)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.24.0 ([#​6819](https://redirect.github.com/googleapis/java-cloud-bom/issues/6819)) ([edc7c35](https://redirect.github.com/googleapis/java-cloud-bom/commit/edc7c352409869dea5dcb8d9bc0fdc0ffe1393ee)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.24.1 ([#​6824](https://redirect.github.com/googleapis/java-cloud-bom/issues/6824)) ([5413759](https://redirect.github.com/googleapis/java-cloud-bom/commit/541375972ce2d38c8ec4ffef19a2f8311989c98c)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.44.0 ([#​6813](https://redirect.github.com/googleapis/java-cloud-bom/issues/6813)) ([caeedce](https://redirect.github.com/googleapis/java-cloud-bom/commit/caeedced555d1f3c50c66741f9ebc9acb113b879)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.44.1 ([#​6821](https://redirect.github.com/googleapis/java-cloud-bom/issues/6821)) ([063787d](https://redirect.github.com/googleapis/java-cloud-bom/commit/063787d29d80be71399a82a1b3f41fa6efc5e3a2))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2bf7a078b46a..64de55f470f9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.49.0 + 26.50.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c411d64089a5..15a6a1d2e67e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.49.0 + 26.50.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 9ef4b1ace605..b19a9d86e563 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.49.0 + 26.50.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index c41cc3664688..3f5983d5fdbb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.49.0 + 26.50.0 import pom From 114618d5edf280f70c39c8c202d9cb6398930c26 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 10 Nov 2024 12:04:10 +0100 Subject: [PATCH 1479/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.44.1 (#1823) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index b19a9d86e563..f59caad73423 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.44.0 + 1.44.1 pom import From 2b5cad39e70845eb1efd95f8aa278532e5ae5aae Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 18 Nov 2024 09:25:47 +0100 Subject: [PATCH 1480/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.40.0 (#1825) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 60caac52f468..3efa76d73be4 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.39.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.40.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 5f84dd393a1b..82ed3a43e49b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.39.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.40.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 418a399b7599..a836c97f04bd 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.39.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.40.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0aaa283c733d..a8a7f8bff19d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.39.0 + 3.40.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 64de55f470f9..ef6e6e9b66bb 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.39.0 + 3.40.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 15a6a1d2e67e..114c0f8e858b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.39.0 + 3.40.0 From 0eae7a3fad500c0a60bd76cfc57e3fe92a667fd5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 18 Nov 2024 09:26:05 +0100 Subject: [PATCH 1481/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.0 (#1826) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index f59caad73423..a87ad50e2680 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.0.5 + 2024.1.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 3f5983d5fdbb..df6f597f7b36 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.0.5 + 2024.1.0 import pom From 3f44e890af5d8dea1e95bb3f7d57257ea0966b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 18 Nov 2024 13:38:52 +0100 Subject: [PATCH 1482/1979] build: remove alpha test dependecy (#1828) --- java-spanner-jdbc/pom.xml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a8a7f8bff19d..cc596da035ad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -201,13 +201,6 @@
    - - - io.opentelemetry - opentelemetry-api-incubator - 1.40.0-alpha - test - io.opentelemetry opentelemetry-sdk @@ -368,6 +361,7 @@ com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1 + io.opentelemetry:opentelemetry-api-incubator From d6b842defc1ceeab6aaf85d7526879d9f0e9ec9d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Nov 2024 16:25:24 +0100 Subject: [PATCH 1483/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.81.1 (#1821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.81.1 * deps: move common dep up * deps: remove duplicate dependencies * deps: remove deps that are already in java-spanner --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 33 +++++++------------ .../samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cc596da035ad..65479d8e27ed 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.80.1 + 6.81.1 pom import @@ -200,38 +200,23 @@ test - - - io.opentelemetry - opentelemetry-sdk - test - - - io.opentelemetry - opentelemetry-sdk-common - test - - - io.opentelemetry - opentelemetry-sdk-trace - test - + com.google.cloud.opentelemetry exporter-trace - 0.33.0 + 0.32.0 test com.google.cloud google-cloud-trace - 2.53.0 + 2.52.0 test com.google.api.grpc proto-google-cloud-trace-v1 - 2.53.0 + 2.52.0 test @@ -361,7 +346,7 @@ com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1 - io.opentelemetry:opentelemetry-api-incubator + io.opentelemetry:* @@ -371,7 +356,13 @@ com.google.api.grpc:grpc-google-cloud-spanner-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1 com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1 + io.opentelemetry:* + + io.opentelemetry:* + com.google.cloud:google-cloud-trace + com.google.cloud.opentelemetry:exporter-trace +
    diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a87ad50e2680..5882816eb119 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.80.1 + 6.81.1 import pom From 2518e30e4a33fe7fb229091f3f03c449b7cfadca Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Nov 2024 16:44:52 +0100 Subject: [PATCH 1484/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.33.0 (#1832) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 65479d8e27ed..d43a499ec2d2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -204,7 +204,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.32.0 + 0.33.0 test From 14a3e8558082c9f140480192ff1f3a37eccb6b7c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Nov 2024 16:49:44 +0100 Subject: [PATCH 1485/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.54.0 (#1830) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d43a499ec2d2..5f71a5a22b81 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -210,7 +210,7 @@ com.google.cloud google-cloud-trace - 2.52.0 + 2.54.0 test From bda70388ec4850496d800a2306b83658c1b6690e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Nov 2024 16:50:02 +0100 Subject: [PATCH 1486/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.54.0 (#1831) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5f71a5a22b81..a5b11a30ab2d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.52.0 + 2.54.0 test From fd4fe8a8cb68ab3df6ec9ff1b68348a73373c2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 20 Nov 2024 16:55:54 +0100 Subject: [PATCH 1487/1979] deps: bump Spanner client to 6.81.2 (#1833) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a5b11a30ab2d..e7ca6f387198 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.81.1 + 6.81.2 pom import From 98354b81e175be93d7d9510951f5c1c5ec0fbb8e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:48:48 +0100 Subject: [PATCH 1488/1979] chore(main): release 2.24.2 (#1819) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e5832379e243..dfd86ef0b142 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.24.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.1...v2.24.2) (2024-11-20) + + +### Dependencies + +* Bump Spanner client to 6.81.2 ([#1833](https://github.com/googleapis/java-spanner-jdbc/issues/1833)) ([3b16c90](https://github.com/googleapis/java-spanner-jdbc/commit/3b16c9071cdab9b8f8d719ba6839a8bc5e1a2e8c)) +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.1 ([#1815](https://github.com/googleapis/java-spanner-jdbc/issues/1815)) ([f4a23e3](https://github.com/googleapis/java-spanner-jdbc/commit/f4a23e31b63a0f832b6a17fef9fcf8f02ae327d3)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.53.0 ([#1816](https://github.com/googleapis/java-spanner-jdbc/issues/1816)) ([cdaf7ee](https://github.com/googleapis/java-spanner-jdbc/commit/cdaf7ee8c34cc0bed6256daeb2ae0c6c2eb4e4d3)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.54.0 ([#1831](https://github.com/googleapis/java-spanner-jdbc/issues/1831)) ([41eafa7](https://github.com/googleapis/java-spanner-jdbc/commit/41eafa70ef8c75bb99c7f0058d1fea7f28e8a14b)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.81.1 ([#1821](https://github.com/googleapis/java-spanner-jdbc/issues/1821)) ([c314bad](https://github.com/googleapis/java-spanner-jdbc/commit/c314bada6f631020cbf0a956c0b4d3ddd2c1b9cb)) +* Update dependency com.google.cloud:google-cloud-trace to v2.53.0 ([#1817](https://github.com/googleapis/java-spanner-jdbc/issues/1817)) ([1cc543c](https://github.com/googleapis/java-spanner-jdbc/commit/1cc543c7898fbf1a3febb8f4142b1d40ad8873f8)) +* Update dependency com.google.cloud:google-cloud-trace to v2.54.0 ([#1830](https://github.com/googleapis/java-spanner-jdbc/issues/1830)) ([5df5752](https://github.com/googleapis/java-spanner-jdbc/commit/5df57523b7d5bdf1945dca4bbc5fea4a100cf47e)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.40.0 ([#1825](https://github.com/googleapis/java-spanner-jdbc/issues/1825)) ([cec5322](https://github.com/googleapis/java-spanner-jdbc/commit/cec53225a5dcd5bd0f5046346d99c6b2f82147b5)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.33.0 ([#1832](https://github.com/googleapis/java-spanner-jdbc/issues/1832)) ([3128451](https://github.com/googleapis/java-spanner-jdbc/commit/31284512d6de19121a8dd587b46921513dc62900)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.44.0 ([#1822](https://github.com/googleapis/java-spanner-jdbc/issues/1822)) ([40bf9e4](https://github.com/googleapis/java-spanner-jdbc/commit/40bf9e49bd6dad04efbb6f5178b4fa4e6efc2106)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.44.1 ([#1823](https://github.com/googleapis/java-spanner-jdbc/issues/1823)) ([ba8edfd](https://github.com/googleapis/java-spanner-jdbc/commit/ba8edfd7a344cb6e7806b057ec4a1d460062ed38)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.0 ([#1826](https://github.com/googleapis/java-spanner-jdbc/issues/1826)) ([66a7fc5](https://github.com/googleapis/java-spanner-jdbc/commit/66a7fc58405ad3c301ef056b3d20ff1237387cd4)) + ## [2.24.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.0...v2.24.1) (2024-10-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 10a587c79a3e..70bace0dea2a 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.24.1 + 2.24.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e7ca6f387198..420f3315eecc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.2-SNAPSHOT + 2.24.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index aef391185f64..3b4703db1b40 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.2-SNAPSHOT + 2.24.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 04ca2cf9d80f..45c90fc2824f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.1:2.24.2-SNAPSHOT +google-cloud-spanner-jdbc:2.24.2:2.24.2 From d12ada5d24e1be3141f073f40216cfec6ca5c7b6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:49:11 +0100 Subject: [PATCH 1489/1979] chore(main): release 2.24.3-SNAPSHOT (#1834) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 420f3315eecc..e9661fb3f8ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.2 + 2.24.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3b4703db1b40..a352583429b7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.2 + 2.24.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 45c90fc2824f..f34f4553bd90 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.2:2.24.2 +google-cloud-spanner-jdbc:2.24.2:2.24.3-SNAPSHOT From bf648ab0b80b8b46e0d264a0c185872e5ca0ba5e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 11:49:24 +0100 Subject: [PATCH 1490/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.4 (#1835) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e9661fb3f8ef..39ce893e1b51 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.3 + 1.20.4 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ef6e6e9b66bb..7d9ed71b8bbb 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.3 + 1.20.4 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 114c0f8e858b..36fbfb9b0b31 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.3 + 1.20.4 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5882816eb119..8dc0e66de7a9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.20.3 + 1.20.4 test From f2f07e461c6cd26bba2b09dc716f73dc86595c95 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 11:49:38 +0100 Subject: [PATCH 1491/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.20.4 (#1836) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index df6f597f7b36..3b6fde057d28 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.3 + 1.20.4 import pom From 5ea63a7f9cc6b38f97bf5352322ebf66ada924c5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 11:49:52 +0100 Subject: [PATCH 1492/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.81.2 (#1837) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 8dc0e66de7a9..2efaf42d9a3c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.81.1 + 6.81.2 import pom From 5fea8fcd938288a440573614c7840822bb407574 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 15:20:56 +0100 Subject: [PATCH 1493/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.0 (#1838) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 7d9ed71b8bbb..2bbb78057035 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.3.5 + 3.4.0 test From e65632f79a6b973ae5f214deaca4605a6ffe2415 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 15:21:09 +0100 Subject: [PATCH 1494/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.0 (#1839) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 3b6fde057d28..764d37a3ab19 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.5 + 3.4.0 From 944bae9ba261e325618f31734b404ad8cd950594 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Nov 2024 15:21:23 +0100 Subject: [PATCH 1495/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.0 (#1840) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2efaf42d9a3c..a0160bde1ee7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.3.5 + 3.4.0 From 7cfb0dacf1065a201c36d899f1b5a9798841ef4c Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Thu, 28 Nov 2024 07:41:00 -0500 Subject: [PATCH 1496/1979] chore: mark the unmanaged dependency check required (#1845) b/326247198 --- java-spanner-jdbc/.github/sync-repo-settings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index f35f4721f0c2..7f0d9f2f041d 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -39,7 +39,7 @@ branchProtectionRules: - 'Kokoro - Test: Java GraalVM Native Image' - 'Kokoro - Test: Java 17 GraalVM Native Image' - javadoc - + - unmanaged_dependency_check # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `main` - pattern: 1.21.x From a1dfee495c2e289b374b863737eeadd16ff04a54 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Dec 2024 14:02:52 +0100 Subject: [PATCH 1497/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.82.0 (#1847) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 39ce893e1b51..997dfe79df76 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.81.2 + 6.82.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a0160bde1ee7..50e4c1226083 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.81.2 + 6.82.0 import pom From 2d2b23e5e8378851247d568dedc27e9cd51ce285 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Dec 2024 14:05:23 +0100 Subject: [PATCH 1498/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.2 (#1846) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2bbb78057035..6a09a0aaba5d 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.18.1 + 2.18.2 From 509c30dbcc6ce1e52e19e544b2ecf1b29454c91a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Dec 2024 14:05:41 +0100 Subject: [PATCH 1499/1979] deps: update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.4 (#1844) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 764d37a3ab19..469207ca3231 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -53,7 +53,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - 3.0.3 + 3.0.4 org.mybatis.dynamic-sql From 483e76b4cf762decfd5cf69b5c70be1bd2478a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 4 Dec 2024 14:28:36 +0100 Subject: [PATCH 1500/1979] feat: add fallback to PDML mode (#1841) DML statements that are executed in auto-commit mode can use either atomic transactions, or partitioned non-atomic transactions. The former is bound by the mutation limits in Spanner. The latter may update/delete any number of rows. The transaction type that is used to execute DML statements in auto-commit mode is determined by the connection variable `autocommit_dml_mode`. This connection variable now supports a third value. The supported values are: - TRANSACTIONAL (default): Uses atomic read/write transactions. - PARTITIONED_NON_ATOMIC: Use Partitioned DML for DML statements in auto-commit mode. Use this mode to execute DML statements that exceed the transaction mutation limit in Spanner. - TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC: Execute DML statements using atomic read/write transactions. If this fails because the mutation limit on Spanner has been exceeded, the DML statement is retried using a Partitioned DML transaction. --- java-spanner-jdbc/README.md | 9 + ...allbackToPartitionedDMLMockServerTest.java | 259 ++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/FallbackToPartitionedDMLMockServerTest.java diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 70bace0dea2a..40570b2aca7d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -118,6 +118,15 @@ these can also be supplied in a Properties instance that is passed to the - maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. - numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. +- autocommit_dml_mode (string): Determines the transaction type that is used to execute + [DML statements](https://cloud.google.com/spanner/docs/dml-tasks#using-dml) when the connection is + in auto-commit mode. The following values are supported: + - TRANSACTIONAL (default): Uses atomic read/write transactions. + - PARTITIONED_NON_ATOMIC: Use Partitioned DML for DML statements in auto-commit mode. Use this mode + to execute DML statements that exceed the transaction mutation limit in Spanner. + - TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC: Execute DML statements using atomic read/write + transactions. If this fails because the mutation limit on Spanner has been exceeded, the DML statement + is retried using a Partitioned DML transaction. - auto_batch_dml (boolean): Automatically buffer DML statements and execute them as one batch, instead of executing them on Spanner directly. The buffered DML statements are executed on Spanner in one batch when a query is executed, or when the transaction is committed. This option can for diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/FallbackToPartitionedDMLMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/FallbackToPartitionedDMLMockServerTest.java new file mode 100644 index 000000000000..587143a86432 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/FallbackToPartitionedDMLMockServerTest.java @@ -0,0 +1,259 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.MockSpannerServiceImpl; +import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.TransactionMutationLimitExceededException; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.connection.AutocommitDmlMode; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.protobuf.Any; +import com.google.rpc.Help; +import com.google.rpc.Help.Link; +import com.google.spanner.v1.BeginTransactionRequest; +import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import io.grpc.Metadata; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class FallbackToPartitionedDMLMockServerTest extends AbstractMockServerTest { + + static StatusRuntimeException createTransactionMutationLimitExceededException() { + Metadata.Key key = + Metadata.Key.of("grpc-status-details-bin", Metadata.BINARY_BYTE_MARSHALLER); + Help help = + Help.newBuilder() + .addLinks( + Link.newBuilder() + .setDescription("Cloud Spanner limits documentation.") + .setUrl("https://cloud.google.com/spanner/docs/limits") + .build()) + .build(); + com.google.rpc.Status status = + com.google.rpc.Status.newBuilder().addDetails(Any.pack(help)).build(); + + Metadata trailers = new Metadata(); + trailers.put(key, status.toByteArray()); + + return Status.INVALID_ARGUMENT + .withDescription("The transaction contains too many mutations.") + .asRuntimeException(trailers); + } + + @Test + public void testConnectionProperty() throws SQLException { + for (AutocommitDmlMode mode : AutocommitDmlMode.values()) { + Properties properties = new Properties(); + properties.put("autocommit_dml_mode", mode.name()); + try (Connection connection = + DriverManager.getConnection("jdbc:" + getBaseUrl(), properties)) { + assertEquals( + mode, connection.unwrap(CloudSpannerJdbcConnection.class).getAutocommitDmlMode()); + } + } + } + + @Test + public void testTransactionMutationLimitExceeded_isNotRetriedByDefault() throws SQLException { + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException())); + + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(true); + assertEquals( + AutocommitDmlMode.TRANSACTIONAL, + connection.unwrap(CloudSpannerJdbcConnection.class).getAutocommitDmlMode()); + + SQLException exception = + assertThrows( + SQLException.class, + () -> + connection.createStatement().executeUpdate("update test set value=1 where true")); + assertNotNull(exception.getCause()); + assertEquals( + TransactionMutationLimitExceededException.class, exception.getCause().getClass()); + TransactionMutationLimitExceededException transactionMutationLimitExceededException = + (TransactionMutationLimitExceededException) exception.getCause(); + assertEquals(0, transactionMutationLimitExceededException.getSuppressed().length); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testTransactionMutationLimitExceeded_canBeRetriedAsPDML() throws SQLException { + String sql = "update test set value=1 where true"; + com.google.cloud.spanner.Statement statement = com.google.cloud.spanner.Statement.of(sql); + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException())); + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.update(statement, 100000L)); + + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(true); + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setAutocommitDmlMode( + AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC); + + long updateCount = connection.createStatement().executeUpdate(sql); + assertEquals(100000L, updateCount); + } + // Verify that the request is retried as Partitioned DML. + assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + // The transactional request uses inline-begin. + ExecuteSqlRequest transactionalRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite()); + + // Partitioned DML uses an explicit BeginTransaction RPC. + assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + BeginTransactionRequest beginRequest = + mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0); + assertTrue(beginRequest.getOptions().hasPartitionedDml()); + ExecuteSqlRequest partitionedDmlRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1); + assertTrue(partitionedDmlRequest.getTransaction().hasId()); + + // Partitioned DML transactions are not committed. + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testTransactionMutationLimitExceeded_retryAsPDMLFails() throws SQLException { + String sql = "insert into test (id, value) select -id, value from test"; + com.google.cloud.spanner.Statement statement = com.google.cloud.spanner.Statement.of(sql); + // The transactional update statement uses ExecuteSql(..). + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException())); + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.exception( + statement, + Status.INVALID_ARGUMENT + .withDescription("This statement is not supported with Partitioned DML") + .asRuntimeException())); + + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(true); + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setAutocommitDmlMode( + AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC); + + // The connection throws TransactionMutationLimitExceededException if the retry using + // partitioned DML fails. The exception from the failed retry is returned as a suppressed + // exception of the TransactionMutationLimitExceededException. + SQLException exception = + assertThrows(SQLException.class, () -> connection.createStatement().executeUpdate(sql)); + assertNotNull(exception.getCause()); + assertEquals( + TransactionMutationLimitExceededException.class, exception.getCause().getClass()); + TransactionMutationLimitExceededException transactionMutationLimitExceededException = + (TransactionMutationLimitExceededException) exception.getCause(); + assertEquals(1, transactionMutationLimitExceededException.getSuppressed().length); + assertEquals( + SpannerException.class, + transactionMutationLimitExceededException.getSuppressed()[0].getClass()); + SpannerException spannerException = + (SpannerException) transactionMutationLimitExceededException.getSuppressed()[0]; + assertEquals(ErrorCode.INVALID_ARGUMENT, spannerException.getErrorCode()); + assertTrue( + spannerException.getMessage(), + spannerException + .getMessage() + .contains("This statement is not supported with Partitioned DML")); + } + // Verify that the request was retried as Partitioned DML. + assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + // The transactional request uses inline-begin. + ExecuteSqlRequest transactionalRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite()); + + // Partitioned DML uses an explicit BeginTransaction RPC. + assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class)); + BeginTransactionRequest beginRequest = + mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0); + assertTrue(beginRequest.getOptions().hasPartitionedDml()); + ExecuteSqlRequest partitionedDmlRequest = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1); + assertTrue(partitionedDmlRequest.getTransaction().hasId()); + + // Partitioned DML transactions are not committed. + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } + + @Test + public void testSqlStatements() throws SQLException { + for (Dialect dialect : Dialect.values()) { + SpannerPool.closeSpannerPool(); + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.detectDialectResult(dialect)); + String prefix = dialect == Dialect.POSTGRESQL ? "SPANNER." : ""; + + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(true); + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery(String.format("show variable %sautocommit_dml_mode", prefix))) { + assertTrue(resultSet.next()); + assertEquals( + AutocommitDmlMode.TRANSACTIONAL.name(), + resultSet.getString(String.format("%sAUTOCOMMIT_DML_MODE", prefix))); + assertFalse(resultSet.next()); + } + connection + .createStatement() + .execute( + String.format( + "set %sautocommit_dml_mode = 'transactional_with_fallback_to_partitioned_non_atomic'", + prefix)); + try (ResultSet resultSet = + connection + .createStatement() + .executeQuery(String.format("show variable %sautocommit_dml_mode", prefix))) { + assertTrue(resultSet.next()); + assertEquals( + AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC.name(), + resultSet.getString(String.format("%sAUTOCOMMIT_DML_MODE", prefix))); + assertFalse(resultSet.next()); + } + } + } + } +} From f76a16f57a4f4c0c0ddb92c7e89cdf97ac4819de Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:15:26 +0100 Subject: [PATCH 1501/1979] chore(main): release 2.25.0 (#1842) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index dfd86ef0b142..74bfd538cec8 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.25.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.2...v2.25.0) (2024-12-04) + + +### Features + +* Add fallback to PDML mode ([#1841](https://github.com/googleapis/java-spanner-jdbc/issues/1841)) ([1e81863](https://github.com/googleapis/java-spanner-jdbc/commit/1e818634d1f4845ef96c206de26388e6c3c80bf7)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.2 ([#1846](https://github.com/googleapis/java-spanner-jdbc/issues/1846)) ([1a010a1](https://github.com/googleapis/java-spanner-jdbc/commit/1a010a1ecb4e5f3c83c8fca26c64e607095f1351)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.81.2 ([#1837](https://github.com/googleapis/java-spanner-jdbc/issues/1837)) ([52180d9](https://github.com/googleapis/java-spanner-jdbc/commit/52180d9ad8ff9ae1beda42af4c16c0796948e5a0)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.82.0 ([#1847](https://github.com/googleapis/java-spanner-jdbc/issues/1847)) ([b4ea413](https://github.com/googleapis/java-spanner-jdbc/commit/b4ea4130e667f417d249edbeb560720f58a3c1aa)) +* Update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.4 ([#1844](https://github.com/googleapis/java-spanner-jdbc/issues/1844)) ([3cd9cd6](https://github.com/googleapis/java-spanner-jdbc/commit/3cd9cd6d3d2e7be023e1ff80019bf35bfedc07f9)) +* Update dependency org.springframework.boot:spring-boot to v3.4.0 ([#1838](https://github.com/googleapis/java-spanner-jdbc/issues/1838)) ([fb20987](https://github.com/googleapis/java-spanner-jdbc/commit/fb2098723ad193bf7331578113c0ed0f2e734101)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.0 ([#1840](https://github.com/googleapis/java-spanner-jdbc/issues/1840)) ([3f9dbf1](https://github.com/googleapis/java-spanner-jdbc/commit/3f9dbf18415315db204d679c28d6f226b3edd7f1)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.0 ([#1839](https://github.com/googleapis/java-spanner-jdbc/issues/1839)) ([d681cea](https://github.com/googleapis/java-spanner-jdbc/commit/d681cea1d03f1b57d86f362a5bd2f5089ffcde4c)) +* Update dependency org.testcontainers:testcontainers to v1.20.4 ([#1835](https://github.com/googleapis/java-spanner-jdbc/issues/1835)) ([78aa4bf](https://github.com/googleapis/java-spanner-jdbc/commit/78aa4bf90e8a5339f5179fe1b95d6ed6e1b9ebbc)) +* Update dependency org.testcontainers:testcontainers-bom to v1.20.4 ([#1836](https://github.com/googleapis/java-spanner-jdbc/issues/1836)) ([c01ab98](https://github.com/googleapis/java-spanner-jdbc/commit/c01ab9800483db3eec5da0bd35acda5fb00de663)) + ## [2.24.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.1...v2.24.2) (2024-11-20) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 40570b2aca7d..4ad9bf804bd0 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.24.2 + 2.25.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.24.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.24.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 997dfe79df76..3ea029965f83 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.24.3-SNAPSHOT + 2.25.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a352583429b7..d197033bfc58 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.3-SNAPSHOT + 2.25.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f34f4553bd90..04768795aa59 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.24.2:2.24.3-SNAPSHOT +google-cloud-spanner-jdbc:2.25.0:2.25.0 From f569b695f6dd22d321b2d1cbdd88b1a663f00b62 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:00:38 +0000 Subject: [PATCH 1502/1979] chore(main): release 2.25.1-SNAPSHOT (#1848) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ea029965f83..faf177f06410 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.0 + 2.25.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d197033bfc58..2fde582a1a6a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.0 + 2.25.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 04768795aa59..56bc2ad1e965 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.0:2.25.0 +google-cloud-spanner-jdbc:2.25.0:2.25.1-SNAPSHOT From 827cab95d620a8597a6f7d1f9d74175d0811095f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Dec 2024 11:36:50 +0100 Subject: [PATCH 1503/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.25.0 (#1849) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index af50a928d3fa..cd4967bb33a7 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.24.1 + 2.25.0 From 97e1f48356f3d60da0bc07cc12440abb5ac96465 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 11 Dec 2024 11:37:03 +0100 Subject: [PATCH 1504/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.51.0 (#1850) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6a09a0aaba5d..71322f4ee616 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.50.0 + 26.51.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 36fbfb9b0b31..76c216cb44c9 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.50.0 + 26.51.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 50e4c1226083..44300aaa13db 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.50.0 + 26.51.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 469207ca3231..6e4c046ac529 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.50.0 + 26.51.0 import pom From 7ec5cf2d7695ce32f7e8fab9f2af5b48ee739f05 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Dec 2024 10:16:23 +0100 Subject: [PATCH 1505/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.45.0 (#1853) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 44300aaa13db..88c6e47b4121 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.44.1 + 1.45.0 pom import From ca02222968e25c3a0cb42994cfe9fdbe35059947 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Dec 2024 10:58:40 +0100 Subject: [PATCH 1506/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.41.0 (#1857) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 3efa76d73be4..9150bf459c8a 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.40.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.41.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 82ed3a43e49b..76ca3ee6dafa 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.40.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.41.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index a836c97f04bd..644bb62ce7d3 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.40.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.41.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index faf177f06410..daa817efc448 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.40.0 + 3.41.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 71322f4ee616..28ab09861fea 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.40.0 + 3.41.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 76c216cb44c9..9bb63f3b02ab 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.40.0 + 3.41.0 From 30d253ea282723cd4b3d97f22f4d73e167474efc Mon Sep 17 00:00:00 2001 From: Cameron Moberg Date: Fri, 13 Dec 2024 06:24:16 -0800 Subject: [PATCH 1507/1979] Update README to include all supported ConnectionProperties (#1852) Without this, users may believe that the supported set of connection properties is exhaustive in the README. In addition there could be lead-time between new features being added and the JDBC itself. It should be noted that the version linked is `main` branch rather than the one actively used by the JDBC driver. --- java-spanner-jdbc/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 4ad9bf804bd0..8cb792fb7b0d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -135,6 +135,8 @@ these can also be supplied in a Properties instance that is passed to the - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. +For a full list of supported connection properties see https://github.com/googleapis/java-spanner/blob/main/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperties.java. + ### Jar with Dependencies A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest or be built with the command `mvn package` (select the jar that is named `google-cloud-spanner-jdbc--single-jar-with-dependencies.jar`). From bb8af533a5be747c507489eb5f4142d92aab9d73 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Dec 2024 15:24:37 +0100 Subject: [PATCH 1508/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.1 (#1859) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 88c6e47b4121..7c147d922766 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.0 + 2024.1.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 6e4c046ac529..e958a85f5e87 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.0 + 2024.1.1 import pom From bcb40d5aeade1df6722101055729905883537843 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Dec 2024 09:07:08 +0100 Subject: [PATCH 1509/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.83.0 (#1863) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index daa817efc448..ec1d8ba49d88 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.82.0 + 6.83.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 7c147d922766..246d743f4e5d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.82.0 + 6.83.0 import pom From 7ee518e67f663d00d88682750d75a3aacecd26c9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 13:10:22 +0000 Subject: [PATCH 1510/1979] chore(main): release 2.25.1 (#1858) :robot: I have created a release *beep* *boop* --- ## [2.25.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.25.0...v2.25.1) (2024-12-14) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.83.0 ([#1863](https://togithub.com/googleapis/java-spanner-jdbc/issues/1863)) ([bcb40d5](https://togithub.com/googleapis/java-spanner-jdbc/commit/bcb40d5aeade1df6722101055729905883537843)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.41.0 ([#1857](https://togithub.com/googleapis/java-spanner-jdbc/issues/1857)) ([ca02222](https://togithub.com/googleapis/java-spanner-jdbc/commit/ca02222968e25c3a0cb42994cfe9fdbe35059947)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.45.0 ([#1853](https://togithub.com/googleapis/java-spanner-jdbc/issues/1853)) ([7ec5cf2](https://togithub.com/googleapis/java-spanner-jdbc/commit/7ec5cf2d7695ce32f7e8fab9f2af5b48ee739f05)) * Update dependency org.springframework.data:spring-data-bom to v2024.1.1 ([#1859](https://togithub.com/googleapis/java-spanner-jdbc/issues/1859)) ([bb8af53](https://togithub.com/googleapis/java-spanner-jdbc/commit/bb8af533a5be747c507489eb5f4142d92aab9d73)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 10 ++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 74bfd538cec8..5355f38e8434 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [2.25.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.0...v2.25.1) (2024-12-14) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.83.0 ([#1863](https://github.com/googleapis/java-spanner-jdbc/issues/1863)) ([0e5680b](https://github.com/googleapis/java-spanner-jdbc/commit/0e5680b5dd7b433c850b389a64e8c8c1343151ed)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.41.0 ([#1857](https://github.com/googleapis/java-spanner-jdbc/issues/1857)) ([162fa47](https://github.com/googleapis/java-spanner-jdbc/commit/162fa476b6b45ec14700efe5fea8f6fad7d1c5ad)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.45.0 ([#1853](https://github.com/googleapis/java-spanner-jdbc/issues/1853)) ([350e755](https://github.com/googleapis/java-spanner-jdbc/commit/350e75519d13c81c820c51f88786ca8a61662858)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.1 ([#1859](https://github.com/googleapis/java-spanner-jdbc/issues/1859)) ([150827c](https://github.com/googleapis/java-spanner-jdbc/commit/150827c54042f9d754f1d130287f56ebfadeb7c8)) + ## [2.25.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.24.2...v2.25.0) (2024-12-04) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8cb792fb7b0d..ce0412a50f55 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.25.0 + 2.25.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ec1d8ba49d88..d694d1450d96 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.1-SNAPSHOT + 2.25.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2fde582a1a6a..6abca8960527 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.1-SNAPSHOT + 2.25.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 56bc2ad1e965..be62b81b3171 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.0:2.25.1-SNAPSHOT +google-cloud-spanner-jdbc:2.25.1:2.25.1 From 25976608996b6d9014df0094b60d9028037290cd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 18:28:06 +0100 Subject: [PATCH 1511/1979] chore(main): release 2.25.2-SNAPSHOT (#1866) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d694d1450d96..ef5923f496fb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.1 + 2.25.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6abca8960527..38b687e97774 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.1 + 2.25.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index be62b81b3171..bd7d5639f2b8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.1:2.25.1 +google-cloud-spanner-jdbc:2.25.1:2.25.2-SNAPSHOT From 8399b86308feabf6a522d330e4ffd5a165db1831 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 14 Dec 2024 18:51:12 +0100 Subject: [PATCH 1512/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.25.1 (#1867) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cd4967bb33a7..6761e1c05e9f 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.0 + 2.25.1 From 56b2df9208c1fc64cdbb019adcf907821f8a4c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 16 Dec 2024 11:33:26 +0100 Subject: [PATCH 1513/1979] docs: fix troubleshooting link (#1861) Fixes #1770 --- java-spanner-jdbc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ce0412a50f55..d2202aa027d9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -259,7 +259,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [developer-console]: https://console.developers.google.com/ [create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects [cloud-sdk]: https://cloud.google.com/sdk/ -[troubleshooting]: https://github.com/googleapis/google-cloud-common/blob/main/troubleshooting/readme.md#troubleshooting +[troubleshooting]: https://github.com/googleapis/google-cloud-java/blob/main/TROUBLESHOOTING.md [contributing]: https://github.com/googleapis/java-spanner-jdbc/blob/main/CONTRIBUTING.md [code-of-conduct]: https://github.com/googleapis/java-spanner-jdbc/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct [license]: https://github.com/googleapis/java-spanner-jdbc/blob/main/LICENSE From f0df3324b43d50a7a5c1d72732560d09ebad12f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 16 Dec 2024 11:34:16 +0100 Subject: [PATCH 1514/1979] docs: auto-generate connection properties documentation (#1860) * docs: auto-generate connection properties documentation * docs: add link to README * chore: only run during test phase --- java-spanner-jdbc/README.md | 6 +- .../documentation/connection_properties.md | 56 +++++++++++++++ java-spanner-jdbc/pom.xml | 19 +++++ .../ConnectionPropertiesHelper.java | 72 +++++++++++++++++++ .../google/cloud/spanner/jdbc/JdbcDriver.java | 24 ++----- .../ConnectionPropertiesFileGenerator.java | 71 ++++++++++++++++++ .../cloud/spanner/jdbc/JdbcDriverTest.java | 9 +-- 7 files changed, 234 insertions(+), 23 deletions(-) create mode 100644 java-spanner-jdbc/documentation/connection_properties.md create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index d2202aa027d9..8dbd96329481 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -105,6 +105,9 @@ The Cloud Spanner JDBC driver supports the following connection URL properties. these can also be supplied in a Properties instance that is passed to the `DriverManager#getConnection(String url, Properties properties)` method. +See [Supported Connection Properties](documentation/connection_properties.md) for a full list of all +supported connection properties. + #### Commonly Used Properties - credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json` - autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. @@ -135,7 +138,8 @@ these can also be supplied in a Properties instance that is passed to the - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. -For a full list of supported connection properties see https://github.com/googleapis/java-spanner/blob/main/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperties.java. +For a full list of supported connection properties, see +[Supported Connection Properties](documentation/connection_properties.md). ### Jar with Dependencies A single jar with all dependencies can be downloaded from https://repo1.maven.org/maven2/com/google/cloud/google-cloud-spanner-jdbc/latest diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md new file mode 100644 index 000000000000..8e157ffd8706 --- /dev/null +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -0,0 +1,56 @@ +# Supported Connection Properties + +This file contains all supported connection properties for the Spanner JDBC driver. These properties can be specified both in the connection URL and in the Properties map that is used to create a connection. + +The 'Context' value indicates whether the property can only be set when a connection is created (STARTUP), or whether the value can also be changed after a connection has been created. + +| Name | Description | Default | Enum values | Context | +|------|-------------|---------|-------------|---------| +| auto_batch_dml | Automatically buffer DML statements that are executed on this connection and execute them as one batch when a non-DML statement is executed, or when the current transaction is committed. The update count that is returned for DML statements that are buffered is by default 1. This default can be changed by setting the connection variable auto_batch_dml_update_count to value other than 1. This setting is only in read/write transactions. DML statements in auto-commit mode are executed directly. | false | | USER | +| auto_batch_dml_update_count | DML statements that are executed when auto_batch_dml is set to true, are not directly sent to Spanner, but are buffered in the client until the batch is flushed. This property determines the update count that is returned for these DML statements. The default is 1, as that is the update count that is expected by most ORMs (e.g. Hibernate). | 1 | | USER | +| auto_batch_dml_update_count_verification | The update count that is returned for DML statements that are buffered during an automatic DML batch is by default 1. This value can be changed by setting the connection variable auto_batch_dml_update_count. The update counts that are returned by Spanner when the DML statements are actually executed are verified against the update counts that were returned when they were buffered. If these do not match, a com.google.cloud.spanner.DmlBatchUpdateCountVerificationFailedException will be thrown. You can disable this verification by setting auto_batch_dml_update_count_verification to false. | true | | USER | +| autocommit | Should the connection start in autocommit (true/false) | true | | USER | +| autocommit_dml_mode | Should the connection automatically retry Aborted errors (true/false) | TRANSACTIONAL | | USER | +| autoconfigemulator | Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect. | false | | STARTUP | +| autopartitionmode | Execute all queries on this connection as partitioned queries. Executing a query that cannot be partitioned will fail. Executing a query in a read/write transaction will also fail. | false | | USER | +| channelprovider | The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider. | | | STARTUP | +| connection_state_type | The type of connection state to use for this connection. Can only be set at start up. If no value is set, then the database dialect default will be used, which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL. | | | STARTUP | +| credentials | The location of the credentials file to use for this connection. If neither this property or encoded credentials are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | +| credentialsprovider | The class name of the com.google.api.gax.core.CredentialsProvider implementation that should be used to obtain credentials for connections. | | | STARTUP | +| databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | +| databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | | USER | +| ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | | USER | +| delaytransactionstartuntilfirstwrite | Enabling this option will delay the actual start of a read/write transaction until the first write operation is seen in that transaction. All reads that happen before the first write in a transaction will instead be executed as if the connection was in auto-commit mode. Enabling this option will make read/write transactions lose their SERIALIZABLE isolation level. Read operations that are executed after the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking and improve performance for applications that can handle the lower transaction isolation semantics. | false | | USER | +| dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | | STARTUP | +| directed_read | The directed read options to apply to read-only transactions. | | | USER | +| enableapitracing | Add OpenTelemetry traces for each individual RPC call. Enable this to get a detailed view of each RPC that is being executed by your application, or if you want to debug potential latency problems caused by RPCs that are being retried. | | | STARTUP | +| enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | | STARTUP | +| enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | | STARTUP | +| encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | +| endpoint | The endpoint that the JDBC driver should connect to. The default is the default Spanner production endpoint when autoConfigEmulator=false, and the default Spanner emulator endpoint (localhost:9010) when autoConfigEmulator=true. This property takes precedence over any host name at the start of the connection URL. | | | STARTUP | +| keeptransactionalive | Enabling this option will trigger the connection to keep read/write transactions alive by executing a SELECT 1 query once every 10 seconds if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time. | false | | USER | +| lenient | Silently ignore unknown properties in the connection string/properties (true/false) | false | | STARTUP | +| maxcommitdelay | The max delay that Spanner may apply to commit requests to improve throughput. | | | USER | +| maxpartitionedparallelism | The max partitions hint value to use for partitioned queries. Use 0 if you do not want to specify a hint. | 1 | | USER | +| maxpartitions | The max partitions hint value to use for partitioned queries. Use 0 if you do not want to specify a hint. | 0 | | USER | +| maxsessions | The maximum number of sessions in the backing session pool. The default is 400. | | | STARTUP | +| minsessions | The minimum number of sessions in the backing session pool. The default is 100. | | | STARTUP | +| numchannels | The number of gRPC channels to use to communicate with Cloud Spanner. The default is 4. | | | STARTUP | +| oauthtoken | A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. | | | STARTUP | +| optimizerstatisticspackage | Sets the query optimizer statistics package to use for this connection. | | | USER | +| optimizerversion | Sets the default query optimizer version to use for this connection. | | | USER | +| read_only_staleness | The read-only staleness to use for read-only transactions and single-use queries. | strong | | USER | +| readonly | Should the connection start in read-only mode (true/false) | false | | USER | +| retryabortsinternally | Should the connection automatically retry Aborted errors (true/false) | true | | USER | +| returncommitstats | Request that Spanner returns commit statistics for read/write transactions (true/false) | false | | USER | +| routetoleader | Should read/write transactions and partitioned DML be routed to leader region (true/false) | true | | STARTUP | +| rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | | USER | +| savepoint_support | Determines the behavior of the connection when savepoints are used. | FAIL_AFTER_ROLLBACK | | USER | +| tracing_prefix | The prefix that will be prepended to all OpenTelemetry traces that are generated by a Connection. | CloudSpanner | | STARTUP | +| trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | | STARTUP | +| tracksessionleaks | Capture the call stack of the thread that checked out a session of the session pool. This will pre-create a LeakedSessionException already when a session is checked out. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedSessionException will only be created when an actual session leak is detected. The stack trace of the exception will in that case not contain the call stack of when the session was checked out. | true | | STARTUP | +| useautosavepointsforemulator | Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. This is no longer needed when using Emulator version 1.5.23 or higher. | false | | STARTUP | +| useplaintext | Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator. | false | | STARTUP | +| useragent | The custom user-agent property name to use when communicating with Cloud Spanner. This property is intended for internal library usage, and should not be set by applications. | | | STARTUP | +| usevirtualgrpctransportthreads | Use a virtual thread instead of a platform thread for the gRPC executor (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | | STARTUP | +| usevirtualthreads | Use a virtual thread instead of a platform thread for each connection (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | | STARTUP | diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ef5923f496fb..adb86a0a18ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -334,6 +334,25 @@ org.codehaus.mojo flatten-maven-plugin
    + + + org.codehaus.mojo + exec-maven-plugin + + + generate_connection_properties_documentation + test + + java + + + com.google.cloud.spanner.connection.ConnectionPropertiesFileGenerator + test + false + + + + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java new file mode 100644 index 000000000000..7e64b8f11650 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.connection; + +import com.google.api.core.InternalApi; +import com.google.common.collect.ImmutableList; +import java.sql.DriverPropertyInfo; +import java.util.Arrays; +import java.util.Comparator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// TODO: Remove this class when the Connection API has made the list of properties public. +@InternalApi +public class ConnectionPropertiesHelper { + public static ImmutableList> VALID_CONNECTION_PROPERTIES = + ImmutableList.copyOf( + ConnectionProperties.CONNECTION_PROPERTIES.values().stream() + .sorted(Comparator.comparing(ConnectionProperty::getName)) + .collect(Collectors.toList())); + + public static DriverPropertyInfo toDriverPropertyInfo( + String connectionUri, ConnectionProperty connectionProperty) { + DriverPropertyInfo result = + new DriverPropertyInfo( + connectionProperty.getName(), + parseUriProperty( + connectionUri, + connectionProperty.getName(), + connectionProperty.getDefaultValue() == null + ? null + : connectionProperty.getDefaultValue().toString())); + result.description = connectionProperty.getDescription(); + result.choices = + connectionProperty.getValidValues() == null + ? null + : Arrays.stream(connectionProperty.getValidValues()) + .map(Object::toString) + .toArray(String[]::new); + return result; + } + + public static String getConnectionPropertyName(ConnectionProperty connectionProperty) { + return connectionProperty.getName(); + } + + private static String parseUriProperty(String uri, String property, String defaultValue) { + Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); + Matcher matcher = pattern.matcher(uri); + if (matcher.find() && matcher.groupCount() == 1) { + return matcher.group(1); + } + return defaultValue; + } + + private ConnectionPropertiesHelper() {} +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index d87aab02ebdb..1c499abff2d8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -22,7 +22,8 @@ import com.google.cloud.spanner.SessionPoolOptionsHelper; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.ConnectionOptions; -import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; +import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; +import com.google.cloud.spanner.connection.ConnectionProperty; import com.google.rpc.Code; import io.opentelemetry.api.OpenTelemetry; import java.sql.Connection; @@ -265,29 +266,16 @@ public boolean acceptsURL(String url) { @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { String connectionUri = appendPropertiesToUrl(url.substring(5), info); - DriverPropertyInfo[] res = new DriverPropertyInfo[ConnectionOptions.VALID_PROPERTIES.size()]; + DriverPropertyInfo[] res = + new DriverPropertyInfo[ConnectionPropertiesHelper.VALID_CONNECTION_PROPERTIES.size()]; int i = 0; - for (ConnectionProperty prop : ConnectionOptions.VALID_PROPERTIES) { - res[i] = - new DriverPropertyInfo( - prop.getName(), - parseUriProperty(connectionUri, prop.getName(), prop.getDefaultValue())); - res[i].description = prop.getDescription(); - res[i].choices = prop.getValidValues(); + for (ConnectionProperty prop : ConnectionPropertiesHelper.VALID_CONNECTION_PROPERTIES) { + res[i] = ConnectionPropertiesHelper.toDriverPropertyInfo(connectionUri, prop); i++; } return res; } - private String parseUriProperty(String uri, String property, String defaultValue) { - Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); - Matcher matcher = pattern.matcher(uri); - if (matcher.find() && matcher.groupCount() == 1) { - return matcher.group(1); - } - return defaultValue; - } - @Override public int getMajorVersion() { return MAJOR_VERSION; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java new file mode 100644 index 000000000000..fe8dd9c968df --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java @@ -0,0 +1,71 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.connection; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.stream.Collectors; + +/** Generator for the documentation/connection_properties.md file. */ +public class ConnectionPropertiesFileGenerator { + + public static void main(String[] args) throws IOException { + StringBuilder builder = + new StringBuilder("# Supported Connection Properties\n\n") + .append( + "This file contains all supported connection properties for the Spanner JDBC driver. " + + "These properties can be specified both in the connection URL and in the Properties map " + + "that is used to create a connection.\n\n" + + "The 'Context' value indicates whether the property can only be set when a connection is " + + "created (STARTUP), or whether the value can also be changed after a connection has been " + + "created.\n\n"); + builder.append("| Name | Description | Default | Enum values | Context |\n"); + builder.append("|------|-------------|---------|-------------|---------|\n"); + for (ConnectionProperty connectionProperty : + ConnectionPropertiesHelper.VALID_CONNECTION_PROPERTIES) { + builder + .append("| ") + .append(connectionProperty.getName()) + .append(" | ") + .append(connectionProperty.getDescription()) + .append(" | ") + .append( + connectionProperty.getDefaultValue() == null + ? "" + : connectionProperty.getDefaultValue().toString()) + .append(" | ") + .append(getValidValues(connectionProperty)) + .append(" | ") + .append(connectionProperty.getContext()) + .append(" |\n"); + } + try (BufferedWriter writer = + new BufferedWriter(new FileWriter("documentation/connection_properties.md"))) { + writer.write(builder.toString()); + } + } + + static String getValidValues(ConnectionProperty connectionProperty) { + return connectionProperty.getValidValues() == null + ? "" + : Arrays.stream(connectionProperty.getValidValues()) + .map(Object::toString) + .collect(Collectors.joining(", ")); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 13efeb8170f4..020848e1eae7 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -24,8 +24,7 @@ import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.MockSpannerServiceImpl; -import com.google.cloud.spanner.connection.ConnectionOptions; -import com.google.cloud.spanner.connection.ConnectionOptions.ConnectionProperty; +import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.SpannerPool; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; @@ -174,10 +173,12 @@ public void testGetPropertyInfo() throws SQLException { JdbcDriver.getRegisteredDriver() .getPropertyInfo( "jdbc:cloudspanner:/projects/p/instances/i/databases/d", new Properties()); - assertThat(props).hasLength(ConnectionOptions.VALID_PROPERTIES.size()); + assertThat(props).hasLength(ConnectionPropertiesHelper.VALID_CONNECTION_PROPERTIES.size()); Collection validConnectionPropertyNames = - Collections2.transform(ConnectionOptions.VALID_PROPERTIES, ConnectionProperty::getName); + Collections2.transform( + ConnectionPropertiesHelper.VALID_CONNECTION_PROPERTIES, + ConnectionPropertiesHelper::getConnectionPropertyName); Collection driverPropertyNames = Collections2.transform(ImmutableList.copyOf(props), input -> input.name); assertThat(driverPropertyNames).containsExactlyElementsIn(validConnectionPropertyNames); From fe7b96d03dc24ba369af8b9374c3262ecdd99e8d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 14:39:31 +0100 Subject: [PATCH 1515/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.55.0 (#1870) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index adb86a0a18ab..f4295e9e716d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -210,7 +210,7 @@ com.google.cloud google-cloud-trace - 2.54.0 + 2.55.0 test From 80532c3c445cabc2e317458a38c4e3112dc4fe3e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 14:39:51 +0100 Subject: [PATCH 1516/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.55.0 (#1869) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f4295e9e716d..ae5765874cd5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.54.0 + 2.55.0 test From e73db8aea36a3a330ed5b42f0df2dfa9684b955d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 19 Dec 2024 14:40:06 +0100 Subject: [PATCH 1517/1979] chore: store query timeout as a java.time.Duration (#1865) Store the query timeout internally as a java.time.Duration, so we can use a smaller unit for testing. This again allows us to enable the timeout tests by default. --- java-spanner-jdbc/pom.xml | 1 - .../spanner/jdbc/AbstractJdbcStatement.java | 35 +++++++++++++++---- .../jdbc/JdbcStatementTimeoutTest.java | 20 ++++++----- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ae5765874cd5..d535c3d1f75e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -241,7 +241,6 @@ com.google.cloud.spanner.jdbc.it.** - com.google.cloud.spanner.jdbc.JdbcStatementTimeoutTest sponge_log diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index f3a1539b88bb..3152445b0dee 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -24,6 +24,7 @@ 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.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; import com.google.rpc.Code; import java.sql.ResultSet; @@ -35,6 +36,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; +import javax.annotation.Nonnull; /** Base class for Cloud Spanner JDBC {@link Statement}s */ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Statement { @@ -45,7 +47,7 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Stat private boolean closeOnCompletion; private boolean poolable; private final JdbcConnection connection; - private int queryTimeout; + private Duration queryTimeout = Duration.ZERO; AbstractJdbcStatement(JdbcConnection connection) throws SQLException { this.connection = connection; @@ -148,13 +150,22 @@ protected T runWithStatementTimeout(JdbcFunction function) */ StatementTimeout setTemporaryStatementTimeout() throws SQLException { StatementTimeout originalTimeout = null; - if (getQueryTimeout() > 0) { + if (!getQueryTimeoutDuration().isZero()) { if (connection.getSpannerConnection().hasStatementTimeout()) { TimeUnit unit = getAppropriateTimeUnit(); originalTimeout = StatementTimeout.of(connection.getSpannerConnection().getStatementTimeout(unit), unit); } - connection.getSpannerConnection().setStatementTimeout(getQueryTimeout(), TimeUnit.SECONDS); + Duration queryTimeout = getQueryTimeoutDuration(); + if (queryTimeout.getNano() > 0) { + connection + .getSpannerConnection() + .setStatementTimeout(queryTimeout.toMillis(), TimeUnit.MILLISECONDS); + } else { + connection + .getSpannerConnection() + .setStatementTimeout(queryTimeout.getSeconds(), TimeUnit.SECONDS); + } } return originalTimeout; } @@ -164,7 +175,7 @@ StatementTimeout setTemporaryStatementTimeout() throws SQLException { * has been executed. */ void resetStatementTimeout(StatementTimeout originalTimeout) throws SQLException { - if (getQueryTimeout() > 0) { + if (!getQueryTimeoutDuration().isZero()) { if (originalTimeout == null) { connection.getSpannerConnection().clearStatementTimeout(); } else { @@ -317,14 +328,26 @@ private StatementResult rerunShowStatementTimeout(com.google.cloud.spanner.State @Override public int getQueryTimeout() throws SQLException { + return (int) getQueryTimeoutDuration().getSeconds(); + } + + @VisibleForTesting + @Nonnull + Duration getQueryTimeoutDuration() throws SQLException { checkClosed(); - return queryTimeout; + return this.queryTimeout; } @Override public void setQueryTimeout(int seconds) throws SQLException { + setQueryTimeout(Duration.ofSeconds(seconds)); + } + + @VisibleForTesting + void setQueryTimeout(@Nonnull Duration duration) throws SQLException { + JdbcPreconditions.checkArgument(!duration.isNegative(), "Timeout must be >= 0"); checkClosed(); - this.queryTimeout = seconds; + this.queryTimeout = duration; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java index a9d1840068f0..eb876c237088 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java @@ -27,17 +27,21 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.time.Duration; +import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Tests setting a statement timeout. This test is by default not included in unit test runs, as the - * minimum timeout value in JDBC is 1 second, which again makes this test relatively slow. - */ +/** Tests setting a statement timeout. */ @RunWith(JUnit4.class) public class JdbcStatementTimeoutTest extends AbstractMockServerTest { + @After + public void resetExecutionTimes() { + mockSpanner.removeAllExecutionTimes(); + } + @Test public void testExecuteTimeout() throws SQLException { try (java.sql.Connection connection = createJdbcConnection()) { @@ -50,7 +54,7 @@ public void testExecuteTimeout() throws SQLException { // Simulate that executeSql takes 2 seconds and set a statement timeout of 1 second. mockSpanner.setExecuteSqlExecutionTime( SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); - statement.setQueryTimeout(1); + ((JdbcStatement) statement).setQueryTimeout(Duration.ofMillis(5L)); assertThrows( JdbcSqlTimeoutException.class, () -> statement.execute(INSERT_STATEMENT.getSql())); } @@ -74,7 +78,7 @@ public void testExecuteQueryTimeout() throws SQLException { // second. mockSpanner.setExecuteStreamingSqlExecutionTime( SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); - statement.setQueryTimeout(1); + ((JdbcStatement) statement).setQueryTimeout(Duration.ofMillis(5L)); assertThrows( JdbcSqlTimeoutException.class, () -> statement.executeQuery(SELECT_RANDOM_STATEMENT.getSql())); @@ -92,7 +96,7 @@ public void testExecuteUpdateTimeout() throws SQLException { // Simulate that executeSql takes 2 seconds and set a statement timeout of 1 second. mockSpanner.setExecuteSqlExecutionTime( SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); - statement.setQueryTimeout(1); + ((JdbcStatement) statement).setQueryTimeout(Duration.ofMillis(5L)); assertThrows( JdbcSqlTimeoutException.class, () -> statement.executeUpdate(INSERT_STATEMENT.getSql())); @@ -112,7 +116,7 @@ public void testExecuteBatchTimeout() throws SQLException { // Simulate that executeBatchDml takes 2 seconds and set a statement timeout of 1 second. mockSpanner.setExecuteBatchDmlExecutionTime( SimulatedExecutionTime.ofMinimumAndRandomTime(2000, 0)); - statement.setQueryTimeout(1); + ((JdbcStatement) statement).setQueryTimeout(Duration.ofMillis(5L)); statement.addBatch(INSERT_STATEMENT.getSql()); assertThrows(JdbcSqlTimeoutException.class, statement::executeBatch); } From 334bf46a09921c2a22c381acfe02b5f73f9ad356 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 14:49:26 +0100 Subject: [PATCH 1518/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.52.0 (#1872) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 28ab09861fea..b9f6a13a22e3 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.51.0 + 26.52.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 9bb63f3b02ab..11b8346b99ca 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.51.0 + 26.52.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 246d743f4e5d..e8fc57ed0f56 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.51.0 + 26.52.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index e958a85f5e87..6e294a1c7f73 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.51.0 + 26.52.0 import pom From c8634d0ec1155b105c728441a54aa3f0a121a333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 19 Dec 2024 15:18:12 +0100 Subject: [PATCH 1519/1979] perf: use direct executor (#1864) Use a direct executor by default for JDBC connections, as these do not use the async API, and cancelling statements can be handled by directly in the JDBC driver. This reduces the overall number of threads that is created by the JDBC driver. --- .../connection/ConnectionOptionsHelper.java | 41 ++++++++++++++ .../spanner/jdbc/AbstractJdbcConnection.java | 7 +++ .../spanner/jdbc/AbstractJdbcStatement.java | 28 +++++++++- .../google/cloud/spanner/jdbc/JdbcDriver.java | 4 ++ .../jdbc/JdbcStatementTimeoutTest.java | 56 ++++++++++++++++++- 5 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionOptionsHelper.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionOptionsHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionOptionsHelper.java new file mode 100644 index 000000000000..75aef4947a60 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionOptionsHelper.java @@ -0,0 +1,41 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.connection; + +import com.google.api.core.InternalApi; +import com.google.cloud.spanner.connection.StatementExecutor.StatementExecutorType; + +@InternalApi +public class ConnectionOptionsHelper { + + @InternalApi + public static ConnectionOptions.Builder useDirectExecutorIfNotUseVirtualThreads( + String uri, ConnectionOptions.Builder builder) { + ConnectionState connectionState = new ConnectionState(ConnectionProperties.parseValues(uri)); + if (!connectionState.getValue(ConnectionProperties.USE_VIRTUAL_THREADS).getValue()) { + return builder.setStatementExecutorType(StatementExecutorType.DIRECT_EXECUTOR); + } + return builder; + } + + @InternalApi + public static boolean usesDirectExecutor(ConnectionOptions options) { + return options.getStatementExecutorType() == StatementExecutorType.DIRECT_EXECUTOR; + } + + private ConnectionOptionsHelper() {} +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index d790cf855c16..122d48967d5d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -21,6 +21,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.AbstractStatementParser; import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.ConnectionOptionsHelper; import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; import java.sql.CallableStatement; @@ -53,6 +54,7 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper private final ConnectionOptions options; private final com.google.cloud.spanner.connection.Connection spanner; private final Properties clientInfo; + private final boolean usesDirectExecutor; private AbstractStatementParser parser; private SQLWarning firstWarning = null; @@ -63,6 +65,7 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper this.options = options; this.spanner = options.getConnection(); this.clientInfo = new Properties(JdbcDatabaseMetaData.getDefaultClientInfoProperties()); + this.usesDirectExecutor = ConnectionOptionsHelper.usesDirectExecutor(options); } /** Return the corresponding {@link com.google.cloud.spanner.connection.Connection} */ @@ -83,6 +86,10 @@ Spanner getSpanner() { return this.spanner.getSpanner(); } + boolean usesDirectExecutor() { + return this.usesDirectExecutor; + } + @Override public Dialect getDialect() { return spanner.getDialect(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 3152445b0dee..5c15f3362404 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -34,6 +34,8 @@ import java.time.Duration; import java.util.Arrays; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.function.Supplier; import javax.annotation.Nonnull; @@ -43,6 +45,8 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Stat private static final String CURSORS_NOT_SUPPORTED = "Cursors are not supported"; private static final String ONLY_FETCH_FORWARD_SUPPORTED = "Only fetch_forward is supported"; final AbstractStatementParser parser; + private final Lock executingLock; + private volatile Thread executingThread; private boolean closed; private boolean closeOnCompletion; private boolean poolable; @@ -52,6 +56,11 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Stat AbstractJdbcStatement(JdbcConnection connection) throws SQLException { this.connection = connection; this.parser = connection.getParser(); + if (connection.usesDirectExecutor()) { + this.executingLock = new ReentrantLock(); + } else { + this.executingLock = null; + } } @Override @@ -239,6 +248,10 @@ private T doWithStatementTimeout( Supplier runnable, Function shouldResetTimeout) throws SQLException { StatementTimeout originalTimeout = setTemporaryStatementTimeout(); T result = null; + if (this.executingLock != null) { + this.executingLock.lock(); + this.executingThread = Thread.currentThread(); + } try { Stopwatch stopwatch = Stopwatch.createStarted(); result = runnable.get(); @@ -248,6 +261,10 @@ private T doWithStatementTimeout( } catch (SpannerException spannerException) { throw JdbcSqlExceptionFactory.of(spannerException); } finally { + if (this.executingLock != null) { + this.executingThread = null; + this.executingLock.unlock(); + } if (shouldResetTimeout.apply(result)) { resetStatementTimeout(originalTimeout); } @@ -353,7 +370,16 @@ void setQueryTimeout(@Nonnull Duration duration) throws SQLException { @Override public void cancel() throws SQLException { checkClosed(); - connection.getSpannerConnection().cancel(); + if (this.executingThread != null) { + // This is a best-effort operation. It could be that the executing thread is set to null + // between the if-check and the actual execution. Just ignore if that happens. + try { + this.executingThread.interrupt(); + } catch (NullPointerException ignore) { + } + } else { + connection.getSpannerConnection().cancel(); + } } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 1c499abff2d8..6bb70283f0cc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -22,6 +22,7 @@ import com.google.cloud.spanner.SessionPoolOptionsHelper; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.connection.ConnectionOptionsHelper; import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.ConnectionProperty; import com.google.rpc.Code; @@ -245,6 +246,9 @@ private ConnectionOptions buildConnectionOptions(String connectionUrl, Propertie // Enable multiplexed sessions by default for the JDBC driver. builder.setSessionPoolOptions( SessionPoolOptionsHelper.useMultiplexedSessions(SessionPoolOptions.newBuilder()).build()); + // Enable direct executor for JDBC, as we don't use the async API. + builder = + ConnectionOptionsHelper.useDirectExecutorIfNotUseVirtualThreads(connectionUrl, builder); return builder.build(); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java index eb876c237088..2c8c43ca1194 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java @@ -19,24 +19,45 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlTimeoutException; +import com.google.rpc.Code; +import com.google.spanner.v1.ExecuteSqlRequest; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.Duration; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.junit.After; 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; /** Tests setting a statement timeout. */ -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class JdbcStatementTimeoutTest extends AbstractMockServerTest { + @Parameter public boolean useVirtualThreads; + + @Parameters(name = "useVirtualThreads = {0}") + public static Object[] data() { + return new Boolean[] {false, true}; + } + + @Override + protected String getBaseUrl() { + return super.getBaseUrl() + ";useVirtualThreads=" + this.useVirtualThreads; + } + @After public void resetExecutionTimes() { mockSpanner.removeAllExecutionTimes(); @@ -122,4 +143,35 @@ public void testExecuteBatchTimeout() throws SQLException { } } } + + @Test + public void testCancel() throws Exception { + ExecutorService service = Executors.newSingleThreadExecutor(); + String sql = INSERT_STATEMENT.getSql(); + + try (java.sql.Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + mockSpanner.freeze(); + Future future = + service.submit( + () -> { + // Wait until the request has landed on the server and then cancel the statement. + mockSpanner.waitForRequestsToContain( + message -> + message instanceof ExecuteSqlRequest + && ((ExecuteSqlRequest) message).getSql().equals(sql), + 5000L); + System.out.println("Cancelling statement"); + statement.cancel(); + return null; + }); + JdbcSqlExceptionImpl exception = + assertThrows(JdbcSqlExceptionImpl.class, () -> statement.execute(sql)); + assertEquals(Code.CANCELLED, exception.getCode()); + assertNull(future.get()); + } finally { + mockSpanner.unfreeze(); + service.shutdown(); + } + } } From aa3085ecf3eb30bcd0c3eba93261694b0493204f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:54:35 +0100 Subject: [PATCH 1520/1979] chore(main): release 2.25.2 (#1868) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 19 +++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 5355f38e8434..4e0afceddf53 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [2.25.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.1...v2.25.2) (2024-12-19) + + +### Performance Improvements + +* Use direct executor ([#1864](https://github.com/googleapis/java-spanner-jdbc/issues/1864)) ([6d6d500](https://github.com/googleapis/java-spanner-jdbc/commit/6d6d50006eec29bba47ebe08339ef0c440530710)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.55.0 ([#1869](https://github.com/googleapis/java-spanner-jdbc/issues/1869)) ([dee17e2](https://github.com/googleapis/java-spanner-jdbc/commit/dee17e2130819e722106100032975bbcbbef360a)) +* Update dependency com.google.cloud:google-cloud-trace to v2.55.0 ([#1870](https://github.com/googleapis/java-spanner-jdbc/issues/1870)) ([0e78510](https://github.com/googleapis/java-spanner-jdbc/commit/0e78510229378319dd67c3bc240a10b6330886e2)) + + +### Documentation + +* Auto-generate connection properties documentation ([#1860](https://github.com/googleapis/java-spanner-jdbc/issues/1860)) ([c22e654](https://github.com/googleapis/java-spanner-jdbc/commit/c22e654c23511ec108a454928da3d426e78dda0d)) +* Fix troubleshooting link ([#1861](https://github.com/googleapis/java-spanner-jdbc/issues/1861)) ([6c08ffa](https://github.com/googleapis/java-spanner-jdbc/commit/6c08ffa536b7b0f0c6c65e54391f119399ce8bbf)), closes [#1770](https://github.com/googleapis/java-spanner-jdbc/issues/1770) + ## [2.25.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.0...v2.25.1) (2024-12-14) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8dbd96329481..12015e861c8d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.25.1 + 2.25.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d535c3d1f75e..fb07a0d69822 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.2-SNAPSHOT + 2.25.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 38b687e97774..3f0e54f6b2a4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.2-SNAPSHOT + 2.25.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bd7d5639f2b8..fcaf7771d8a6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.1:2.25.2-SNAPSHOT +google-cloud-spanner-jdbc:2.25.2:2.25.2 From 85c9d2ced5f0028bb8f8dd48b44c41ab6e666da6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 16:06:55 +0100 Subject: [PATCH 1521/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.1 (#1873) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index b9f6a13a22e3..15b8b27da358 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.0 + 3.4.1 test From 0e7772a06c15a3a719374a78c9fabcf0bdb44b74 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:28:09 +0100 Subject: [PATCH 1522/1979] chore(main): release 2.25.3-SNAPSHOT (#1875) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fb07a0d69822..c7ba43a19549 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.2 + 2.25.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3f0e54f6b2a4..bcefd78384be 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.2 + 2.25.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fcaf7771d8a6..5a79df343fde 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.2:2.25.2 +google-cloud-spanner-jdbc:2.25.2:2.25.3-SNAPSHOT From ca82c42976e88bcf342372252f320983e656936e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 17:53:42 +0100 Subject: [PATCH 1523/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.1 (#1874) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e8fc57ed0f56..bb593b658688 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.0 + 3.4.1 From db8ae0c231d1da71d0ab20aaaf8dd08de7963e4e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 19 Dec 2024 18:05:07 +0100 Subject: [PATCH 1524/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.1 (#1876) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 6e294a1c7f73..73ff402e260f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.0 + 3.4.1 From 37027de1792d94d2842a95a811cbe86d69c63eea Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Dec 2024 14:35:13 +0100 Subject: [PATCH 1525/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.25.2 (#1878) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 6761e1c05e9f..5b713984cbfe 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.1 + 2.25.2 From 9e1cec2399939bd1dbe498da92818f1496b11a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 6 Jan 2025 09:30:26 +0100 Subject: [PATCH 1526/1979] docs: add sample for using array of struct query param (#1871) --- .../com/example/spanner/jdbc/JdbcSample.java | 64 +++++++++++++++++++ .../example/spanner/jdbc/JdbcSampleTest.java | 5 ++ 2 files changed, 69 insertions(+) diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java index b17c6b4d8f6f..a597d74302b5 100644 --- a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java @@ -22,6 +22,10 @@ import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Struct; +import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.Type.StructField; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; @@ -1519,6 +1523,59 @@ static void partitionedDmlPostgreSQL( } // [END spanner_postgresql_partitioned_dml] + static void arrayOfStructAsQueryParameter( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + try (Statement statement = connection.createStatement()) { + statement.execute( + "create table if not exists my_table " + + "(col1 string(max), col2 int64) primary key (col1)"); + statement.execute( + "insert or update into my_table (col1, col2) " + + "values ('value1', 1), ('value2', 2), ('value3', 3)"); + } + + try (PreparedStatement statement = connection.prepareStatement( + "select * from my_table " + + "where STRUCT(col1, col2) " + + "in unnest (?)")) { + statement.setObject( + 1, + Value.structArray( + com.google.cloud.spanner.Type.struct( + StructField.of("col1", Type.string()), + StructField.of("col2", Type.int64())), + ImmutableList.of( + Struct.newBuilder() + .set("col1").to("value1") + .set("col2").to(1L) + .build(), + Struct.newBuilder() + .set("col1").to("value2") + .set("col2").to(2L) + .build()))); + try (java.sql.ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + for (int col = 1; + col <= resultSet.getMetaData().getColumnCount(); + col++) { + System.out.printf("%s;", resultSet.getString(col)); + } + System.out.println(); + } + } + } + } + } + /** The expected number of command line arguments. */ private static final int NUM_EXPECTED_ARGS = 3; @@ -1697,6 +1754,13 @@ static boolean runGoogleSQLSample( database.getDatabase(), createProperties()); return true; + case "arrayofstructparam": + arrayOfStructAsQueryParameter( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; default: return false; } diff --git a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java index 1b0328de91e9..c1275f457c04 100644 --- a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java +++ b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/JdbcSampleTest.java @@ -18,6 +18,7 @@ import static com.example.spanner.jdbc.JdbcSample.addColumn; import static com.example.spanner.jdbc.JdbcSample.addColumnPostgreSQL; +import static com.example.spanner.jdbc.JdbcSample.arrayOfStructAsQueryParameter; import static com.example.spanner.jdbc.JdbcSample.createConnection; import static com.example.spanner.jdbc.JdbcSample.createConnectionWithEmulator; import static com.example.spanner.jdbc.JdbcSample.createDatabase; @@ -243,6 +244,10 @@ public void testGoogleSQLSamples() throws Exception { result = runSample(() -> partitionedDml(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); assertEquals("Updated at least 3 albums\n", result); + + result = runSample( + () -> arrayOfStructAsQueryParameter(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("value1;1;\nvalue2;2;\n", result); } @Test From 8c4de77a7dbde1574e9ce05582e745813c934053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 6 Jan 2025 09:31:38 +0100 Subject: [PATCH 1527/1979] fix: clear interrupted flag after cancel (#1880) Clear the interrupted flag after cancelling a statement when using a direct executor. Fixes #1879 --- .../spanner/jdbc/AbstractJdbcStatement.java | 17 +++++++++++++++++ .../spanner/jdbc/JdbcStatementTimeoutTest.java | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java index 5c15f3362404..3b98591abbad 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcStatement.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Options; import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; @@ -34,6 +35,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; @@ -47,6 +49,7 @@ abstract class AbstractJdbcStatement extends AbstractJdbcWrapper implements Stat final AbstractStatementParser parser; private final Lock executingLock; private volatile Thread executingThread; + private final AtomicBoolean cancelled = new AtomicBoolean(); private boolean closed; private boolean closeOnCompletion; private boolean poolable; @@ -259,10 +262,18 @@ private T doWithStatementTimeout( connection.recordClientLibLatencyMetric(executionDuration.toMillis()); return result; } catch (SpannerException spannerException) { + if (this.cancelled.get() + && spannerException.getErrorCode() == ErrorCode.CANCELLED + && this.executingLock != null) { + // Clear the interrupted flag of the thread. + //noinspection ResultOfMethodCallIgnored + Thread.interrupted(); + } throw JdbcSqlExceptionFactory.of(spannerException); } finally { if (this.executingLock != null) { this.executingThread = null; + this.cancelled.set(false); this.executingLock.unlock(); } if (shouldResetTimeout.apply(result)) { @@ -374,8 +385,14 @@ public void cancel() throws SQLException { // This is a best-effort operation. It could be that the executing thread is set to null // between the if-check and the actual execution. Just ignore if that happens. try { + this.cancelled.set(true); this.executingThread.interrupt(); } catch (NullPointerException ignore) { + // ignore, this just means that the execution finished before we got to the point where we + // could interrupt the thread. + } catch (SecurityException securityException) { + throw JdbcSqlExceptionFactory.of( + securityException.getMessage(), Code.PERMISSION_DENIED, securityException); } } else { connection.getSpannerConnection().cancel(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java index 2c8c43ca1194..7ce51d362dd2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcStatementTimeoutTest.java @@ -161,7 +161,6 @@ public void testCancel() throws Exception { message instanceof ExecuteSqlRequest && ((ExecuteSqlRequest) message).getSql().equals(sql), 5000L); - System.out.println("Cancelling statement"); statement.cancel(); return null; }); From 7cb98509f47ce31ea16db6f2d454e0deca894c19 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 6 Jan 2025 16:26:25 +0100 Subject: [PATCH 1528/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.84.0 (#1881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-bom](https://redirect.github.com/googleapis/java-spanner) | `6.83.0` -> `6.84.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.84.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.84.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.83.0/6.84.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.83.0/6.84.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.84.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6840-2025-01-06) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.83.0...v6.84.0) ##### Features - Add support for ARRAY\ to CloudCilentExecutor ([#​3544](https://redirect.github.com/googleapis/java-spanner/issues/3544)) ([6cbaf7e](https://redirect.github.com/googleapis/java-spanner/commit/6cbaf7ec6502d04fc0a0c09720e2054bd10bead9)) - Add transaction runner for connections ([#​3559](https://redirect.github.com/googleapis/java-spanner/issues/3559)) ([5a1be3d](https://redirect.github.com/googleapis/java-spanner/commit/5a1be3dedeafa6858502eadc7918820b9cd90f68)) - Exposing InstanceType in Instance configuration (to define PROVISIONED or FREE spanner instance) ([8d295c4](https://redirect.github.com/googleapis/java-spanner/commit/8d295c4a4030b4e97b1d653cc3baf412864f3042)) - Improve tracing by adding attributes ([#​3576](https://redirect.github.com/googleapis/java-spanner/issues/3576)) ([eee333b](https://redirect.github.com/googleapis/java-spanner/commit/eee333b51fa69123e011dfbd2a0896fd31ac10dc)) - **spanner:** Add jdbc support for external hosts ([#​3536](https://redirect.github.com/googleapis/java-spanner/issues/3536)) ([801346a](https://redirect.github.com/googleapis/java-spanner/commit/801346a1b2efe7d0144f7442e1568eb5b02ddcbc)) ##### Bug Fixes - AsyncTransactionManager did not always close the session ([#​3580](https://redirect.github.com/googleapis/java-spanner/issues/3580)) ([d9813a0](https://redirect.github.com/googleapis/java-spanner/commit/d9813a05240b966f444168d3b8c30da9d27a8cc4)) - Retry specific internal errors ([#​3565](https://redirect.github.com/googleapis/java-spanner/issues/3565)) ([b9ce1a6](https://redirect.github.com/googleapis/java-spanner/commit/b9ce1a6fcbd11373a5cc82807af15c1cca0dd48e)) - Update max_in_use_session at 10 mins interval ([#​3570](https://redirect.github.com/googleapis/java-spanner/issues/3570)) ([cc1753d](https://redirect.github.com/googleapis/java-spanner/commit/cc1753da72b3e508f8fea8a6d19e1ed3f34e3602)) ##### Dependencies - Update opentelemetry.version to v1.45.0 ([#​3531](https://redirect.github.com/googleapis/java-spanner/issues/3531)) ([78c82ed](https://redirect.github.com/googleapis/java-spanner/commit/78c82edb4fcc4a5a9a372225ca429038c3b34955))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c7ba43a19549..22f3cbaae76c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.83.0 + 6.84.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index bb593b658688..2ac50a807f6d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.83.0 + 6.84.0 import pom From 8ef7ea5a9bc926c9a41b54bc838af10149fdd4bf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:58:22 +0000 Subject: [PATCH 1529/1979] chore(main): release 2.25.3 (#1877) :robot: I have created a release *beep* *boop* --- ## [2.25.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.25.2...v2.25.3) (2025-01-06) ### Bug Fixes * Clear interrupted flag after cancel ([#1880](https://togithub.com/googleapis/java-spanner-jdbc/issues/1880)) ([8c4de77](https://togithub.com/googleapis/java-spanner-jdbc/commit/8c4de77a7dbde1574e9ce05582e745813c934053)), closes [#1879](https://togithub.com/googleapis/java-spanner-jdbc/issues/1879) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.84.0 ([#1881](https://togithub.com/googleapis/java-spanner-jdbc/issues/1881)) ([7cb9850](https://togithub.com/googleapis/java-spanner-jdbc/commit/7cb98509f47ce31ea16db6f2d454e0deca894c19)) * Update dependency org.springframework.boot:spring-boot to v3.4.1 ([#1873](https://togithub.com/googleapis/java-spanner-jdbc/issues/1873)) ([85c9d2c](https://togithub.com/googleapis/java-spanner-jdbc/commit/85c9d2ced5f0028bb8f8dd48b44c41ab6e666da6)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.1 ([#1874](https://togithub.com/googleapis/java-spanner-jdbc/issues/1874)) ([ca82c42](https://togithub.com/googleapis/java-spanner-jdbc/commit/ca82c42976e88bcf342372252f320983e656936e)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.1 ([#1876](https://togithub.com/googleapis/java-spanner-jdbc/issues/1876)) ([db8ae0c](https://togithub.com/googleapis/java-spanner-jdbc/commit/db8ae0c231d1da71d0ab20aaaf8dd08de7963e4e)) ### Documentation * Add sample for using array of struct query param ([#1871](https://togithub.com/googleapis/java-spanner-jdbc/issues/1871)) ([9e1cec2](https://togithub.com/googleapis/java-spanner-jdbc/commit/9e1cec2399939bd1dbe498da92818f1496b11a04)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4e0afceddf53..64e1e8f81121 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.25.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.2...v2.25.3) (2025-01-06) + + +### Bug Fixes + +* Clear interrupted flag after cancel ([#1880](https://github.com/googleapis/java-spanner-jdbc/issues/1880)) ([e1fd4e1](https://github.com/googleapis/java-spanner-jdbc/commit/e1fd4e131a039b80306991cc93c5c097f2538c90)), closes [#1879](https://github.com/googleapis/java-spanner-jdbc/issues/1879) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.84.0 ([#1881](https://github.com/googleapis/java-spanner-jdbc/issues/1881)) ([42ffaad](https://github.com/googleapis/java-spanner-jdbc/commit/42ffaadf0e671806269ba6c0fba8ce470911b8fe)) +* Update dependency org.springframework.boot:spring-boot to v3.4.1 ([#1873](https://github.com/googleapis/java-spanner-jdbc/issues/1873)) ([c81941c](https://github.com/googleapis/java-spanner-jdbc/commit/c81941ca62face226804619e11b3e9de9b0aa801)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.1 ([#1874](https://github.com/googleapis/java-spanner-jdbc/issues/1874)) ([cc3fc3e](https://github.com/googleapis/java-spanner-jdbc/commit/cc3fc3e8a2f455909eb9687a81d742250decb8c3)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.1 ([#1876](https://github.com/googleapis/java-spanner-jdbc/issues/1876)) ([ea02e5d](https://github.com/googleapis/java-spanner-jdbc/commit/ea02e5da9d220782c2223bc7f2d4969e70a1b868)) + + +### Documentation + +* Add sample for using array of struct query param ([#1871](https://github.com/googleapis/java-spanner-jdbc/issues/1871)) ([d7cb90d](https://github.com/googleapis/java-spanner-jdbc/commit/d7cb90d264eaf0793422d3bfcaadd5be2ebd6412)) + ## [2.25.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.1...v2.25.2) (2024-12-19) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 12015e861c8d..ec61e362211b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.25.2 + 2.25.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 22f3cbaae76c..306777953675 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.3-SNAPSHOT + 2.25.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index bcefd78384be..0e135825bd5d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.3-SNAPSHOT + 2.25.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5a79df343fde..d3b8ba19e6ea 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.2:2.25.3-SNAPSHOT +google-cloud-spanner-jdbc:2.25.3:2.25.3 From 4478acca85b8932391bdb88b91260c11a39f0d8a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:46:32 +0000 Subject: [PATCH 1530/1979] chore(main): release 2.25.4-SNAPSHOT (#1882) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 306777953675..a6bcd5bcacea 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.3 + 2.25.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0e135825bd5d..ea33b94e4bea 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.3 + 2.25.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d3b8ba19e6ea..bf44f183031d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.3:2.25.3 +google-cloud-spanner-jdbc:2.25.3:2.25.4-SNAPSHOT From 71c0b81c130f3b69f04b12b4e2c03b97933d028b Mon Sep 17 00:00:00 2001 From: Sagnik Ghosh Date: Wed, 8 Jan 2025 19:35:37 +0530 Subject: [PATCH 1531/1979] feat: support for spanner external host (#1884) * feat(spanner): jdbc support for spanner external host * added unit tests for the new introduced pattern --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 9 +++++- .../cloud/spanner/jdbc/JdbcDriverTest.java | 31 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 6bb70283f0cc..3fb70106a113 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -25,6 +25,7 @@ import com.google.cloud.spanner.connection.ConnectionOptionsHelper; import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.ConnectionProperty; +import com.google.common.annotations.VisibleForTesting; import com.google.rpc.Code; import io.opentelemetry.api.OpenTelemetry; import java.sql.Connection; @@ -145,6 +146,11 @@ public class JdbcDriver implements Driver { private static final String JDBC_URL_FORMAT = "jdbc:" + ConnectionOptions.Builder.SPANNER_URI_FORMAT; private static final Pattern URL_PATTERN = Pattern.compile(JDBC_URL_FORMAT); + private static final String JDBC_EXTERNAL_HOST_FORMAT = + "jdbc:" + ConnectionOptions.Builder.EXTERNAL_HOST_FORMAT; + + @VisibleForTesting + static final Pattern EXTERNAL_HOST_URL_PATTERN = Pattern.compile(JDBC_EXTERNAL_HOST_FORMAT); @InternalApi public static String getClientLibToken() { @@ -213,7 +219,8 @@ public Connection connect(String url, Properties info) throws SQLException { if (url != null && url.startsWith("jdbc:cloudspanner")) { try { Matcher matcher = URL_PATTERN.matcher(url); - if (matcher.matches()) { + Matcher matcherExternalHost = EXTERNAL_HOST_URL_PATTERN.matcher(url); + if (matcher.matches() || matcherExternalHost.matches()) { // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic // Connection API String connectionUri = appendPropertiesToUrl(url.substring(5), info); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 020848e1eae7..b4ae04f56801 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -16,8 +16,10 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.JdbcDriver.EXTERNAL_HOST_URL_PATTERN; import static com.google.common.truth.Truth.assertThat; 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 static org.junit.Assert.fail; @@ -47,6 +49,7 @@ import java.util.Collection; import java.util.Objects; import java.util.Properties; +import java.util.regex.Matcher; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -211,4 +214,32 @@ public void testLenient() throws SQLException { assertThat(jdbc.getCode()).isEqualTo(Code.INVALID_ARGUMENT); } } + + @Test + public void testJdbcExternalHostFormat() { + Matcher matcherWithoutInstance = + EXTERNAL_HOST_URL_PATTERN.matcher("jdbc:cloudspanner://localhost:15000/databases/test-db"); + assertTrue(matcherWithoutInstance.matches()); + assertEquals("test-db", matcherWithoutInstance.group("DATABASEGROUP")); + Matcher matcherWithProperty = + EXTERNAL_HOST_URL_PATTERN.matcher( + "jdbc:cloudspanner://localhost:15000/instances/default/databases/singers-db?usePlainText=true"); + assertTrue(matcherWithProperty.matches()); + assertEquals("default", matcherWithProperty.group("INSTANCEGROUP")); + assertEquals("singers-db", matcherWithProperty.group("DATABASEGROUP")); + Matcher matcherWithoutPort = + EXTERNAL_HOST_URL_PATTERN.matcher( + "jdbc:cloudspanner://localhost/instances/default/databases/test-db"); + assertTrue(matcherWithoutPort.matches()); + assertEquals("default", matcherWithoutPort.group("INSTANCEGROUP")); + assertEquals("test-db", matcherWithoutPort.group("DATABASEGROUP")); + Matcher matcherWithProject = + EXTERNAL_HOST_URL_PATTERN.matcher( + "jdbc:cloudspanner://localhost:15000/projects/default/instances/default/databases/singers-db"); + assertFalse(matcherWithProject.matches()); + Matcher matcherWithoutHost = + EXTERNAL_HOST_URL_PATTERN.matcher( + "jdbc:cloudspanner:/instances/default/databases/singers-db"); + assertFalse(matcherWithoutHost.matches()); + } } From 2c2fb95d0629482bbe7932b96b695c5ad0d860dd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Jan 2025 15:05:51 +0100 Subject: [PATCH 1532/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.25.3 (#1883) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 5b713984cbfe..91840fd45654 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.2 + 2.25.3 From 4c6c59efbee96c416f9fc735da031c2a16262e39 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 11 Jan 2025 07:41:53 +0100 Subject: [PATCH 1533/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.41.1 (#1886) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 9150bf459c8a..547bea04a82b 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.41.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.41.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 76ca3ee6dafa..9705694f8348 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.41.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.41.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 644bb62ce7d3..b070666b48ed 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.41.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.41.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a6bcd5bcacea..f2e87f887c7c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.41.0 + 3.41.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 15b8b27da358..7dfc53f7f223 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.41.0 + 3.41.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 11b8346b99ca..431ac24bc34d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.41.0 + 3.41.1 From 4e122d6bd8dabf5e8d5219549949d56397e29194 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 11 Jan 2025 07:42:06 +0100 Subject: [PATCH 1534/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.56.0 (#1887) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f2e87f887c7c..7372416ef56e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.55.0 + 2.56.0 test From ca6dd7601ed8750b67a2e9983b671458a4285bcf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 11 Jan 2025 07:42:19 +0100 Subject: [PATCH 1535/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.56.0 (#1888) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7372416ef56e..e4db8c2a352d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -210,7 +210,7 @@ com.google.cloud google-cloud-trace - 2.55.0 + 2.56.0 test From 3cbf0b699d1b2e9c8a5c6393f309d5c0f627688a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 11 Jan 2025 08:08:22 +0100 Subject: [PATCH 1536/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.85.0 (#1889) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e4db8c2a352d..5d136645a1cb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.84.0 + 6.85.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2ac50a807f6d..b945992ef73d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.84.0 + 6.85.0 import pom From 87a5026895b02362b9ff99b4d7223339a7087cf9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 10:52:26 +0000 Subject: [PATCH 1537/1979] chore(main): release 2.26.0 (#1885) :robot: I have created a release *beep* *boop* --- ## [2.26.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.25.3...v2.26.0) (2025-01-11) ### Features * Support for spanner external host ([#1884](https://togithub.com/googleapis/java-spanner-jdbc/issues/1884)) ([71c0b81](https://togithub.com/googleapis/java-spanner-jdbc/commit/71c0b81c130f3b69f04b12b4e2c03b97933d028b)) ### Dependencies * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.56.0 ([#1887](https://togithub.com/googleapis/java-spanner-jdbc/issues/1887)) ([4e122d6](https://togithub.com/googleapis/java-spanner-jdbc/commit/4e122d6bd8dabf5e8d5219549949d56397e29194)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.85.0 ([#1889](https://togithub.com/googleapis/java-spanner-jdbc/issues/1889)) ([3cbf0b6](https://togithub.com/googleapis/java-spanner-jdbc/commit/3cbf0b699d1b2e9c8a5c6393f309d5c0f627688a)) * Update dependency com.google.cloud:google-cloud-trace to v2.56.0 ([#1888](https://togithub.com/googleapis/java-spanner-jdbc/issues/1888)) ([ca6dd76](https://togithub.com/googleapis/java-spanner-jdbc/commit/ca6dd7601ed8750b67a2e9983b671458a4285bcf)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.41.1 ([#1886](https://togithub.com/googleapis/java-spanner-jdbc/issues/1886)) ([4c6c59e](https://togithub.com/googleapis/java-spanner-jdbc/commit/4c6c59efbee96c416f9fc735da031c2a16262e39)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 64e1e8f81121..24f175e80cf9 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [2.26.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.3...v2.26.0) (2025-01-11) + + +### Features + +* Support for spanner external host ([#1884](https://github.com/googleapis/java-spanner-jdbc/issues/1884)) ([123a7bc](https://github.com/googleapis/java-spanner-jdbc/commit/123a7bcd9825b20bfbf7e9b057c2bd0f5213cac3)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.56.0 ([#1887](https://github.com/googleapis/java-spanner-jdbc/issues/1887)) ([2016d9c](https://github.com/googleapis/java-spanner-jdbc/commit/2016d9c47a5c6d12ba101827fe933c3ddd334e78)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.85.0 ([#1889](https://github.com/googleapis/java-spanner-jdbc/issues/1889)) ([3424d38](https://github.com/googleapis/java-spanner-jdbc/commit/3424d382a89b33d0870b00f04fd10dafa62bcc3d)) +* Update dependency com.google.cloud:google-cloud-trace to v2.56.0 ([#1888](https://github.com/googleapis/java-spanner-jdbc/issues/1888)) ([ce78b18](https://github.com/googleapis/java-spanner-jdbc/commit/ce78b188e70f30776e58a1e3a7d8c4b1559e4d68)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.41.1 ([#1886](https://github.com/googleapis/java-spanner-jdbc/issues/1886)) ([73eacc6](https://github.com/googleapis/java-spanner-jdbc/commit/73eacc66bacfd5c367f764ed3db805309cb0d1c8)) + ## [2.25.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.2...v2.25.3) (2025-01-06) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ec61e362211b..1c0c6b101221 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.25.3 + 2.26.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.25.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.26.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.25.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.26.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5d136645a1cb..8d8afb2911d0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.25.4-SNAPSHOT + 2.26.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ea33b94e4bea..5f470ec17574 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.4-SNAPSHOT + 2.26.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bf44f183031d..bab76b3917d9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.25.3:2.25.4-SNAPSHOT +google-cloud-spanner-jdbc:2.26.0:2.26.0 From f827d8abf14328112f40e9855f4cb98bf50e03e0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sun, 12 Jan 2025 11:00:44 +0100 Subject: [PATCH 1538/1979] chore(main): release 2.26.1-SNAPSHOT (#1890) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8d8afb2911d0..97247da74a7c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.26.0 + 2.26.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5f470ec17574..29756ee5cd69 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.0 + 2.26.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index bab76b3917d9..a213c31c026e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.26.0:2.26.0 +google-cloud-spanner-jdbc:2.26.0:2.26.1-SNAPSHOT From 31095e0a1add444c8308f0cab8b0354c6913baff Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 12 Jan 2025 11:11:40 +0100 Subject: [PATCH 1539/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.26.0 (#1891) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 91840fd45654..ee49952b5c43 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.25.3 + 2.26.0 From a24d44ba3ed8444f0af29cd6b3518f7f0ef3e2ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 12 Jan 2025 11:11:59 +0100 Subject: [PATCH 1540/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.46.0 (#1892) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index b945992ef73d..0ab871aa0562 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.45.0 + 1.46.0 pom import From b1c46412f9b7959a4353acaa6b4f438e774f1360 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:06:22 +0100 Subject: [PATCH 1541/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.2 (#1899) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/spring-projects/spring-boot)) | `3.4.1` -> `3.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.4.2?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.4.2?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.4.1/3.4.2?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.4.1/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.4.2`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 73ff402e260f..dcb1f09d2ba8 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.1 + 3.4.2 From 9620ec3c3c0dae376ea6312595d5b68474225ad5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:08:25 +0100 Subject: [PATCH 1542/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.53.0 (#1895) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.52.0` -> `26.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.52.0/26.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.52.0/26.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.53.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26530-2025-01-15) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.52.0...v26.53.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.41.1 ([#​6899](https://redirect.github.com/googleapis/java-cloud-bom/issues/6899)) ([1c01b89](https://redirect.github.com/googleapis/java-cloud-bom/commit/1c01b894a0f5863a1a1afa563bbe3d605c0d18be)) - update dependency com.google.cloud:gapic-libraries-bom to v1.50.0 ([#​6902](https://redirect.github.com/googleapis/java-cloud-bom/issues/6902)) ([b7d83c9](https://redirect.github.com/googleapis/java-cloud-bom/commit/b7d83c93df2eac51c5d48b2eaa788cf02d7f9f1e)) - update dependency com.google.cloud:google-cloud-bigquery to v2.46.0 ([#​6911](https://redirect.github.com/googleapis/java-cloud-bom/issues/6911)) ([f37e24d](https://redirect.github.com/googleapis/java-cloud-bom/commit/f37e24d824447fa376aa414578705d4c8bb5136f)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.11.1 ([#​6905](https://redirect.github.com/googleapis/java-cloud-bom/issues/6905)) ([177c6ef](https://redirect.github.com/googleapis/java-cloud-bom/commit/177c6ef965e1081f86042f11e73347ae4efbe2d4)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.51.1 ([#​6906](https://redirect.github.com/googleapis/java-cloud-bom/issues/6906)) ([dc06ef0](https://redirect.github.com/googleapis/java-cloud-bom/commit/dc06ef047e86ed7101ea52ce623807d73c6cf823)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.25.2 ([#​6907](https://redirect.github.com/googleapis/java-cloud-bom/issues/6907)) ([1413e7a](https://redirect.github.com/googleapis/java-cloud-bom/commit/1413e7aaa4728d078e7309ba9efb06d80c459010)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.30.3 ([#​6910](https://redirect.github.com/googleapis/java-cloud-bom/issues/6910)) ([692b250](https://redirect.github.com/googleapis/java-cloud-bom/commit/692b250e94d489752aee904ad5e0a075fb133745)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.21.1 ([#​6912](https://redirect.github.com/googleapis/java-cloud-bom/issues/6912)) ([b617eee](https://redirect.github.com/googleapis/java-cloud-bom/commit/b617eeef8b6739830fae536f355c1f989c6ea628)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.132.1-alpha ([#​6913](https://redirect.github.com/googleapis/java-cloud-bom/issues/6913)) ([7a0748f](https://redirect.github.com/googleapis/java-cloud-bom/commit/7a0748f0f7cad5071248784a7628e916cee7abfb)) - update dependency com.google.cloud:google-cloud-nio to v0.127.29 ([#​6901](https://redirect.github.com/googleapis/java-cloud-bom/issues/6901)) ([2a7f123](https://redirect.github.com/googleapis/java-cloud-bom/commit/2a7f1239603a42ec1ebb4935bab8c2761d3e9093)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.136.0 ([#​6909](https://redirect.github.com/googleapis/java-cloud-bom/issues/6909)) ([3abbe0e](https://redirect.github.com/googleapis/java-cloud-bom/commit/3abbe0e2c89d6e493155d9fcb06acb1fcfd2ebee)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.15.1 ([#​6908](https://redirect.github.com/googleapis/java-cloud-bom/issues/6908)) ([68830a5](https://redirect.github.com/googleapis/java-cloud-bom/commit/68830a5464a90fdc18580baa47bfbe260071201e)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.85.0 ([#​6898](https://redirect.github.com/googleapis/java-cloud-bom/issues/6898)) ([f8b4af6](https://redirect.github.com/googleapis/java-cloud-bom/commit/f8b4af6f54d1133a083aa7bc869bbb0a8a55840c)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.26.0 ([#​6896](https://redirect.github.com/googleapis/java-cloud-bom/issues/6896)) ([42aa242](https://redirect.github.com/googleapis/java-cloud-bom/commit/42aa2428f0027ea96a5b3951ae591e9b5bb70ede)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.47.0 ([#​6900](https://redirect.github.com/googleapis/java-cloud-bom/issues/6900)) ([4ff7d59](https://redirect.github.com/googleapis/java-cloud-bom/commit/4ff7d59840c42edf2a60541b51636394005ad9c0)) - update protobuf to 4.29.0 ([#​6903](https://redirect.github.com/googleapis/java-cloud-bom/issues/6903)) ([a5a6f30](https://redirect.github.com/googleapis/java-cloud-bom/commit/a5a6f303272a78c11e465d4f3f54fdfe3eeb0ede))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 7dfc53f7f223..b2335f1e0c71 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.52.0 + 26.53.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 431ac24bc34d..30155cb65621 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.52.0 + 26.53.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 0ab871aa0562..2c6745053593 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.52.0 + 26.53.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index dcb1f09d2ba8..a3e9c21bad36 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.52.0 + 26.53.0 import pom From 51830f2ed7b3ba7448f9e6da7d21e4b533445fd0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:08:29 +0100 Subject: [PATCH 1543/1979] deps: update dependency org.postgresql:postgresql to v42.7.5 (#1894) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.postgresql:postgresql](https://jdbc.postgresql.org) ([source](https://redirect.github.com/pgjdbc/pgjdbc)) | `42.7.4` -> `42.7.5` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.postgresql:postgresql/42.7.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.postgresql:postgresql/42.7.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.postgresql:postgresql/42.7.4/42.7.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.postgresql:postgresql/42.7.4/42.7.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    pgjdbc/pgjdbc (org.postgresql:postgresql) ### [`v42.7.5`](https://redirect.github.com/pgjdbc/pgjdbc/blob/HEAD/CHANGELOG.md#4275-2025-01-14-080000--0400) ##### Added - ci: Test with Java 23 [PR #​3381](https://redirect.github.com/pgjdbc/pgjdbc/pull/3381) ##### Fixed - regression: revert change in [`fc60537`](https://redirect.github.com/pgjdbc/pgjdbc/commit/fc60537) [PR #​3476](https://redirect.github.com/pgjdbc/pgjdbc/pull/3476) - fix: PgDatabaseMetaData implementation of catalog as param and return value [PR #​3390](https://redirect.github.com/pgjdbc/pgjdbc/pull/3390) - fix: Support default GSS credentials in the Java Postgres client [PR #​3451](https://redirect.github.com/pgjdbc/pgjdbc/pull/3451) - fix: return only the transactions accessible by the current_user in XAResource.recover [PR #​3450](https://redirect.github.com/pgjdbc/pgjdbc/pull/3450) - feat: don't force send extra_float_digits for PostgreSQL >= 12 fix [Issue #​3432](https://redirect.github.com/pgjdbc/pgjdbc/issues/3432) [PR #​3446](https://redirect.github.com/pgjdbc/pgjdbc/pull/3446) - fix: exclude "include columns" from the list of primary keys [PR #​3434](https://redirect.github.com/pgjdbc/pgjdbc/pull/3434) - perf: Enhance the meta query performance by specifying the oid. [PR #​3427](https://redirect.github.com/pgjdbc/pgjdbc/pull/3427) - feat: support getObject(int, byte\[].class) for bytea [PR #​3274](https://redirect.github.com/pgjdbc/pgjdbc/pull/3274) - docs: document infinity and some minor edits [PR #​3407](https://redirect.github.com/pgjdbc/pgjdbc/pull/3407) - fix: Added way to check for major server version, fixed check for RULE [PR #​3402](https://redirect.github.com/pgjdbc/pgjdbc/pull/3402) - docs: fixed remaining paragraphs [PR #​3398](https://redirect.github.com/pgjdbc/pgjdbc/pull/3398) - docs: fixed paragraphs in javadoc comments [PR #​3397](https://redirect.github.com/pgjdbc/pgjdbc/pull/3397) - fix: Reuse buffers and reduce allocations in GSSInputStream addresses [Issue #​3251](https://redirect.github.com/pgjdbc/pgjdbc/issues/3251) [PR #​3255](https://redirect.github.com/pgjdbc/pgjdbc/pull/3255) - chore: Update Gradle to 8.10.2 [PR #​3388](https://redirect.github.com/pgjdbc/pgjdbc/pull/3388) - fix: getSchemas() [PR #​3386](https://redirect.github.com/pgjdbc/pgjdbc/pull/3386) - fix: Update rpm postgresql-jdbc.spec.tpl with scram-client [PR #​3324](https://redirect.github.com/pgjdbc/pgjdbc/pull/3324) - fix: Clearing thisRow and rowBuffer on close() of ResultSet [Issue #​3383](https://redirect.github.com/pgjdbc/pgjdbc/issues/3383) [PR #​3384](https://redirect.github.com/pgjdbc/pgjdbc/pull/3384) - fix: Package was renamed to maven-bundle-plugin [PR #​3382](https://redirect.github.com/pgjdbc/pgjdbc/pull/3382) - fix: As of version 18 the RULE privilege has been removed [PR #​3378](https://redirect.github.com/pgjdbc/pgjdbc/pull/3378) - fix: use buffered inputstream to create GSSInputStream [PR #​3373](https://redirect.github.com/pgjdbc/pgjdbc/pull/3373) - test: get rid of 8.4, 9.0 pg versions and use >= jdk version 17 [PR #​3372](https://redirect.github.com/pgjdbc/pgjdbc/pull/3372) - Changed docker-compose version and renamed script file in instructions to match the real file name [PR #​3363](https://redirect.github.com/pgjdbc/pgjdbc/pull/3363) - test:Do not assume "test" database in DatabaseMetaDataTransactionIsolationTest [PR #​3364](https://redirect.github.com/pgjdbc/pgjdbc/pull/3364) - try to categorize dependencies [PR #​3362](https://redirect.github.com/pgjdbc/pgjdbc/pull/3362)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2c6745053593..7e82d0eb9cdb 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -72,7 +72,7 @@ org.postgresql postgresql - 42.7.4 + 42.7.5 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index a3e9c21bad36..9e087167b43c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.4 + 42.7.5 org.testcontainers From 320f97e9fbac80734a80bcf3be538981d5cba3e4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:10:20 +0100 Subject: [PATCH 1544/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.2 (#1896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.data:spring-data-bom](https://redirect.github.com/spring-projects/spring-data-bom) | `2024.1.1` -> `2024.1.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.data:spring-data-bom/2024.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.data:spring-data-bom/2024.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.data:spring-data-bom/2024.1.1/2024.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.data:spring-data-bom/2024.1.1/2024.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-data-bom (org.springframework.data:spring-data-bom) ### [`v2024.1.2`](https://redirect.github.com/spring-projects/spring-data-bom/releases/tag/2024.1.2) [Compare Source](https://redirect.github.com/spring-projects/spring-data-bom/compare/2024.1.1...2024.1.2) ##### :shipit: Participating Modules - [Spring Data BOM 2024.1.2](https://redirect.github.com/spring-projects/spring-data-bom/releases/tag/2024.1.2) - [Spring Data Build 3.4.2](https://redirect.github.com/spring-projects/spring-data-build/releases/tag/3.4.2) - [Spring Data Cassandra 4.4.2](https://redirect.github.com/spring-projects/spring-data-cassandra/releases/tag/4.4.2) - [Spring Data Commons 3.4.2](https://redirect.github.com/spring-projects/spring-data-commons/releases/tag/3.4.2) - [Spring Data Couchbase 5.4.2](https://redirect.github.com/spring-projects/spring-data-couchbase/releases/tag/5.4.2) - [Spring Data Elasticsearch 5.4.2](https://redirect.github.com/spring-projects/spring-data-elasticsearch/releases/tag/5.4.2) - [Spring Data JPA 3.4.2](https://redirect.github.com/spring-projects/spring-data-jpa/releases/tag/3.4.2) - [Spring Data KeyValue 3.4.2](https://redirect.github.com/spring-projects/spring-data-keyvalue/releases/tag/3.4.2) - [Spring Data LDAP 3.4.2](https://redirect.github.com/spring-projects/spring-data-ldap/releases/tag/3.4.2) - [Spring Data MongoDB 4.4.2](https://redirect.github.com/spring-projects/spring-data-mongodb/releases/tag/4.4.2) - [Spring Data Neo4j 7.4.2](https://redirect.github.com/spring-projects/spring-data-neo4j/releases/tag/7.4.2) - [Spring Data REST 4.4.2](https://redirect.github.com/spring-projects/spring-data-rest/releases/tag/4.4.2) - [Spring Data Redis 3.4.2](https://redirect.github.com/spring-projects/spring-data-redis/releases/tag/3.4.2) - [Spring Data Relational 3.4.2](https://redirect.github.com/spring-projects/spring-data-relational/releases/tag/3.4.2)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 7e82d0eb9cdb..1c0c50bed34c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.1 + 2024.1.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 9e087167b43c..efe2cab83a2a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.1 + 2024.1.2 import pom From d768c8018a7caff22bcf7286f1594829eea175e5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:10:26 +0100 Subject: [PATCH 1545/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.2 (#1898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-data-jdbc](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `3.4.1` -> `3.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.4.1/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.4.1/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-data-jdbc) ### [`v3.4.2`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 1c0c50bed34c..21d6402ef9ac 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.1 + 3.4.2 From f75be2c06adcfb3557de450b69c510a9eb7724dd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 25 Jan 2025 12:16:23 +0100 Subject: [PATCH 1546/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.2 (#1897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `3.4.1` -> `3.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.4.1/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.4.1/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.4.2`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.1...v3.4.2)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index b2335f1e0c71..d7331c74c230 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.1 + 3.4.2 test From fbbe9f8fbb61925d1fa94b0d3e060a58693a4ffc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Jan 2025 15:13:41 +0100 Subject: [PATCH 1547/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.42.0 (#1900) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 547bea04a82b..6d507150e8ff 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.41.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.42.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 9705694f8348..b78c82df571b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.41.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.42.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index b070666b48ed..f08c4be3e00b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.41.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.42.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97247da74a7c..b2aa37b2b08d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.41.1 + 3.42.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d7331c74c230..6a5c76eafb30 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.41.1 + 3.42.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 30155cb65621..ba325ff3289d 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.41.1 + 3.42.0 From c91385d4dcecae60e369616695fd20c7e7fdebd3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Jan 2025 15:24:02 +0100 Subject: [PATCH 1548/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.57.0 (#1901) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b2aa37b2b08d..f5a52f26a0b2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.56.0 + 2.57.0 test From a8e1df82e984fea581109b46a459f6fbbdb1825d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 29 Jan 2025 15:24:22 +0100 Subject: [PATCH 1549/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.57.0 (#1902) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f5a52f26a0b2..9eb8e49af499 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -210,7 +210,7 @@ com.google.cloud google-cloud-trace - 2.56.0 + 2.57.0 test From 15303773c8472d1999008fbb25582f79f2d46034 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 3 Feb 2025 08:00:47 +0100 Subject: [PATCH 1550/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.86.0 (#1903) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9eb8e49af499..928af8186cf0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.85.0 + 6.86.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 21d6402ef9ac..c765eb278e6e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.85.0 + 6.86.0 import pom From 3ef7a13f788f36d38b74bfd3fdac752a80e34072 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 08:39:30 +0100 Subject: [PATCH 1551/1979] chore(main): release 2.26.1 (#1893) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 24f175e80cf9..ae96e3365bba 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.26.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.26.0...v2.26.1) (2025-02-03) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.57.0 ([#1901](https://github.com/googleapis/java-spanner-jdbc/issues/1901)) ([9170f97](https://github.com/googleapis/java-spanner-jdbc/commit/9170f97171da09c730742bb8198c6893cca72205)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.86.0 ([#1903](https://github.com/googleapis/java-spanner-jdbc/issues/1903)) ([7eb727d](https://github.com/googleapis/java-spanner-jdbc/commit/7eb727d2b656d2488f2d7246793b6e09925940cd)) +* Update dependency com.google.cloud:google-cloud-trace to v2.57.0 ([#1902](https://github.com/googleapis/java-spanner-jdbc/issues/1902)) ([f7efb1b](https://github.com/googleapis/java-spanner-jdbc/commit/f7efb1b578fd0b04743090be39b7a7351dc9ba05)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.42.0 ([#1900](https://github.com/googleapis/java-spanner-jdbc/issues/1900)) ([be47dd6](https://github.com/googleapis/java-spanner-jdbc/commit/be47dd622954e4112486b2760a2e3c534a2e69b8)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.46.0 ([#1892](https://github.com/googleapis/java-spanner-jdbc/issues/1892)) ([c700c9c](https://github.com/googleapis/java-spanner-jdbc/commit/c700c9c9a4f6844360f6257a5e57aceff03cfa00)) +* Update dependency org.postgresql:postgresql to v42.7.5 ([#1894](https://github.com/googleapis/java-spanner-jdbc/issues/1894)) ([b965f02](https://github.com/googleapis/java-spanner-jdbc/commit/b965f02d6992f4f1b38d1670d389f2bc91e21ee3)) +* Update dependency org.springframework.boot:spring-boot to v3.4.2 ([#1897](https://github.com/googleapis/java-spanner-jdbc/issues/1897)) ([b567c2c](https://github.com/googleapis/java-spanner-jdbc/commit/b567c2ca8301fe97be52cddf9d223f6a5c0e9925)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.2 ([#1898](https://github.com/googleapis/java-spanner-jdbc/issues/1898)) ([14d2368](https://github.com/googleapis/java-spanner-jdbc/commit/14d236857a7c7ab5e3a5172c31405ba892bd39de)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.2 ([#1899](https://github.com/googleapis/java-spanner-jdbc/issues/1899)) ([0381a31](https://github.com/googleapis/java-spanner-jdbc/commit/0381a318da286e016291a299f30765aa4d0cc9f6)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.2 ([#1896](https://github.com/googleapis/java-spanner-jdbc/issues/1896)) ([d819620](https://github.com/googleapis/java-spanner-jdbc/commit/d8196205c34725ac48db346982ec73013a1da57e)) + ## [2.26.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.25.3...v2.26.0) (2025-01-11) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 1c0c6b101221..e56fd25a4636 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.26.0 + 2.26.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.26.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.26.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.26.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.26.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 928af8186cf0..b3dd1c549259 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.26.1-SNAPSHOT + 2.26.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 29756ee5cd69..9bbb7da49c9e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.1-SNAPSHOT + 2.26.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a213c31c026e..0befe28d9de6 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.26.0:2.26.1-SNAPSHOT +google-cloud-spanner-jdbc:2.26.1:2.26.1 From 157b9ec113e2a42fb82423925e17f27de026d5ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 3 Feb 2025 13:42:22 +0100 Subject: [PATCH 1552/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.26.1 (#1905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.26.0` -> `2.26.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.26.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.26.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.26.0/2.26.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.26.0/2.26.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.26.1`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2261-2025-02-03) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.26.0...v2.26.1) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.57.0 ([#​1901](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1901)) ([c91385d](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/c91385d4dcecae60e369616695fd20c7e7fdebd3)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.86.0 ([#​1903](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1903)) ([1530377](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/15303773c8472d1999008fbb25582f79f2d46034)) - Update dependency com.google.cloud:google-cloud-trace to v2.57.0 ([#​1902](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1902)) ([a8e1df8](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/a8e1df82e984fea581109b46a459f6fbbdb1825d)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.42.0 ([#​1900](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1900)) ([fbbe9f8](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/fbbe9f8fbb61925d1fa94b0d3e060a58693a4ffc)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.46.0 ([#​1892](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1892)) ([a24d44b](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/a24d44ba3ed8444f0af29cd6b3518f7f0ef3e2ce)) - Update dependency org.postgresql:postgresql to v42.7.5 ([#​1894](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1894)) ([51830f2](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/51830f2ed7b3ba7448f9e6da7d21e4b533445fd0)) - Update dependency org.springframework.boot:spring-boot to v3.4.2 ([#​1897](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1897)) ([f75be2c](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/f75be2c06adcfb3557de450b69c510a9eb7724dd)) - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.2 ([#​1898](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1898)) ([d768c80](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/d768c8018a7caff22bcf7286f1594829eea175e5)) - Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.2 ([#​1899](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1899)) ([b1c4641](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/b1c46412f9b7959a4353acaa6b4f438e774f1360)) - Update dependency org.springframework.data:spring-data-bom to v2024.1.2 ([#​1896](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/1896)) ([320f97e](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/320f97e9fbac80734a80bcf3be538981d5cba3e4))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ee49952b5c43..ef9e179f9daf 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.0 + 2.26.1 From fead64c3a588af9af4d6a267ac10b8e7ffe3dd5a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 6 Feb 2025 14:35:17 +0100 Subject: [PATCH 1553/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.54.0 (#1906) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6a5c76eafb30..f0670c6e6a10 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.53.0 + 26.54.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ba325ff3289d..697da8e6c14a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.53.0 + 26.54.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c765eb278e6e..39e4aacb1e53 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.53.0 + 26.54.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index efe2cab83a2a..b5f472e44564 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.53.0 + 26.54.0 import pom From 80d16130c7c466ec98522a82712e8f56e5fd7cbb Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:12:41 +0100 Subject: [PATCH 1554/1979] chore(main): release 2.26.2-SNAPSHOT (#1904) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b3dd1c549259..407823276e7c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.26.1 + 2.26.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9bbb7da49c9e..bc7048666985 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.1 + 2.26.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0befe28d9de6..a3cc8f9a1769 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.26.1:2.26.1 +google-cloud-spanner-jdbc:2.26.1:2.26.2-SNAPSHOT From 378149dff165b49cd3b69fc0f5020445230a36a4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Feb 2025 12:18:21 +0100 Subject: [PATCH 1555/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.47.0 (#1907) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://redirect.github.com/open-telemetry/opentelemetry-java) | `1.46.0` -> `1.47.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.46.0/1.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.46.0/1.47.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.47.0`](https://redirect.github.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1470-2025-02-07) [Compare Source](https://redirect.github.com/open-telemetry/opentelemetry-java/compare/v1.46.0...v1.47.0) ##### API ##### Incubator - Make `ExtendedTracer` easier to use ([#​6943](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6943)) - Add `ExtendedLogRecordBuilder#setEventName` and corresponding SDK and OTLP serialization ([#​7012](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7012)) - BREAKING: Drop event API / SDK ([#​7053](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7053)) ##### SDK - Remove -alpha artifacts from runtime classpath of stable components ([#​6944](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6944)) ##### Traces - Bugfix: Follow spec on span limits, batch processors ([#​7030](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7030)) - Add experimental `SdkTracerProvider.setScopeConfigurator(ScopeConfigurator)` for updating `TracerConfig` at runtime ([#​7021](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7021)) ##### Profiles - Add AttributeKeyValue abstraction to common otlp exporters ([#​7026](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7026)) - Improve profiles attribute table handling ([#​7031](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7031)) ##### Exporters - Interpret timeout zero value as no limit ([#​7023](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7023)) - Bugfix - OTLP: Fix concurrent span reusable data marshaler ([#​7041](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7041)) - OTLP: Add ability to customize retry exception predicate ([#​6991](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/6991)) - OTLP: Expand default OkHttp sender retry exception predicate ([#​7047](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7047), [#​7057](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7057)) ##### Extensions - Autoconfigure: Consistent application of exporter customizers when otel.{signal}.exporter=none ([#​7017](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7017)) - Autoconfigure: Promote EnvironmentResourceProvider to public API ([#​7052](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7052)) - Autoconfigure: Ensure `OTEL_PROPAGATORS` still works when `OTEL_SDK_DISABLED=true`. ([#​7062](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7062))% ##### Testing - Add W3CBaggagePropagator to `OpenTelemetryRule`, `OpenTelemetryExtension`. ([#​7056](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7056))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 39e4aacb1e53..a82f6f93cfc9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.46.0 + 1.47.0 pom import From eb8f4b74f732b6d8d06107dfe2b8c381909d7554 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Feb 2025 12:20:46 +0100 Subject: [PATCH 1556/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.58.0 (#1909) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.57.0` -> `2.58.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.57.0/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.57.0/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 407823276e7c..21ec9ff68560 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.57.0 + 2.58.0 test From ca5bdc52520a0452d5141bd50b459618a3bdf090 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Feb 2025 12:20:49 +0100 Subject: [PATCH 1557/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.58.0 (#1910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.57.0` -> `2.58.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.57.0/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.57.0/2.58.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 21ec9ff68560..14e79cf8750e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -210,7 +210,7 @@ com.google.cloud google-cloud-trace - 2.57.0 + 2.58.0 test From e2206102adb981acc7b8fcf4ffcbdd0bb47d2303 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Feb 2025 16:07:05 +0100 Subject: [PATCH 1558/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.3 (#1913) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a82f6f93cfc9..c0abdd51d583 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.2 + 2024.1.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b5f472e44564..8d5884824e30 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.2 + 2024.1.3 import pom From 0d6ecbb3bb0dd814f3f4db66f3eb0f7a61415c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 15 Feb 2025 12:24:20 +0100 Subject: [PATCH 1559/1979] feat: add methods for unwrapping Spanner client (#1914) Adds methods for unwrapping the underlying DatabaseClient and Spanner instance that is used by a JDBC connection. --- .../clirr-ignored-differences.xml | 15 +++++++++++ .../spanner/jdbc/AbstractJdbcConnection.java | 15 ++++++++++- .../jdbc/CloudSpannerJdbcConnection.java | 25 ++++++++++++++++++ .../cloud/spanner/jdbc/DdlMockServerTest.java | 26 +++++++++++++++++++ .../spanner/jdbc/JdbcConnectionTest.java | 11 ++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index e82c99291022..547c9c44c7f3 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -108,4 +108,19 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection void setAutoBatchDmlUpdateCountVerification(boolean) + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.DatabaseClient getDatabaseClient() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.Spanner getSpanner() + + + 7012 + com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection + com.google.cloud.spanner.DatabaseId getDatabaseId() + diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 122d48967d5d..38430cf124db 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; @@ -68,6 +70,16 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper this.usesDirectExecutor = ConnectionOptionsHelper.usesDirectExecutor(options); } + @Override + public DatabaseId getDatabaseId() { + return this.options.getDatabaseId(); + } + + @Override + public DatabaseClient getDatabaseClient() { + return getSpannerConnection().getDatabaseClient(); + } + /** Return the corresponding {@link com.google.cloud.spanner.connection.Connection} */ com.google.cloud.spanner.connection.Connection getSpannerConnection() { return spanner; @@ -82,7 +94,8 @@ ConnectionOptions getConnectionOptions() { return options; } - Spanner getSpanner() { + @Override + public Spanner getSpanner() { return this.spanner.getSpanner(); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index b8491d12c52f..359854c9049a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -20,10 +20,13 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.CommitStats; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.Options.QueryOption; import com.google.cloud.spanner.PartitionOptions; +import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.connection.AutocommitDmlMode; import com.google.cloud.spanner.connection.SavepointSupport; @@ -47,6 +50,28 @@ */ public interface CloudSpannerJdbcConnection extends Connection { + /** + * Returns the {@link DatabaseId} of the database that this {@link Connection} is connected to. + */ + default DatabaseId getDatabaseId() { + throw new UnsupportedOperationException(); + } + + /** + * Returns the underlying {@link DatabaseClient} that is used by this connection. Operations that + * are executed on the {@link DatabaseClient} that is returned has no impact on this {@link + * Connection}, e.g. starting a read/write transaction on the {@link DatabaseClient} will not + * start a transaction on this connection. + */ + default DatabaseClient getDatabaseClient() { + throw new UnsupportedOperationException(); + } + + /** Returns the underlying {@link Spanner} instance that is used by this connection. */ + default Spanner getSpanner() { + throw new UnsupportedOperationException(); + } + /** * Sets the transaction tag to use for the current transaction. This method may only be called * when in a transaction, and before the transaction is actually started, i.e. before any diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java index 75f9d9efcbd9..7bca2369a713 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java @@ -24,15 +24,18 @@ import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.common.collect.ImmutableList; import com.google.longrunning.Operation; import com.google.protobuf.Any; import com.google.protobuf.Empty; import com.google.rpc.Code; +import com.google.spanner.admin.database.v1.GetDatabaseDdlResponse; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -50,6 +53,29 @@ private Connection createConnection(boolean autoCommit) throws SQLException { return DriverManager.getConnection(createUrl(autoCommit)); } + @Test + public void testGetDatabaseDdl() throws SQLException { + List expectedDdl = + ImmutableList.of( + "create table foo (id int64) primary key (id)", + "create table bar (id int64) primary key (id)"); + mockDatabaseAdmin.addResponse( + GetDatabaseDdlResponse.newBuilder().addAllStatements(expectedDdl).build()); + + try (Connection connection = createConnection(/* autoCommit = */ true)) { + CloudSpannerJdbcConnection spannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + List ddl = + spannerJdbcConnection + .getSpanner() + .getDatabaseAdminClient() + .getDatabaseDdl( + spannerJdbcConnection.getDatabaseId().getInstanceId().getInstance(), + spannerJdbcConnection.getDatabaseId().getDatabase()); + assertEquals(expectedDdl, ddl); + } + } + @Test public void testDdlInAutoCommitIsTrue_succeeds() throws SQLException { mockDatabaseAdmin.addResponse( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index a54c179b6053..e0ea49f6f7f2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/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.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -100,6 +101,16 @@ private ConnectionOptions mockOptions() { return options; } + @Test + public void testGetDatabaseClient() throws SQLException { + ConnectionOptions options = mockOptions(); + try (Connection connection = createConnection(options)) { + CloudSpannerJdbcConnection spannerJdbcConnection = + connection.unwrap(CloudSpannerJdbcConnection.class); + assertNotNull(spannerJdbcConnection.getDatabaseClient()); + } + } + @Test public void testAutoCommit() throws SQLException { ConnectionOptions options = mockOptions(); From 39416a54779f06383257fabe239c8901b1a14823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sun, 16 Feb 2025 07:57:23 +0100 Subject: [PATCH 1560/1979] docs: add sample for PROTO columns (#1918) Adds a sample for using PROTO columns with the JDBC driver. Fixes #1916 --- java-spanner-jdbc/README.md | 15 +- java-spanner-jdbc/samples/snapshot/pom.xml | 1 + java-spanner-jdbc/samples/snippets/pom.xml | 7 + .../com/example/spanner/jdbc/JdbcSample.java | 105 ++ .../com/example/spanner/jdbc/SingerProto.java | 1168 +++++++++++++++++ .../com/example/spanner/jdbc/README.md | 7 + .../com/example/spanner/jdbc/descriptors.pb | Bin 0 -> 377 bytes .../com/example/spanner/jdbc/singer.proto | 21 + .../example/spanner/jdbc/JdbcSampleTest.java | 19 + 9 files changed, 1341 insertions(+), 2 deletions(-) create mode 100644 java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/SingerProto.java create mode 100644 java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/README.md create mode 100644 java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/descriptors.pb create mode 100644 java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/singer.proto diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index e56fd25a4636..0e445bf001a9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -155,8 +155,19 @@ activate the `shade` profile like this: mvn package -Pshade ``` - - +## Samples + +See the [samples](/samples) directory for various examples for using the Spanner JDBC driver. + +- [snippets](/samples/snippets): Contains small code snippets for commonly used JDBC and Spanner + features. Refer to these snippets for examples on how to execute DDL and DML batches, use various + data types with the JDBC driver, execute various types of transactions (read/write, read-only, + Partitioned DML), use request and transaction tags, etc. +- [spring-data-jdbc](/samples/spring-data-jdbc): Contains a sample application that uses Spring Data + JDBC in combination with a Spanner PostgreSQL database. +- [spring-data-mybatis](/samples/spring-data-mybatis): Contains a sample application that uses + Spring Data MyBatis in combination with a Spanner PostgreSQL database. +- [quickperf](/samples/quickperf): Contains a simple benchmarking application. ## Troubleshooting diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index bc7048666985..ccd66c4ea00c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -15,6 +15,7 @@ com.google.cloud.samples shared-configuration 1.2.2 + diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 697da8e6c14a..56b88c472e5a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -122,6 +122,13 @@
    + + org.apache.maven.plugins + maven-checkstyle-plugin + + **/SingerProto.java + + diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java index a597d74302b5..2b340feb195c 100644 --- a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/JdbcSample.java @@ -16,6 +16,8 @@ package com.example.spanner.jdbc; +import com.example.spanner.jdbc.SingerProto.Genre; +import com.example.spanner.jdbc.SingerProto.SingerInfo; import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.cloud.spanner.DatabaseId; @@ -29,6 +31,8 @@ import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings; import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +import com.google.cloud.spanner.jdbc.ProtoEnumType; +import com.google.cloud.spanner.jdbc.ProtoMessageType; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.spanner.admin.database.v1.CreateDatabaseRequest; @@ -36,6 +40,8 @@ import com.google.spanner.admin.instance.v1.InstanceName; import com.google.spanner.v1.DatabaseName; import io.grpc.ManagedChannelBuilder; +import java.io.IOException; +import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -1576,6 +1582,98 @@ static void arrayOfStructAsQueryParameter( } } + static void protoColumns( + final String project, + final String instance, + final String database, + final Properties properties) throws SQLException, IOException { + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database), + properties)) { + // Create a PROTO BUNDLE and a table. + try (Statement statement = connection.createStatement(); + InputStream protoDescriptors = JdbcSample.class.getClassLoader() + .getResourceAsStream("com/example/spanner/jdbc/descriptors.pb")) { + if (protoDescriptors == null) { + throw new IllegalArgumentException("proto descriptors not found"); + } + + // Unwrap the CloudSpannerJdbcConnection interface to set the proto + // descriptors that should be used for the next DDL statements. + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setProtoDescriptors(protoDescriptors); + // Execute the DDL statements as one batch. + // This will reduce execution time compared to executing each statement + // sequentially. + statement.addBatch("CREATE PROTO BUNDLE (\n" + + "examples.spanner.music.SingerInfo,\n" + + "examples.spanner.music.Genre,\n" + + ")"); + statement.addBatch("CREATE TABLE SingersWithProto (\n" + + " SingerId INT64 NOT NULL,\n" + + " SingerInfo examples.spanner.music.SingerInfo,\n" + + " SingerGenre examples.spanner.music.Genre,\n" + + ") PRIMARY KEY (SingerId)"); + statement.executeBatch(); + } + + // Insert a couple of rows using a prepared statement. + try (PreparedStatement statement = connection.prepareStatement( + "INSERT INTO SingersWithProto " + + "(SingerId, SingerInfo, SingerGenre) " + + "VALUES (?, ?, ?)")) { + int param = 0; + statement.setLong(++param, 1L); + statement.setObject(++param, + SingerInfo.newBuilder() + .setGenre(Genre.ROCK) + .setBirthDate("1998-07-04") + .setSingerId(1L) + .setNationality("ES") + .build(), ProtoMessageType.VENDOR_TYPE_NUMBER); + statement.setObject(++param, Genre.ROCK, + ProtoEnumType.VENDOR_TYPE_NUMBER); + statement.addBatch(); + + param = 0; + statement.setLong(++param, 2L); + statement.setObject(++param, + SingerInfo.newBuilder() + .setGenre(Genre.POP) + .setBirthDate("2001-12-03") + .setSingerId(2L) + .setNationality("FO") + .build(), ProtoMessageType.VENDOR_TYPE_NUMBER); + statement.setObject(++param, Genre.POP, + ProtoEnumType.VENDOR_TYPE_NUMBER); + statement.addBatch(); + + int[] updateCounts = statement.executeBatch(); + System.out.printf("Inserted %d singers\n", + Arrays.stream(updateCounts).sum()); + } + + // Read the inserted rows. + try (ResultSet resultSet = connection.createStatement() + .executeQuery("SELECT * FROM SingersWithProto")) { + while (resultSet.next()) { + long singerId = resultSet.getLong("SingerId"); + // Proto messages and proto enums can be retrieved with the + // ResultSet#getObject(int, Class) method. + // The Spanner JDBC driver automatically deserializes + // and converts the column to the Java class representation. + SingerInfo info = resultSet.getObject("SingerInfo", SingerInfo.class); + Genre genre = resultSet.getObject("SingerGenre", Genre.class); + System.out.printf("%d:\n%s\n%s\n", singerId, info, genre); + } + } + } + } + /** The expected number of command line arguments. */ private static final int NUM_EXPECTED_ARGS = 3; @@ -1761,6 +1859,13 @@ static boolean runGoogleSQLSample( database.getDatabase(), createProperties()); return true; + case "protocolumns": + protoColumns( + database.getInstanceId().getProject(), + database.getInstanceId().getInstance(), + database.getDatabase(), + createProperties()); + return true; default: return false; } diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/SingerProto.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/SingerProto.java new file mode 100644 index 000000000000..382456a2eac1 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/SingerProto.java @@ -0,0 +1,1168 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: singer.proto + +package com.example.spanner.jdbc; + +public final class SingerProto { + private SingerProto() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + /** + * Protobuf enum {@code examples.spanner.music.Genre} + */ + public enum Genre + implements com.google.protobuf.ProtocolMessageEnum { + /** + * POP = 0; + */ + POP(0), + /** + * JAZZ = 1; + */ + JAZZ(1), + /** + * FOLK = 2; + */ + FOLK(2), + /** + * ROCK = 3; + */ + ROCK(3), + UNRECOGNIZED(-1), + ; + + /** + * POP = 0; + */ + public static final int POP_VALUE = 0; + /** + * JAZZ = 1; + */ + public static final int JAZZ_VALUE = 1; + /** + * FOLK = 2; + */ + public static final int FOLK_VALUE = 2; + /** + * ROCK = 3; + */ + public static final int ROCK_VALUE = 3; + + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalArgumentException( + "Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static Genre valueOf(int value) { + return forNumber(value); + } + + /** + * @param value The numeric wire value of the corresponding enum entry. + * @return The enum associated with the given numeric wire value. + */ + public static Genre forNumber(int value) { + switch (value) { + case 0: return POP; + case 1: return JAZZ; + case 2: return FOLK; + case 3: return ROCK; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + Genre> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Genre findValueByNumber(int number) { + return Genre.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalStateException( + "Can't get the descriptor of an unrecognized enum value."); + } + return getDescriptor().getValues().get(ordinal()); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return com.example.spanner.jdbc.SingerProto.getDescriptor().getEnumTypes().get(0); + } + + private static final Genre[] VALUES = values(); + + public static Genre valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private Genre(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:examples.spanner.music.Genre) + } + + public interface SingerInfoOrBuilder extends + // @@protoc_insertion_point(interface_extends:examples.spanner.music.SingerInfo) + com.google.protobuf.MessageOrBuilder { + + /** + * optional int64 singer_id = 1; + * @return Whether the singerId field is set. + */ + boolean hasSingerId(); + /** + * optional int64 singer_id = 1; + * @return The singerId. + */ + long getSingerId(); + + /** + * optional string birth_date = 2; + * @return Whether the birthDate field is set. + */ + boolean hasBirthDate(); + /** + * optional string birth_date = 2; + * @return The birthDate. + */ + java.lang.String getBirthDate(); + /** + * optional string birth_date = 2; + * @return The bytes for birthDate. + */ + com.google.protobuf.ByteString + getBirthDateBytes(); + + /** + * optional string nationality = 3; + * @return Whether the nationality field is set. + */ + boolean hasNationality(); + /** + * optional string nationality = 3; + * @return The nationality. + */ + java.lang.String getNationality(); + /** + * optional string nationality = 3; + * @return The bytes for nationality. + */ + com.google.protobuf.ByteString + getNationalityBytes(); + + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return Whether the genre field is set. + */ + boolean hasGenre(); + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The enum numeric value on the wire for genre. + */ + int getGenreValue(); + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The genre. + */ + com.example.spanner.jdbc.SingerProto.Genre getGenre(); + } + /** + * Protobuf type {@code examples.spanner.music.SingerInfo} + */ + public static final class SingerInfo extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:examples.spanner.music.SingerInfo) + SingerInfoOrBuilder { + private static final long serialVersionUID = 0L; + // Use SingerInfo.newBuilder() to construct. + private SingerInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private SingerInfo() { + birthDate_ = ""; + nationality_ = ""; + genre_ = 0; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new SingerInfo(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.example.spanner.jdbc.SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.example.spanner.jdbc.SingerProto.internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.example.spanner.jdbc.SingerProto.SingerInfo.class, com.example.spanner.jdbc.SingerProto.SingerInfo.Builder.class); + } + + private int bitField0_; + public static final int SINGER_ID_FIELD_NUMBER = 1; + private long singerId_ = 0L; + /** + * optional int64 singer_id = 1; + * @return Whether the singerId field is set. + */ + @java.lang.Override + public boolean hasSingerId() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int64 singer_id = 1; + * @return The singerId. + */ + @java.lang.Override + public long getSingerId() { + return singerId_; + } + + public static final int BIRTH_DATE_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object birthDate_ = ""; + /** + * optional string birth_date = 2; + * @return Whether the birthDate field is set. + */ + @java.lang.Override + public boolean hasBirthDate() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string birth_date = 2; + * @return The birthDate. + */ + @java.lang.Override + public java.lang.String getBirthDate() { + java.lang.Object ref = birthDate_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + birthDate_ = s; + return s; + } + } + /** + * optional string birth_date = 2; + * @return The bytes for birthDate. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getBirthDateBytes() { + java.lang.Object ref = birthDate_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + birthDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NATIONALITY_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object nationality_ = ""; + /** + * optional string nationality = 3; + * @return Whether the nationality field is set. + */ + @java.lang.Override + public boolean hasNationality() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional string nationality = 3; + * @return The nationality. + */ + @java.lang.Override + public java.lang.String getNationality() { + java.lang.Object ref = nationality_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + nationality_ = s; + return s; + } + } + /** + * optional string nationality = 3; + * @return The bytes for nationality. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNationalityBytes() { + java.lang.Object ref = nationality_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + nationality_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int GENRE_FIELD_NUMBER = 4; + private int genre_ = 0; + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return Whether the genre field is set. + */ + @java.lang.Override public boolean hasGenre() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The enum numeric value on the wire for genre. + */ + @java.lang.Override public int getGenreValue() { + return genre_; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The genre. + */ + @java.lang.Override public com.example.spanner.jdbc.SingerProto.Genre getGenre() { + com.example.spanner.jdbc.SingerProto.Genre result = com.example.spanner.jdbc.SingerProto.Genre.forNumber(genre_); + return result == null ? com.example.spanner.jdbc.SingerProto.Genre.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) != 0)) { + output.writeInt64(1, singerId_); + } + if (((bitField0_ & 0x00000002) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, birthDate_); + } + if (((bitField0_ & 0x00000004) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, nationality_); + } + if (((bitField0_ & 0x00000008) != 0)) { + output.writeEnum(4, genre_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, singerId_); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, birthDate_); + } + if (((bitField0_ & 0x00000004) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, nationality_); + } + if (((bitField0_ & 0x00000008) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(4, genre_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.example.spanner.jdbc.SingerProto.SingerInfo)) { + return super.equals(obj); + } + com.example.spanner.jdbc.SingerProto.SingerInfo other = (com.example.spanner.jdbc.SingerProto.SingerInfo) obj; + + if (hasSingerId() != other.hasSingerId()) return false; + if (hasSingerId()) { + if (getSingerId() + != other.getSingerId()) return false; + } + if (hasBirthDate() != other.hasBirthDate()) return false; + if (hasBirthDate()) { + if (!getBirthDate() + .equals(other.getBirthDate())) return false; + } + if (hasNationality() != other.hasNationality()) return false; + if (hasNationality()) { + if (!getNationality() + .equals(other.getNationality())) return false; + } + if (hasGenre() != other.hasGenre()) return false; + if (hasGenre()) { + if (genre_ != other.genre_) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasSingerId()) { + hash = (37 * hash) + SINGER_ID_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getSingerId()); + } + if (hasBirthDate()) { + hash = (37 * hash) + BIRTH_DATE_FIELD_NUMBER; + hash = (53 * hash) + getBirthDate().hashCode(); + } + if (hasNationality()) { + hash = (37 * hash) + NATIONALITY_FIELD_NUMBER; + hash = (53 * hash) + getNationality().hashCode(); + } + if (hasGenre()) { + hash = (37 * hash) + GENRE_FIELD_NUMBER; + hash = (53 * hash) + genre_; + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static com.example.spanner.jdbc.SingerProto.SingerInfo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(com.example.spanner.jdbc.SingerProto.SingerInfo prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code examples.spanner.music.SingerInfo} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:examples.spanner.music.SingerInfo) + com.example.spanner.jdbc.SingerProto.SingerInfoOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return com.example.spanner.jdbc.SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.example.spanner.jdbc.SingerProto.internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.example.spanner.jdbc.SingerProto.SingerInfo.class, com.example.spanner.jdbc.SingerProto.SingerInfo.Builder.class); + } + + // Construct using com.example.spanner.jdbc.SingerProto.SingerInfo.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + singerId_ = 0L; + birthDate_ = ""; + nationality_ = ""; + genre_ = 0; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return com.example.spanner.jdbc.SingerProto.internal_static_examples_spanner_music_SingerInfo_descriptor; + } + + @java.lang.Override + public com.example.spanner.jdbc.SingerProto.SingerInfo getDefaultInstanceForType() { + return com.example.spanner.jdbc.SingerProto.SingerInfo.getDefaultInstance(); + } + + @java.lang.Override + public com.example.spanner.jdbc.SingerProto.SingerInfo build() { + com.example.spanner.jdbc.SingerProto.SingerInfo result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.example.spanner.jdbc.SingerProto.SingerInfo buildPartial() { + com.example.spanner.jdbc.SingerProto.SingerInfo result = new com.example.spanner.jdbc.SingerProto.SingerInfo(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(com.example.spanner.jdbc.SingerProto.SingerInfo result) { + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.singerId_ = singerId_; + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.birthDate_ = birthDate_; + to_bitField0_ |= 0x00000002; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.nationality_ = nationality_; + to_bitField0_ |= 0x00000004; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.genre_ = genre_; + to_bitField0_ |= 0x00000008; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.example.spanner.jdbc.SingerProto.SingerInfo) { + return mergeFrom((com.example.spanner.jdbc.SingerProto.SingerInfo)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.example.spanner.jdbc.SingerProto.SingerInfo other) { + if (other == com.example.spanner.jdbc.SingerProto.SingerInfo.getDefaultInstance()) return this; + if (other.hasSingerId()) { + setSingerId(other.getSingerId()); + } + if (other.hasBirthDate()) { + birthDate_ = other.birthDate_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (other.hasNationality()) { + nationality_ = other.nationality_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (other.hasGenre()) { + setGenre(other.getGenre()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + singerId_ = input.readInt64(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 18: { + birthDate_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + nationality_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 32: { + genre_ = input.readEnum(); + bitField0_ |= 0x00000008; + break; + } // case 32 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private long singerId_ ; + /** + * optional int64 singer_id = 1; + * @return Whether the singerId field is set. + */ + @java.lang.Override + public boolean hasSingerId() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + * optional int64 singer_id = 1; + * @return The singerId. + */ + @java.lang.Override + public long getSingerId() { + return singerId_; + } + /** + * optional int64 singer_id = 1; + * @param value The singerId to set. + * @return This builder for chaining. + */ + public Builder setSingerId(long value) { + + singerId_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * optional int64 singer_id = 1; + * @return This builder for chaining. + */ + public Builder clearSingerId() { + bitField0_ = (bitField0_ & ~0x00000001); + singerId_ = 0L; + onChanged(); + return this; + } + + private java.lang.Object birthDate_ = ""; + /** + * optional string birth_date = 2; + * @return Whether the birthDate field is set. + */ + public boolean hasBirthDate() { + return ((bitField0_ & 0x00000002) != 0); + } + /** + * optional string birth_date = 2; + * @return The birthDate. + */ + public java.lang.String getBirthDate() { + java.lang.Object ref = birthDate_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + birthDate_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string birth_date = 2; + * @return The bytes for birthDate. + */ + public com.google.protobuf.ByteString + getBirthDateBytes() { + java.lang.Object ref = birthDate_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + birthDate_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string birth_date = 2; + * @param value The birthDate to set. + * @return This builder for chaining. + */ + public Builder setBirthDate( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + birthDate_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * optional string birth_date = 2; + * @return This builder for chaining. + */ + public Builder clearBirthDate() { + birthDate_ = getDefaultInstance().getBirthDate(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * optional string birth_date = 2; + * @param value The bytes for birthDate to set. + * @return This builder for chaining. + */ + public Builder setBirthDateBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + birthDate_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object nationality_ = ""; + /** + * optional string nationality = 3; + * @return Whether the nationality field is set. + */ + public boolean hasNationality() { + return ((bitField0_ & 0x00000004) != 0); + } + /** + * optional string nationality = 3; + * @return The nationality. + */ + public java.lang.String getNationality() { + java.lang.Object ref = nationality_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + nationality_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string nationality = 3; + * @return The bytes for nationality. + */ + public com.google.protobuf.ByteString + getNationalityBytes() { + java.lang.Object ref = nationality_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + nationality_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string nationality = 3; + * @param value The nationality to set. + * @return This builder for chaining. + */ + public Builder setNationality( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + nationality_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * optional string nationality = 3; + * @return This builder for chaining. + */ + public Builder clearNationality() { + nationality_ = getDefaultInstance().getNationality(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * optional string nationality = 3; + * @param value The bytes for nationality to set. + * @return This builder for chaining. + */ + public Builder setNationalityBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + nationality_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private int genre_ = 0; + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return Whether the genre field is set. + */ + @java.lang.Override public boolean hasGenre() { + return ((bitField0_ & 0x00000008) != 0); + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The enum numeric value on the wire for genre. + */ + @java.lang.Override public int getGenreValue() { + return genre_; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @param value The enum numeric value on the wire for genre to set. + * @return This builder for chaining. + */ + public Builder setGenreValue(int value) { + genre_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return The genre. + */ + @java.lang.Override + public com.example.spanner.jdbc.SingerProto.Genre getGenre() { + com.example.spanner.jdbc.SingerProto.Genre result = com.example.spanner.jdbc.SingerProto.Genre.forNumber(genre_); + return result == null ? com.example.spanner.jdbc.SingerProto.Genre.UNRECOGNIZED : result; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @param value The genre to set. + * @return This builder for chaining. + */ + public Builder setGenre(com.example.spanner.jdbc.SingerProto.Genre value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + genre_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .examples.spanner.music.Genre genre = 4; + * @return This builder for chaining. + */ + public Builder clearGenre() { + bitField0_ = (bitField0_ & ~0x00000008); + genre_ = 0; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:examples.spanner.music.SingerInfo) + } + + // @@protoc_insertion_point(class_scope:examples.spanner.music.SingerInfo) + private static final com.example.spanner.jdbc.SingerProto.SingerInfo DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.example.spanner.jdbc.SingerProto.SingerInfo(); + } + + public static com.example.spanner.jdbc.SingerProto.SingerInfo getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SingerInfo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.example.spanner.jdbc.SingerProto.SingerInfo getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_examples_spanner_music_SingerInfo_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\014singer.proto\022\026examples.spanner.music\"\301" + + "\001\n\nSingerInfo\022\026\n\tsinger_id\030\001 \001(\003H\000\210\001\001\022\027\n" + + "\nbirth_date\030\002 \001(\tH\001\210\001\001\022\030\n\013nationality\030\003 " + + "\001(\tH\002\210\001\001\0221\n\005genre\030\004 \001(\0162\035.examples.spann" + + "er.music.GenreH\003\210\001\001B\014\n\n_singer_idB\r\n\013_bi" + + "rth_dateB\016\n\014_nationalityB\010\n\006_genre*.\n\005Ge" + + "nre\022\007\n\003POP\020\000\022\010\n\004JAZZ\020\001\022\010\n\004FOLK\020\002\022\010\n\004ROCK" + + "\020\003B)\n\030com.example.spanner.jdbcB\013SingerPr" + + "otoP\000b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_examples_spanner_music_SingerInfo_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_examples_spanner_music_SingerInfo_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_examples_spanner_music_SingerInfo_descriptor, + new java.lang.String[] { "SingerId", "BirthDate", "Nationality", "Genre", "SingerId", "BirthDate", "Nationality", "Genre", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/README.md b/java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/README.md new file mode 100644 index 000000000000..4b689229b239 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/README.md @@ -0,0 +1,7 @@ +#### To generate SingerProto.java and descriptors.pb file from singer.proto using `protoc` +```shell +cd samples/snippets/src/main/resources/ +protoc --proto_path=com/example/spanner/jdbc/ \ + --include_imports --descriptor_set_out=com/example/spanner/jdbc/descriptors.pb \ + --java_out=../java com/example/spanner/jdbc/singer.proto +``` diff --git a/java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/descriptors.pb b/java-spanner-jdbc/samples/snippets/src/main/resources/com/example/spanner/jdbc/descriptors.pb new file mode 100644 index 0000000000000000000000000000000000000000..2dfd90bae7563a142aa8f8b596fe9e5918057ba9 GIT binary patch literal 377 zcmZvY%}T>S6h<>iTa%ku!Ym{kp%eslk%eyDI*O)NNEmnB4EY)BNHYmZ1bqXawGYs> znF-b|++7am-uv;v&IGR&a?P8tZmO=rC;T%l>kV(iwoaw&dHKS%V~BjucdE7ML?GTn&oE3mX= z(nF}U8yK&-Y arrayOfStructAsQueryParameter(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); assertEquals("value1;1;\nvalue2;2;\n", result); + + result = runSample( + () -> protoColumns(PROJECT_ID, INSTANCE_ID, DATABASE_ID, properties)); + assertEquals("Inserted 2 singers\n" + + "2:\n" + + "singer_id: 2\n" + + "birth_date: \"2001-12-03\"\n" + + "nationality: \"FO\"\n" + + "genre: POP\n" + + "\n" + + "POP\n" + + "1:\n" + + "singer_id: 1\n" + + "birth_date: \"1998-07-04\"\n" + + "nationality: \"ES\"\n" + + "genre: ROCK\n" + + "\n" + + "ROCK\n", result); } @Test From 0dee521ae3f32806ecbf9a5b34cdf76480e09133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 17 Feb 2025 14:06:46 +0100 Subject: [PATCH 1561/1979] feat: support FOR UPDATE clauses (#1919) Spanner now supports FOR UPDATE clauses. This is now also reflected in the DatabaseMetaData returned by the JDBC driver. See also https://cloud.google.com/spanner/docs/release-notes#January_27_2025 --- .../com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 2 +- .../com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 6cb6f3e0881b..bdebcad89a82 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -479,7 +479,7 @@ public boolean supportsPositionedUpdate() { @Override public boolean supportsSelectForUpdate() { - return false; + return true; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 193fc9605729..47ab2e549321 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -250,7 +250,7 @@ public void testTrivialMethods() throws SQLException { assertTrue(meta.supportsSchemasInPrivilegeDefinitions()); assertTrue(meta.supportsSchemasInProcedureCalls()); assertTrue(meta.supportsSchemasInTableDefinitions()); - assertFalse(meta.supportsSelectForUpdate()); + assertTrue(meta.supportsSelectForUpdate()); assertFalse(meta.supportsStatementPooling()); assertFalse(meta.supportsStoredFunctionsUsingCallSyntax()); assertFalse(meta.supportsStoredProcedures()); From 246079402331bf290ff397f26e330114145c1656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 17 Feb 2025 14:06:58 +0100 Subject: [PATCH 1562/1979] docs: regenerate Connection properties documentation (#1915) --- .../documentation/connection_properties.md | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index 8e157ffd8706..52938f4eff0b 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -6,30 +6,32 @@ The 'Context' value indicates whether the property can only be set when a connec | Name | Description | Default | Enum values | Context | |------|-------------|---------|-------------|---------| -| auto_batch_dml | Automatically buffer DML statements that are executed on this connection and execute them as one batch when a non-DML statement is executed, or when the current transaction is committed. The update count that is returned for DML statements that are buffered is by default 1. This default can be changed by setting the connection variable auto_batch_dml_update_count to value other than 1. This setting is only in read/write transactions. DML statements in auto-commit mode are executed directly. | false | | USER | +| auto_batch_dml | Automatically buffer DML statements that are executed on this connection and execute them as one batch when a non-DML statement is executed, or when the current transaction is committed. The update count that is returned for DML statements that are buffered is by default 1. This default can be changed by setting the connection variable auto_batch_dml_update_count to value other than 1. This setting is only in read/write transactions. DML statements in auto-commit mode are executed directly. | false | true, false | USER | | auto_batch_dml_update_count | DML statements that are executed when auto_batch_dml is set to true, are not directly sent to Spanner, but are buffered in the client until the batch is flushed. This property determines the update count that is returned for these DML statements. The default is 1, as that is the update count that is expected by most ORMs (e.g. Hibernate). | 1 | | USER | -| auto_batch_dml_update_count_verification | The update count that is returned for DML statements that are buffered during an automatic DML batch is by default 1. This value can be changed by setting the connection variable auto_batch_dml_update_count. The update counts that are returned by Spanner when the DML statements are actually executed are verified against the update counts that were returned when they were buffered. If these do not match, a com.google.cloud.spanner.DmlBatchUpdateCountVerificationFailedException will be thrown. You can disable this verification by setting auto_batch_dml_update_count_verification to false. | true | | USER | -| autocommit | Should the connection start in autocommit (true/false) | true | | USER | -| autocommit_dml_mode | Should the connection automatically retry Aborted errors (true/false) | TRANSACTIONAL | | USER | -| autoconfigemulator | Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect. | false | | STARTUP | -| autopartitionmode | Execute all queries on this connection as partitioned queries. Executing a query that cannot be partitioned will fail. Executing a query in a read/write transaction will also fail. | false | | USER | +| auto_batch_dml_update_count_verification | The update count that is returned for DML statements that are buffered during an automatic DML batch is by default 1. This value can be changed by setting the connection variable auto_batch_dml_update_count. The update counts that are returned by Spanner when the DML statements are actually executed are verified against the update counts that were returned when they were buffered. If these do not match, a com.google.cloud.spanner.DmlBatchUpdateCountVerificationFailedException will be thrown. You can disable this verification by setting auto_batch_dml_update_count_verification to false. | true | true, false | USER | +| autocommit | Should the connection start in autocommit (true/false) | true | true, false | USER | +| autocommit_dml_mode | Determines the transaction type that is used to execute DML statements when the connection is in auto-commit mode. | TRANSACTIONAL | TRANSACTIONAL, PARTITIONED_NON_ATOMIC, TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC | USER | +| autoconfigemulator | Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect. | false | true, false | STARTUP | +| autopartitionmode | Execute all queries on this connection as partitioned queries. Executing a query that cannot be partitioned will fail. Executing a query in a read/write transaction will also fail. | false | true, false | USER | | channelprovider | The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider. | | | STARTUP | -| connection_state_type | The type of connection state to use for this connection. Can only be set at start up. If no value is set, then the database dialect default will be used, which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL. | | | STARTUP | +| clientcertificate | Specifies the file path to the client certificate required for establishing an mTLS connection. | | | STARTUP | +| clientkey | Specifies the file path to the client private key required for establishing an mTLS connection. | | | STARTUP | +| connection_state_type | The type of connection state to use for this connection. Can only be set at start up. If no value is set, then the database dialect default will be used, which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL. | | TRANSACTIONAL, NON_TRANSACTIONAL | STARTUP | | credentials | The location of the credentials file to use for this connection. If neither this property or encoded credentials are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | | credentialsprovider | The class name of the com.google.api.gax.core.CredentialsProvider implementation that should be used to obtain credentials for connections. | | | STARTUP | | databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | -| databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | | USER | -| ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | | USER | -| delaytransactionstartuntilfirstwrite | Enabling this option will delay the actual start of a read/write transaction until the first write operation is seen in that transaction. All reads that happen before the first write in a transaction will instead be executed as if the connection was in auto-commit mode. Enabling this option will make read/write transactions lose their SERIALIZABLE isolation level. Read operations that are executed after the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking and improve performance for applications that can handle the lower transaction isolation semantics. | false | | USER | -| dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | | STARTUP | +| databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | true, false | USER | +| ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | FAIL, ALLOW_IN_EMPTY_TRANSACTION, AUTO_COMMIT_TRANSACTION | USER | +| delaytransactionstartuntilfirstwrite | Enabling this option will delay the actual start of a read/write transaction until the first write operation is seen in that transaction. All reads that happen before the first write in a transaction will instead be executed as if the connection was in auto-commit mode. Enabling this option will make read/write transactions lose their SERIALIZABLE isolation level. Read operations that are executed after the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking and improve performance for applications that can handle the lower transaction isolation semantics. | false | true, false | USER | +| dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | GOOGLE_STANDARD_SQL, POSTGRESQL | STARTUP | | directed_read | The directed read options to apply to read-only transactions. | | | USER | -| enableapitracing | Add OpenTelemetry traces for each individual RPC call. Enable this to get a detailed view of each RPC that is being executed by your application, or if you want to debug potential latency problems caused by RPCs that are being retried. | | | STARTUP | -| enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | | STARTUP | -| enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | | STARTUP | +| enableapitracing | Add OpenTelemetry traces for each individual RPC call. Enable this to get a detailed view of each RPC that is being executed by your application, or if you want to debug potential latency problems caused by RPCs that are being retried. | | true, false | STARTUP | +| enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | true, false | STARTUP | +| enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | true, false | STARTUP | | encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | | endpoint | The endpoint that the JDBC driver should connect to. The default is the default Spanner production endpoint when autoConfigEmulator=false, and the default Spanner emulator endpoint (localhost:9010) when autoConfigEmulator=true. This property takes precedence over any host name at the start of the connection URL. | | | STARTUP | -| keeptransactionalive | Enabling this option will trigger the connection to keep read/write transactions alive by executing a SELECT 1 query once every 10 seconds if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time. | false | | USER | -| lenient | Silently ignore unknown properties in the connection string/properties (true/false) | false | | STARTUP | +| keeptransactionalive | Enabling this option will trigger the connection to keep read/write transactions alive by executing a SELECT 1 query once every 10 seconds if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time. | false | true, false | USER | +| lenient | Silently ignore unknown properties in the connection string/properties (true/false) | false | true, false | STARTUP | | maxcommitdelay | The max delay that Spanner may apply to commit requests to improve throughput. | | | USER | | maxpartitionedparallelism | The max partitions hint value to use for partitioned queries. Use 0 if you do not want to specify a hint. | 1 | | USER | | maxpartitions | The max partitions hint value to use for partitioned queries. Use 0 if you do not want to specify a hint. | 0 | | USER | @@ -40,17 +42,17 @@ The 'Context' value indicates whether the property can only be set when a connec | optimizerstatisticspackage | Sets the query optimizer statistics package to use for this connection. | | | USER | | optimizerversion | Sets the default query optimizer version to use for this connection. | | | USER | | read_only_staleness | The read-only staleness to use for read-only transactions and single-use queries. | strong | | USER | -| readonly | Should the connection start in read-only mode (true/false) | false | | USER | -| retryabortsinternally | Should the connection automatically retry Aborted errors (true/false) | true | | USER | -| returncommitstats | Request that Spanner returns commit statistics for read/write transactions (true/false) | false | | USER | -| routetoleader | Should read/write transactions and partitioned DML be routed to leader region (true/false) | true | | STARTUP | -| rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | | USER | -| savepoint_support | Determines the behavior of the connection when savepoints are used. | FAIL_AFTER_ROLLBACK | | USER | +| readonly | Should the connection start in read-only mode (true/false) | false | true, false | USER | +| retryabortsinternally | Should the connection automatically retry Aborted errors (true/false) | true | true, false | USER | +| returncommitstats | Request that Spanner returns commit statistics for read/write transactions (true/false) | false | true, false | USER | +| routetoleader | Should read/write transactions and partitioned DML be routed to leader region (true/false) | true | true, false | STARTUP | +| rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | LOW, MEDIUM, HIGH, UNSPECIFIED | USER | +| savepoint_support | Determines the behavior of the connection when savepoints are used. | FAIL_AFTER_ROLLBACK | ENABLED, FAIL_AFTER_ROLLBACK, DISABLED | USER | | tracing_prefix | The prefix that will be prepended to all OpenTelemetry traces that are generated by a Connection. | CloudSpanner | | STARTUP | -| trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | | STARTUP | -| tracksessionleaks | Capture the call stack of the thread that checked out a session of the session pool. This will pre-create a LeakedSessionException already when a session is checked out. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedSessionException will only be created when an actual session leak is detected. The stack trace of the exception will in that case not contain the call stack of when the session was checked out. | true | | STARTUP | -| useautosavepointsforemulator | Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. This is no longer needed when using Emulator version 1.5.23 or higher. | false | | STARTUP | -| useplaintext | Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator. | false | | STARTUP | +| trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | true, false | STARTUP | +| tracksessionleaks | Capture the call stack of the thread that checked out a session of the session pool. This will pre-create a LeakedSessionException already when a session is checked out. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedSessionException will only be created when an actual session leak is detected. The stack trace of the exception will in that case not contain the call stack of when the session was checked out. | true | true, false | STARTUP | +| useautosavepointsforemulator | Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. This is no longer needed when using Emulator version 1.5.23 or higher. | false | true, false | STARTUP | +| useplaintext | Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator. | false | true, false | STARTUP | | useragent | The custom user-agent property name to use when communicating with Cloud Spanner. This property is intended for internal library usage, and should not be set by applications. | | | STARTUP | -| usevirtualgrpctransportthreads | Use a virtual thread instead of a platform thread for the gRPC executor (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | | STARTUP | -| usevirtualthreads | Use a virtual thread instead of a platform thread for each connection (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | | STARTUP | +| usevirtualgrpctransportthreads | Use a virtual thread instead of a platform thread for the gRPC executor (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | true, false | STARTUP | +| usevirtualthreads | Use a virtual thread instead of a platform thread for each connection (true/false). This option only has any effect if the application is running on Java 21 or higher. In all other cases, the option is ignored. | false | true, false | STARTUP | From 318e561ff08d2d15402b210efd603c911b13d7ab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 17 Feb 2025 14:07:54 +0100 Subject: [PATCH 1563/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.43.0 (#1908) * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.43.0 * initialize Dialect$2 as part of strict-image-heap enforcement * Revert "initialize Dialect$2 as part of strict-image-heap enforcement" This reverts commit 7cb4d3a2c5fca89737744c7b48b05d74eed8edc8. * Reapply "initialize Dialect$2 as part of strict-image-heap enforcement" This reverts commit 292f05921acfebb8a834dcb1c457be5c0915f9c4. * initialize Dialect$1 at build time * initialize immutable map entry at build time * initialize subclass of immutable map entry * initialize database dialect $1 * add test class initialization * add test class initialization ii * move parameterized initialization to production config * move junit config to test config * Revert "move junit config to test config" This reverts commit d78fe2f5ff06c0675054deaf95fb9b709fae796f. * include runwith in initialized junit classes * add junit method order to image heap * add junit's category to image heap * remove java.lang.annotation from image heap * initialize parameterized junit class at build time * initialize framework in image-heap * initialize it test parameter at build time explicitly * explicitly initialize singleton immutablebimap --------- Co-authored-by: diegomarquezp --- .../workflows/unmanaged_dependency_check.yaml | 2 +- .../.kokoro/presubmit/graalvm-native-17.cfg | 2 +- .../.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- .../native-image.properties | 15 ++++++++++++++- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 6d507150e8ff..a48787484f17 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.42.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.43.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index b78c82df571b..8d3f11dc47e1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.42.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.43.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index f08c4be3e00b..f78bafd26ecb 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.42.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.43.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 14e79cf8750e..e7223d3d0691 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.42.0 + 3.43.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f0670c6e6a10..e9dbe6c065c6 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.42.0 + 3.43.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 56b88c472e5a..893338266af3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.42.0 + 3.43.0 diff --git a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties index b5754aca41dc..f9e42bad8bff 100644 --- a/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties +++ b/java-spanner-jdbc/src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties @@ -1,6 +1,19 @@ Args = --initialize-at-build-time==com.google.cloud.spanner.IntegrationTestEnv,\ com.google.cloud.spanner.jdbc.it.JdbcIntegrationTestEnv,\ + com.google.cloud.spanner.jdbc.it.DialectTestParameter,\ com.google.common.collect.RegularImmutableMap,\ + com.google.common.collect.ImmutableMapEntry,\ + com.google.common.collect.ImmutableMapEntry$NonTerminalImmutableMapEntry,\ + com.google.common.collect.SingletonImmutableBiMap,\ com.google.cloud.spanner.Dialect,\ + com.google.cloud.spanner.Dialect$2,\ + com.google.cloud.spanner.Dialect$1,\ com.google.spanner.admin.database.v1.DatabaseDialect,\ - org.junit.runners.MethodSorters \ No newline at end of file + com.google.spanner.admin.database.v1.DatabaseDialect$1,\ + org.junit.runners.MethodSorters,\ + org.junit.runners.Parameterized,\ + org.junit.runner.RunWith,\ + org.junit.FixMethodOrder,\ + org.junit.experimental.categories.Category,\ + org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters,\ + org.junit.runners.model.FrameworkField,\ \ No newline at end of file From 2912b068c83a2e44771bd8c0b6e6b38c4e071c6c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Feb 2025 18:04:27 +0100 Subject: [PATCH 1564/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.20.5 (#1921) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.testcontainers:testcontainers-bom](https://java.testcontainers.org) ([source](https://redirect.github.com/testcontainers/testcontainers-java)) | `1.20.4` -> `1.20.5` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.testcontainers:testcontainers-bom/1.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.testcontainers:testcontainers-bom/1.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.testcontainers:testcontainers-bom/1.20.4/1.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.testcontainers:testcontainers-bom/1.20.4/1.20.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    testcontainers/testcontainers-java (org.testcontainers:testcontainers-bom) ### [`v1.20.5`](https://redirect.github.com/testcontainers/testcontainers-java/releases/tag/1.20.5) [Compare Source](https://redirect.github.com/testcontainers/testcontainers-java/compare/1.20.4...1.20.5) ### What's Changed - Add `ServiceBusEmulatorContainer` to Azure module ([#​9795](https://redirect.github.com/testcontainers/testcontainers-java/issues/9795)) [@​nagyesta](https://redirect.github.com/nagyesta) - Add `EventHubsEmulatorContainer` to Azure module ([#​9665](https://redirect.github.com/testcontainers/testcontainers-java/issues/9665)) [@​nagyesta](https://redirect.github.com/nagyesta) - Add `AzuriteContainer` to Azure module ([#​9661](https://redirect.github.com/testcontainers/testcontainers-java/issues/9661)) [@​nagyesta](https://redirect.github.com/nagyesta) - Add `ldap` module ([#​9987](https://redirect.github.com/testcontainers/testcontainers-java/issues/9987)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Add `scylladb` module ([#​8002](https://redirect.github.com/testcontainers/testcontainers-java/issues/8002)) [@​mkorolyov](https://redirect.github.com/mkorolyov) - Add `pinecone` module ([#​9911](https://redirect.github.com/testcontainers/testcontainers-java/issues/9911)) [@​eddumelendez](https://redirect.github.com/eddumelendez) #### 🚀 Features & Enhancements - Set `RABBITMQ_DEFAULT_USER` env var with `withAdminUser` ([#​9571](https://redirect.github.com/testcontainers/testcontainers-java/issues/9571)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Move ollama port to a constant and provide new `getPort` method ([#​9623](https://redirect.github.com/testcontainers/testcontainers-java/issues/9623)) [@​edeandrea](https://redirect.github.com/edeandrea) - #### 🐛 Bug Fixes - Fix reuse support for `CouchbaseContainer` ([#​9957](https://redirect.github.com/testcontainers/testcontainers-java/issues/9957)) [@​albihnf](https://redirect.github.com/albihnf) - Fix `SolrContainer` start parameters for version >= 9.7.0 ([#​9926](https://redirect.github.com/testcontainers/testcontainers-java/issues/9926)) [@​mkr](https://redirect.github.com/mkr) - Fix clickhouse authentication ([#​9942](https://redirect.github.com/testcontainers/testcontainers-java/issues/9942)) [@​livk-cloud](https://redirect.github.com/livk-cloud) - Fix cluster creation with `ConfluentKafkaContainer` and `KafkaContainer` ([#​9910](https://redirect.github.com/testcontainers/testcontainers-java/issues/9910)) [@​eddumelendez](https://redirect.github.com/eddumelendez) #### 📖 Documentation - Fix typos ([#​9783](https://redirect.github.com/testcontainers/testcontainers-java/issues/9783)) [@​NathanBaulch](https://redirect.github.com/NathanBaulch) - Added Dash0 as Adoptor ([#​9630](https://redirect.github.com/testcontainers/testcontainers-java/issues/9630)) [@​CodingFabian](https://redirect.github.com/CodingFabian) - Improve Docker Compose docs ([#​9461](https://redirect.github.com/testcontainers/testcontainers-java/issues/9461)) [@​etrandafir93](https://redirect.github.com/etrandafir93) #### 🧹 Housekeeping - Use docker/setup-docker-action ([#​9625](https://redirect.github.com/testcontainers/testcontainers-java/issues/9625)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Declare Java action in windows workflow ([#​9604](https://redirect.github.com/testcontainers/testcontainers-java/issues/9604)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Test against multiple Java versions ([#​8988](https://redirect.github.com/testcontainers/testcontainers-java/issues/8988)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Don't extend configuration compileOnly and testCompile from shaded ([#​9579](https://redirect.github.com/testcontainers/testcontainers-java/issues/9579)) [@​patrick-dedication](https://redirect.github.com/patrick-dedication) - Remove specific Java version for testing in gradle files ([#​9626](https://redirect.github.com/testcontainers/testcontainers-java/issues/9626)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Drop references to `vectorized/redpanda` image ([#​9624](https://redirect.github.com/testcontainers/testcontainers-java/issues/9624)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Polish AbstractPulsar test ([#​9600](https://redirect.github.com/testcontainers/testcontainers-java/issues/9600)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Polish BigtableEmulatorContainer test ([#​9599](https://redirect.github.com/testcontainers/testcontainers-java/issues/9599)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Fix typo in SolrContainer ([#​9572](https://redirect.github.com/testcontainers/testcontainers-java/issues/9572)) [@​dajudge](https://redirect.github.com/dajudge) #### 📦 Dependency updates - Update docker-java version to 3.4.1 ([#​9627](https://redirect.github.com/testcontainers/testcontainers-java/issues/9627)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Adjust shadow gradle plugin coordinates ([#​9577](https://redirect.github.com/testcontainers/testcontainers-java/issues/9577)) [@​patrick-dedication](https://redirect.github.com/patrick-dedication)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 8d5884824e30..ecbbef770da6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.4 + 1.20.5 import pom From bd3337a65f929d85b0d44946e83345f7ba3bbc43 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Feb 2025 21:01:48 +0100 Subject: [PATCH 1565/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.3 (#1922) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index e9dbe6c065c6..74194c9fb586 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.2 + 3.4.3 test From 61a38e0df05955e1f3d01bc0838132e87b6bc63a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Feb 2025 21:02:17 +0100 Subject: [PATCH 1566/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.3 (#1923) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index c0abdd51d583..62412d204f0d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.2 + 3.4.3 From 4bc75a59fbfe2e5032259f0de4a62ac8e2ce74be Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 20 Feb 2025 21:16:25 +0100 Subject: [PATCH 1567/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.3 (#1924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/spring-projects/spring-boot)) | `3.4.2` -> `3.4.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-parent/3.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-parent/3.4.2/3.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-parent/3.4.2/3.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.4.3`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.4.2...v3.4.3)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index ecbbef770da6..1e6f6ac62e06 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.2 + 3.4.3 From bc04050357a73cb41e3a5f0bb123ede6c1b6c4a1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Feb 2025 11:47:21 +0100 Subject: [PATCH 1568/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.5 (#1926) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e7223d3d0691..cdb71c13ae60 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.4 + 1.20.5 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 74194c9fb586..31a5cb50c88e 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.4 + 1.20.5 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 893338266af3..6e5560f6e85b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.4 + 1.20.5 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 62412d204f0d..bbfd8d068252 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.20.4 + 1.20.5 test From 21e2ae3560289bc070267e3b3a70952e06649e55 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Feb 2025 11:54:45 +0100 Subject: [PATCH 1569/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.87.0 (#1925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-bom](https://redirect.github.com/googleapis/java-spanner) | `6.86.0` -> `6.87.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.87.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.87.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.86.0/6.87.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.86.0/6.87.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.87.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#6870-2025-02-20) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.86.0...v6.87.0) ##### Features - Add AddSplitPoints API ([a5ebcd3](https://redirect.github.com/googleapis/java-spanner/commit/a5ebcd343a67c57d61362cfb0ccb4888f5503681)) - Add option for multiplexed sessions with partitioned operations ([#​3635](https://redirect.github.com/googleapis/java-spanner/issues/3635)) ([dc89b4d](https://redirect.github.com/googleapis/java-spanner/commit/dc89b4d7663f0e40a9169b21243f2d94f2fc5749)) - Add option to indicate that a statement is the last in a transaction ([#​3647](https://redirect.github.com/googleapis/java-spanner/issues/3647)) ([b04ea80](https://redirect.github.com/googleapis/java-spanner/commit/b04ea804cfa9551b4d7c49cd83f0ef1120942423)) - Adding gfe_latencies metric to built-in metrics ([#​3490](https://redirect.github.com/googleapis/java-spanner/issues/3490)) ([314dadc](https://redirect.github.com/googleapis/java-spanner/commit/314dadc31f4a5aa798d45886db7231c1bd8b7a91)) - **spanner:** Support multiplexed session for read-write transactions ([#​3608](https://redirect.github.com/googleapis/java-spanner/issues/3608)) ([bda78ed](https://redirect.github.com/googleapis/java-spanner/commit/bda78edaba827acf974c87c335868a6f8caa38f2)) ##### Bug Fixes - **deps:** Update the Java code generator (gapic-generator-java) to 2.53.0 ([20a3d0d](https://redirect.github.com/googleapis/java-spanner/commit/20a3d0da41509ffca66c77de6771fc8080930613)) - **spanner:** End spans for read-write methods ([#​3629](https://redirect.github.com/googleapis/java-spanner/issues/3629)) ([4a1f99c](https://redirect.github.com/googleapis/java-spanner/commit/4a1f99c6bb872ffc08e60d3843e4cdfc4efa2690)) - **spanner:** Release resources in TransactionManager ([#​3638](https://redirect.github.com/googleapis/java-spanner/issues/3638)) ([e0a3e5b](https://redirect.github.com/googleapis/java-spanner/commit/e0a3e5bd169e28e349a2dc92f86a2a9b5510f8f6)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.43.0 ([#​3642](https://redirect.github.com/googleapis/java-spanner/issues/3642)) ([c12968a](https://redirect.github.com/googleapis/java-spanner/commit/c12968a5f6dad95017d9867d96d4f19a26643a07))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 8 +++++++- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cdb71c13ae60..23b5ca664408 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.86.0 + 6.87.0 pom import @@ -207,6 +207,12 @@ 0.33.0 test
    + + io.opentelemetry + opentelemetry-api-incubator + 1.45.0-alpha + test + com.google.cloud google-cloud-trace diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index bbfd8d068252..a9a18f70e4c5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.86.0 + 6.87.0 import pom From 77d5551c4aa68ec0d6553759fc7f5f812e212b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 21 Feb 2025 13:17:35 +0100 Subject: [PATCH 1570/1979] perf: use last_statement optimization in autocommit (#1911) * perf: use last_statement optimization in autocommit Statements that are executed in autocommit mode should use the last_statement optimization. * test: add more tests --- .../spanner/jdbc/ExecuteMockServerTest.java | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index d7d72f76f2ef..0da18144426a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -38,6 +38,7 @@ 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.ResultSetMetadata; import com.google.spanner.v1.ResultSetStats; import com.google.spanner.v1.StructType; @@ -66,6 +67,8 @@ */ @RunWith(Parameterized.class) public class ExecuteMockServerTest extends AbstractMockServerTest { + private static final IllegalStateException REQUEST_NOT_FOUND = + new IllegalStateException("request not found"); private static Dialect currentDialect; @Parameters(name = "dialect = {0}") @@ -219,9 +222,27 @@ public void testStatementExecuteQuery() throws SQLException { try (ResultSet resultSet = statement.executeQuery(query)) { verifyResultSet(resultSet); } + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(r -> r.getSql().equals(query)) + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasSingleUse()); + assertTrue(request.getTransaction().getSingleUse().hasReadOnly()); + assertFalse(request.getLastStatement()); + try (ResultSet resultSet = statement.executeQuery(dmlReturning)) { verifyResultSet(resultSet); } + request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(r -> r.getSql().equals(dmlReturning)) + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + try (ResultSet resultSet = statement.executeQuery(clientSideQuery)) { verifyClientSideResultSet(resultSet); } @@ -237,6 +258,15 @@ public void testStatementExecuteUpdate() throws SQLException { try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter(r -> r.getSql().equals(dml)) + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0, statement.executeUpdate(DDL)); connection.setAutoCommit(false); @@ -256,6 +286,14 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals(1, statement.executeUpdate(dml, Statement.NO_GENERATED_KEYS)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0, statement.executeUpdate(DDL, Statement.NO_GENERATED_KEYS)); assertEquals(0, statement.executeUpdate(clientSideUpdate, Statement.NO_GENERATED_KEYS)); @@ -271,6 +309,14 @@ public void testStatementExecuteUpdateReturnColumnNames() throws SQLException { try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new String[] {"id"})); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"})); assertEquals(0, statement.executeUpdate(clientSideUpdate, new String[] {"id"})); @@ -289,6 +335,14 @@ public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1, statement.executeUpdate(dml, new int[] {1})); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0, statement.executeUpdate(DDL, new int[] {1})); assertEquals(0, statement.executeUpdate(clientSideUpdate, new int[] {1})); verifyOverflow(() -> statement.executeUpdate(largeDml, new int[] {1})); @@ -303,6 +357,14 @@ public void testStatementLargeExecuteUpdate() throws SQLException { try (Connection connection = createJdbcConnection(); Statement statement = connection.createStatement()) { assertEquals(1L, statement.executeLargeUpdate(dml)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0L, statement.executeLargeUpdate(DDL)); assertEquals(0L, statement.executeLargeUpdate(clientSideUpdate)); assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml)); @@ -318,6 +380,14 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep Statement statement = connection.createStatement()) { // TODO: Add tests for RETURN_GENERATED_KEYS when that is supported. assertEquals(1, statement.executeLargeUpdate(dml, Statement.NO_GENERATED_KEYS)); + ExecuteSqlRequest request = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .findAny() + .orElseThrow(() -> REQUEST_NOT_FOUND); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertTrue(request.getLastStatement()); + assertEquals(0, statement.executeLargeUpdate(DDL, Statement.NO_GENERATED_KEYS)); assertEquals(0, statement.executeLargeUpdate(clientSideUpdate, Statement.NO_GENERATED_KEYS)); assertEquals( @@ -870,4 +940,102 @@ public void testExecuteAutoBatchDml() throws SQLException { assertEquals(3, request.getStatementsCount()); assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); } + + @Test + public void testLastStatement_AutoCommit_Query() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + //noinspection EmptyTryBlock + try (ResultSet ignore = statement.executeQuery(query)) {} + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_AutoCommit_Dml() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + statement.executeUpdate(dml); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertTrue(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_AutoCommit_DmlReturning() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + //noinspection EmptyTryBlock + try (ResultSet ignore = statement.executeQuery(dmlReturning)) {} + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertTrue(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_AutoCommit_BatchDml() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + statement.addBatch(dml); + statement.addBatch(dml); + statement.executeBatch(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertTrue( + mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0).getLastStatements()); + } + + @Test + public void testLastStatement_Transaction_Query() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + connection.setAutoCommit(false); + //noinspection EmptyTryBlock + try (ResultSet ignore = statement.executeQuery(query)) {} + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_Transaction_Dml() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + connection.setAutoCommit(false); + statement.executeUpdate(dml); + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_Transaction_DmlReturning() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + connection.setAutoCommit(false); + //noinspection EmptyTryBlock + try (ResultSet ignore = statement.executeQuery(dmlReturning)) {} + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement()); + } + + @Test + public void testLastStatement_Transaction_BatchDml() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + connection.setAutoCommit(false); + statement.addBatch(dml); + statement.addBatch(dml); + statement.executeBatch(); + connection.commit(); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertFalse( + mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0).getLastStatements()); + } } From d3937438dbf7ae9d5a4a482efa019524030ac7fd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 14:32:39 +0100 Subject: [PATCH 1571/1979] chore(main): release 2.27.0 (#1912) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 34 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++-- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ae96e3365bba..a20633643ceb 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,39 @@ # Changelog +## [2.27.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.26.1...v2.27.0) (2025-02-21) + + +### Features + +* Add methods for unwrapping Spanner client ([#1914](https://github.com/googleapis/java-spanner-jdbc/issues/1914)) ([ee6082f](https://github.com/googleapis/java-spanner-jdbc/commit/ee6082fc455860a0f768a1798f98454bbd4cfeb0)) +* Support FOR UPDATE clauses ([#1919](https://github.com/googleapis/java-spanner-jdbc/issues/1919)) ([d296aa9](https://github.com/googleapis/java-spanner-jdbc/commit/d296aa909be23be56faf69e348263cc195708585)) + + +### Performance Improvements + +* Use last_statement optimization in autocommit ([#1911](https://github.com/googleapis/java-spanner-jdbc/issues/1911)) ([ce0c422](https://github.com/googleapis/java-spanner-jdbc/commit/ce0c42269486ddd1f4296f38dc9843e4c1ee87ef)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.58.0 ([#1909](https://github.com/googleapis/java-spanner-jdbc/issues/1909)) ([deefebe](https://github.com/googleapis/java-spanner-jdbc/commit/deefebec85a202ed516b8acc9005691e47f91486)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.87.0 ([#1925](https://github.com/googleapis/java-spanner-jdbc/issues/1925)) ([121ad50](https://github.com/googleapis/java-spanner-jdbc/commit/121ad504f9dec432405fce40bbb452400d17d0bb)) +* Update dependency com.google.cloud:google-cloud-trace to v2.58.0 ([#1910](https://github.com/googleapis/java-spanner-jdbc/issues/1910)) ([9b621df](https://github.com/googleapis/java-spanner-jdbc/commit/9b621df8076775a8b72feb953c878b919ef2a6e5)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.43.0 ([#1908](https://github.com/googleapis/java-spanner-jdbc/issues/1908)) ([c8a2217](https://github.com/googleapis/java-spanner-jdbc/commit/c8a2217c5692219d66e84971741121e725af4ceb)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.47.0 ([#1907](https://github.com/googleapis/java-spanner-jdbc/issues/1907)) ([bfc05e5](https://github.com/googleapis/java-spanner-jdbc/commit/bfc05e52540fc9eeb7523322e567637499f7bf41)) +* Update dependency org.springframework.boot:spring-boot to v3.4.3 ([#1922](https://github.com/googleapis/java-spanner-jdbc/issues/1922)) ([3e13089](https://github.com/googleapis/java-spanner-jdbc/commit/3e13089606da51452c08782e5526e7685c6b6852)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.3 ([#1923](https://github.com/googleapis/java-spanner-jdbc/issues/1923)) ([040b467](https://github.com/googleapis/java-spanner-jdbc/commit/040b46783debc03c8d157decde8a80c4707a6951)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.3 ([#1924](https://github.com/googleapis/java-spanner-jdbc/issues/1924)) ([3cdaad9](https://github.com/googleapis/java-spanner-jdbc/commit/3cdaad949e5dff2916ce69a9adae18806ec8fb26)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.3 ([#1913](https://github.com/googleapis/java-spanner-jdbc/issues/1913)) ([4744c11](https://github.com/googleapis/java-spanner-jdbc/commit/4744c1101faef14d0ce3984f3aafc6f002a38359)) +* Update dependency org.testcontainers:testcontainers to v1.20.5 ([#1926](https://github.com/googleapis/java-spanner-jdbc/issues/1926)) ([6977dfc](https://github.com/googleapis/java-spanner-jdbc/commit/6977dfcd99407c770d493fe7216cebc332ac9907)) +* Update dependency org.testcontainers:testcontainers-bom to v1.20.5 ([#1921](https://github.com/googleapis/java-spanner-jdbc/issues/1921)) ([f91415a](https://github.com/googleapis/java-spanner-jdbc/commit/f91415a75c7c97acb25188de2d68effca534ba0d)) + + +### Documentation + +* Add sample for PROTO columns ([#1918](https://github.com/googleapis/java-spanner-jdbc/issues/1918)) ([60ee659](https://github.com/googleapis/java-spanner-jdbc/commit/60ee659b62a1a940d6a1cc49138da2029e62a01e)), closes [#1916](https://github.com/googleapis/java-spanner-jdbc/issues/1916) +* Regenerate Connection properties documentation ([#1915](https://github.com/googleapis/java-spanner-jdbc/issues/1915)) ([dfddf08](https://github.com/googleapis/java-spanner-jdbc/commit/dfddf08b9af9dae358ddc6a875101f2e35fbef13)) + ## [2.26.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.26.0...v2.26.1) (2025-02-03) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0e445bf001a9..85576faed795 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.26.1 + 2.27.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.26.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.27.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.26.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.27.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 23b5ca664408..972790d254d8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.26.2-SNAPSHOT + 2.27.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ccd66c4ea00c..e6a9447294b1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.2-SNAPSHOT + 2.27.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index a3cc8f9a1769..fcd51f942bf5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.26.1:2.26.2-SNAPSHOT +google-cloud-spanner-jdbc:2.27.0:2.27.0 From 7568c99574e3a67e4ea8aadd8c2a75eb4754a282 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 21 Feb 2025 17:58:25 +0000 Subject: [PATCH 1572/1979] chore(main): release 2.27.1-SNAPSHOT (#1928) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 972790d254d8..b59795d6a58a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.27.0 + 2.27.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e6a9447294b1..acab38c1c247 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.0 + 2.27.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fcd51f942bf5..e675c53a8e84 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.27.0:2.27.0 +google-cloud-spanner-jdbc:2.27.0:2.27.1-SNAPSHOT From ee3002a1113e0ff71b6ad299dba53ac8867149b3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Feb 2025 13:08:14 +0100 Subject: [PATCH 1573/1979] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.9.0 (#1933) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b59795d6a58a..ef72fd3e7df3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -468,7 +468,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.8.0 + 3.9.0 From 3d0f6a709862c40786a4ee060b12adad1d14d06a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Feb 2025 13:08:37 +0100 Subject: [PATCH 1574/1979] build(deps): update dependency org.apache.maven.plugins:maven-deploy-plugin to v3.1.4 (#1932) --- java-spanner-jdbc/samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/pom.xml b/java-spanner-jdbc/samples/pom.xml index bfe9954b2ed3..c36572ade921 100644 --- a/java-spanner-jdbc/samples/pom.xml +++ b/java-spanner-jdbc/samples/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.3 + 3.1.4 true From d037b5c31f1442343267fb0549fe30b37fd72258 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Feb 2025 13:08:54 +0100 Subject: [PATCH 1575/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.55.0 (#1930) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 31a5cb50c88e..0dc69e62fe69 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.54.0 + 26.55.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6e5560f6e85b..a6778c65b7bf 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.54.0 + 26.55.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index a9a18f70e4c5..b9d7379df05f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.54.0 + 26.55.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 1e6f6ac62e06..f556e1f68eb9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.54.0 + 26.55.0 import pom From 065bfdcd664a1ad283fb8fb1fb196925a61fae23 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 27 Feb 2025 13:09:16 +0100 Subject: [PATCH 1576/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.27.0 (#1929) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ef9e179f9daf..9456eaec5014 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.26.1 + 2.27.0 From e4c2f7ed5ebf639606ad7aa196db012cc313ad66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 27 Feb 2025 13:18:53 +0100 Subject: [PATCH 1577/1979] docs: add defaultSequenceKind connection property documentation (#1935) Adds documentation for the defaultSequenceKind connection property. --- java-spanner-jdbc/documentation/connection_properties.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index 52938f4eff0b..887278da12cc 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -22,6 +22,7 @@ The 'Context' value indicates whether the property can only be set when a connec | databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | | databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | true, false | USER | | ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | FAIL, ALLOW_IN_EMPTY_TRANSACTION, AUTO_COMMIT_TRANSACTION | USER | +| defaultsequencekind | The default sequence kind that should be used for the database. This property is only used when a DDL statement that requires a default sequence kind is executed on this connection. | | | USER | | delaytransactionstartuntilfirstwrite | Enabling this option will delay the actual start of a read/write transaction until the first write operation is seen in that transaction. All reads that happen before the first write in a transaction will instead be executed as if the connection was in auto-commit mode. Enabling this option will make read/write transactions lose their SERIALIZABLE isolation level. Read operations that are executed after the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking and improve performance for applications that can handle the lower transaction isolation semantics. | false | true, false | USER | | dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | GOOGLE_STANDARD_SQL, POSTGRESQL | STARTUP | | directed_read | The directed read options to apply to read-only transactions. | | | USER | From 94d97765b065207b151276c2219c272f8fd0122c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 27 Feb 2025 15:09:51 +0100 Subject: [PATCH 1578/1979] fix: include COLUMN_DEFAULT in the returned metadata (#1937) Include the COLUMN_DEFAULT value in the DatabaseMetaData that is returned for the getColumns() method. These were missing, as Spanner previously did not support default values. --- .../jdbc/DatabaseMetaData_GetColumns.sql | 2 +- .../DatabaseMetaData_GetColumns.sql | 2 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 130 ++++++++++++++---- .../spanner/jdbc/it/CreateMusicTables.sql | 10 +- 4 files changed, 112 insertions(+), 32 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 94d2a0e61cf0..b59f3b78a6a0 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -63,7 +63,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU ELSE 2 END AS NULLABLE, NULL AS REMARKS, - NULL AS COLUMN_DEF, + COLUMN_DEFAULT AS COLUMN_DEF, 0 AS SQL_DATA_TYPE, 0 AS SQL_DATETIME_SUB, CASE diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index 38c105108864..5924f980f732 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -62,7 +62,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A ELSE 2 END AS "NULLABLE", NULL AS "REMARKS", - NULL AS "COLUMN_DEF", + COLUMN_DEFAULT AS "COLUMN_DEF", 0 AS "SQL_DATA_TYPE", 0 AS "SQL_DATETIME_SUB", CHARACTER_MAXIMUM_LENGTH AS "CHAR_OCTET_LENGTH", diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 94d9ad1403ea..0ebd0031aae2 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseAdminClient; @@ -62,10 +61,6 @@ public class ITJdbcDatabaseMetaDataTest extends ITAbstractJdbcTest { @BeforeClass public static void setup() throws Exception { - assumeFalse( - "Named schemas are not yet supported on the emulator", - EmulatorSpannerHelper.isUsingEmulator()); - database = env.getOrCreateDatabase( Dialect.GOOGLE_STANDARD_SQL, getMusicTablesDdl(Dialect.GOOGLE_STANDARD_SQL)); @@ -89,6 +84,18 @@ public static void setup() throws Exception { .map(statement -> statement.replace(" ON ", " ON test.")) .map(statement -> statement.replace(" ON test.DELETE", " ON DELETE")) .map(statement -> statement.replace(" REFERENCES ", " REFERENCES test.")) + .map( + statement -> + EmulatorSpannerHelper.isUsingEmulator() + ? statement.replace("Fk_Concerts_Singer", "test_Fk_Concerts_Singer") + : statement) + .map( + statement -> + EmulatorSpannerHelper.isUsingEmulator() + ? statement.replace( + "Fk_TableWithRef_TableWithAllColumnTypes", + "test_Fk_TableWithRef_TableWithAllColumnTypes") + : statement) .collect(Collectors.toList()); tables.add(0, "create schema test"); client @@ -110,6 +117,7 @@ private static final class Column { private final boolean nullable; private final Integer charOctetLength; private final boolean computed; + private final String defaultValue; private Column( String name, @@ -120,7 +128,17 @@ private Column( Integer radix, boolean nullable, Integer charOctetLength) { - this(name, type, typeName, colSize, decimalDigits, radix, nullable, charOctetLength, false); + this( + name, + type, + typeName, + colSize, + decimalDigits, + radix, + nullable, + charOctetLength, + false, + null); } private Column( @@ -132,7 +150,8 @@ private Column( Integer radix, boolean nullable, Integer charOctetLength, - boolean computed) { + boolean computed, + String defaultValue) { this.name = name; this.type = type; this.typeName = typeName; @@ -142,21 +161,42 @@ private Column( this.nullable = nullable; this.charOctetLength = charOctetLength; this.computed = computed; + this.defaultValue = defaultValue; } } private static final List EXPECTED_COLUMNS = Arrays.asList( new Column("ColInt64", Types.BIGINT, "INT64", 19, null, 10, false, null), - new Column("ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null), - new Column("ColFloat32", Types.REAL, "FLOAT32", 15, 16, 2, false, null), + new Column("ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null, false, "0.0"), + new Column("ColFloat32", Types.REAL, "FLOAT32", 15, 16, 2, false, null, false, "0.0"), new Column("ColBool", Types.BOOLEAN, "BOOL", null, null, null, false, null), - new Column("ColString", Types.NVARCHAR, "STRING(100)", 100, null, null, false, 100), + new Column( + "ColString", + Types.NVARCHAR, + "STRING(100)", + 100, + null, + null, + false, + 100, + false, + "'Hello World!'"), new Column( "ColStringMax", Types.NVARCHAR, "STRING(MAX)", 2621440, null, null, false, 2621440), new Column("ColBytes", Types.BINARY, "BYTES(100)", 100, null, null, false, null), new Column("ColBytesMax", Types.BINARY, "BYTES(MAX)", 10485760, null, null, false, null), - new Column("ColDate", Types.DATE, "DATE", 10, null, null, false, null), + new Column( + "ColDate", + Types.DATE, + "DATE", + 10, + null, + null, + false, + null, + false, + "DATE '2000-01-01'"), new Column("ColTimestamp", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColCommitTS", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColNumeric", Types.NUMERIC, "NUMERIC", 15, null, 10, false, null), @@ -202,7 +242,8 @@ private Column( null, true, 2621440, - true)); + true, + null)); @Test public void testGetColumns() throws SQLException { @@ -244,7 +285,7 @@ public void testGetColumns() throws SQLException { col.nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, rs.getInt("NULLABLE")); assertNull(rs.getString("REMARKS")); - assertNull(rs.getString("COLUMN_DEF")); + assertEquals(col.defaultValue, rs.getString("COLUMN_DEF")); assertEquals(0, rs.getInt("SQL_DATA_TYPE")); assertEquals(0, rs.getInt("SQL_DATETIME_SUB")); if (col.charOctetLength == null) { @@ -360,7 +401,11 @@ public void testGetCrossReferences() throws SQLException { assertEquals(1, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_Concerts_Singer", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + } assertEquals("PK_Singers", rs.getString("PK_NAME")); assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertFalse(rs.next()); @@ -389,7 +434,11 @@ public void testGetCrossReferences() throws SQLException { assertEquals(1, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertTrue(rs.next()); @@ -404,7 +453,11 @@ public void testGetCrossReferences() throws SQLException { assertEquals(2, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertTrue(rs.next()); @@ -419,7 +472,11 @@ public void testGetCrossReferences() throws SQLException { assertEquals(3, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyNoAction, rs.getShort("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getShort("DEFERRABILITY")); assertFalse(rs.next()); @@ -519,6 +576,12 @@ public void testGetIndexInfo() throws SQLException { connection.getMetaData().getIndexInfo(DEFAULT_CATALOG, schema, null, false, false)) { for (IndexInfo index : EXPECTED_INDICES) { + // The emulator does not generate indexes for foreign keys in a non-default schema. + if (EmulatorSpannerHelper.isUsingEmulator() + && "test".equals(schema) + && ("FOREIGN_KEY".equals(index.indexName) || "GENERATED".equals(index.indexName))) { + continue; + } assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); assertEquals(schema, rs.getString("TABLE_SCHEM")); @@ -612,7 +675,11 @@ private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws assertEquals(1, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertNotNull(rs.getString("PK_NAME")); // Index name is generated. assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); @@ -628,7 +695,11 @@ private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws assertEquals(2, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertNotNull(rs.getString("PK_NAME")); // Index name is generated. assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); @@ -644,7 +715,11 @@ private void assertImportedKeysTableWithRef(String schema, ResultSet rs) throws assertEquals(3, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); - assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_TableWithRef_TableWithAllColumnTypes", rs.getString("FK_NAME")); + } assertNotNull(rs.getString("PK_NAME")); // Index name is generated. assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); @@ -684,7 +759,11 @@ private void assertImportedKeysConcerts(String schema, ResultSet rs) throws SQLE assertEquals(1, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); - assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_Concerts_Singer", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + } assertEquals("PK_Singers", rs.getString("PK_NAME")); assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); @@ -720,7 +799,11 @@ private void assertExportedKeysSingers(String schema, ResultSet rs) throws SQLEx assertEquals(1, rs.getShort("KEY_SEQ")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("UPDATE_RULE")); assertEquals(DatabaseMetaData.importedKeyRestrict, rs.getInt("DELETE_RULE")); - assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + if (EmulatorSpannerHelper.isUsingEmulator() && "test".equals(schema)) { + assertEquals("test_Fk_Concerts_Singer", rs.getString("FK_NAME")); + } else { + assertEquals("Fk_Concerts_Singer", rs.getString("FK_NAME")); + } assertEquals("PK_Singers", rs.getString("PK_NAME")); assertEquals(DatabaseMetaData.importedKeyNotDeferrable, rs.getInt("DEFERRABILITY")); @@ -888,9 +971,6 @@ public void testGetTables() throws SQLException { try (ResultSet rs = connection.getMetaData().getTables(DEFAULT_CATALOG, schema, null, null)) { for (Table table : EXPECTED_TABLES) { - if (EmulatorSpannerHelper.isUsingEmulator() && table.name.equals("SingersView")) { - continue; - } assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); assertEquals(schema, rs.getString("TABLE_SCHEM")); diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 51f7d1ea12e7..8e4a60b246d4 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -49,7 +49,7 @@ CREATE TABLE Songs ( TrackId INT64 NOT NULL, SongName STRING(MAX), Duration INT64, - SongGenre STRING(25) + SongGenre STRING(25) DEFAULT ('Jazz') ) PRIMARY KEY(SingerId, AlbumId, TrackId), INTERLEAVE IN PARENT Albums ON DELETE CASCADE; @@ -69,14 +69,14 @@ CREATE TABLE Concerts ( CREATE TABLE TableWithAllColumnTypes ( ColInt64 INT64 NOT NULL, - ColFloat64 FLOAT64 NOT NULL, - ColFloat32 FLOAT32 NOT NULL, + ColFloat64 FLOAT64 NOT NULL DEFAULT (0.0), + ColFloat32 FLOAT32 NOT NULL DEFAULT (0.0), ColBool BOOL NOT NULL, - ColString STRING(100) NOT NULL, + ColString STRING(100) NOT NULL DEFAULT ('Hello World!'), ColStringMax STRING(MAX) NOT NULL, ColBytes BYTES(100) NOT NULL, ColBytesMax BYTES(MAX) NOT NULL, - ColDate DATE NOT NULL, + ColDate DATE NOT NULL DEFAULT (DATE '2000-01-01'), ColTimestamp TIMESTAMP NOT NULL, ColCommitTS TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true), ColNumeric NUMERIC NOT NULL, From f6321fbeec01bf10f0e50faa109aa7472f4e98a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 27 Feb 2025 15:10:08 +0100 Subject: [PATCH 1579/1979] test: add tests for using multiplexed sessions (#1934) Add a couple of tests to verify that multiplexed sessions are being used by the JDBC driver when the environment variable has been set. --- .../spanner/jdbc/MultiplexedSessionsTest.java | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java new file mode 100644 index 000000000000..b7b2d2869a04 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java @@ -0,0 +1,238 @@ +/* + * Copyright 2025 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.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +import com.google.cloud.spanner.MockServerHelper; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.common.base.Strings; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +import com.google.spanner.v1.ExecuteSqlRequest; +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.Statement; +import java.util.Collections; +import java.util.Map; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class MultiplexedSessionsTest extends AbstractMockServerTest { + private static final String PROCESS_ENVIRONMENT = "java.lang.ProcessEnvironment"; + private static final String ENVIRONMENT = "theUnmodifiableEnvironment"; + private static final String SOURCE_MAP = "m"; + private static final Object STATIC_METHOD = null; + private static final Class UMODIFIABLE_MAP_CLASS = + Collections.unmodifiableMap(Collections.emptyMap()).getClass(); + private static final Class MAP_CLASS = Map.class; + + private static boolean setEnvVar = false; + + private String query; + private String dml; + private String dmlReturning; + + @SuppressWarnings("unchecked") + private static Map getModifiableEnvironment() throws Exception { + Class environmentClass = Class.forName(PROCESS_ENVIRONMENT); + java.lang.reflect.Field environmentField = environmentClass.getDeclaredField(ENVIRONMENT); + assertNotNull(environmentField); + environmentField.setAccessible(true); + + Object unmodifiableEnvironmentMap = environmentField.get(STATIC_METHOD); + assertNotNull(unmodifiableEnvironmentMap); + assertTrue(UMODIFIABLE_MAP_CLASS.isAssignableFrom(unmodifiableEnvironmentMap.getClass())); + + java.lang.reflect.Field underlyingMapField = + unmodifiableEnvironmentMap.getClass().getDeclaredField(SOURCE_MAP); + underlyingMapField.setAccessible(true); + Object underlyingMap = underlyingMapField.get(unmodifiableEnvironmentMap); + assertNotNull(underlyingMap); + assertTrue(MAP_CLASS.isAssignableFrom(underlyingMap.getClass())); + + return (Map) underlyingMap; + } + + @BeforeClass + public static void setEnvVars() throws Exception { + // Java versions 8 and lower start with 1. (1.8, 1.7 etc.). + // Higher versions start with the major version number. + // So this effectively verifies that the test is running on Java 8. + assumeTrue(System.getProperty("java.version", "undefined").startsWith("1.")); + assumeFalse(System.getProperty("os.name", "").toLowerCase().startsWith("windows")); + + if (Strings.isNullOrEmpty(System.getenv("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW"))) { + Map env = getModifiableEnvironment(); + env.put("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW", "true"); + setEnvVar = true; + } + } + + @AfterClass + public static void clearEnvVars() throws Exception { + if (setEnvVar) { + Map env = getModifiableEnvironment(); + env.remove("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW"); + } + } + + @Before + public void setupResults() { + query = "select * from my_table"; + dml = "insert into my_table (id, value) values (1, 'One')"; + String DML_THEN_RETURN_ID = dml + "\nTHEN RETURN `id`"; + dmlReturning = "insert into my_table (id, value) values (1, 'One') THEN RETURN *"; + + 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(); + 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.query( + com.google.cloud.spanner.Statement.of(dmlReturning), + 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())); + } + + private String createUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true", + getPort(), "proj", "inst", "db"); + } + + @Override + protected Connection createJdbcConnection() throws SQLException { + return DriverManager.getConnection(createUrl()); + } + + @Test + public void testStatementExecuteQuery() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + try (ResultSet resultSet = statement.executeQuery(query)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) {} + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(MockServerHelper.getSession(mockSpanner, request.getSession()).getMultiplexed()); + } + + @Test + public void testStatementExecuteUpdate() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + assertEquals(1, statement.executeUpdate(dml)); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(MockServerHelper.getSession(mockSpanner, request.getSession()).getMultiplexed()); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + } + + @Test + public void testStatementExecuteQueryDmlReturning() throws SQLException { + try (Connection connection = createJdbcConnection(); + Statement statement = connection.createStatement()) { + try (ResultSet resultSet = statement.executeQuery(dmlReturning)) { + //noinspection StatementWithEmptyBody + while (resultSet.next()) {} + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(MockServerHelper.getSession(mockSpanner, request.getSession()).getMultiplexed()); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + } +} From afa02cf380972e2a145bc0ec322cf3502ecb066d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Feb 2025 07:42:52 +0100 Subject: [PATCH 1580/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.59.0 (#1938) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ef72fd3e7df3..89a17c43c6ba 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.58.0 + 2.59.0 test From 211bf6e00a1977dfcb19c729f2732f0c3b1f65a0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Feb 2025 07:43:11 +0100 Subject: [PATCH 1581/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.59.0 (#1940) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 89a17c43c6ba..1b87263ccf84 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.58.0 + 2.59.0 test From f173486c0e05b04450f4110ed7271237c1766599 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Feb 2025 09:05:58 +0100 Subject: [PATCH 1582/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.44.0 (#1931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.44.0 * chore: add more logging * test: skip timezone tests on GraalVM * chore: skip based on vendor name --------- Co-authored-by: Knut Olav Løite --- .../workflows/unmanaged_dependency_check.yaml | 2 +- .../.kokoro/presubmit/graalvm-native-17.cfg | 2 +- .../.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 27 +++++++++++++++++-- 7 files changed, 31 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index a48787484f17..7e8b9466746c 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.43.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.44.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 8d3f11dc47e1..728751d048e9 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.43.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.44.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index f78bafd26ecb..39151469c784 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.43.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.44.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1b87263ccf84..38792b7f522b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.43.0 + 3.44.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 0dc69e62fe69..20eabefcfcda 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.43.0 + 3.44.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a6778c65b7bf..2135dd40e5a3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.43.0 + 3.44.0 diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 31a1a7f1766f..a26137b217f0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -743,9 +743,21 @@ public void test04_Timestamps() throws SQLException { Timestamp inDefaultTZ = rs.getTimestamp(4); assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); // Then get it in the test timezone. - if (testCalendar != null) { + if (testCalendar != null + && !System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") + && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm")) { Timestamp inOtherTZ = rs.getTimestamp(4, testCalendar); assertEquals( + "Timezone: " + + testCalendar + + ", rawOffset=" + + testCalendar.getTimeZone().getRawOffset() + + ", os=" + + System.getProperty("os.name") + + ", vm=" + + System.getProperty("java.vm.name") + + ", vendor=" + + System.getProperty("java.vendor"), testTimestamp.getTime() + testCalendar.getTimeZone().getRawOffset(), inOtherTZ.getTime()); } @@ -755,8 +767,19 @@ public void test04_Timestamps() throws SQLException { inDefaultTZ = rs.getTimestamp(5); if (testCalendar == null) { assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); - } else { + } else if (!System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") + && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm")) { assertEquals( + "Timezone: " + + testCalendar + + ", rawOffset=" + + testCalendar.getTimeZone().getRawOffset() + + ", os=" + + System.getProperty("os.name") + + ", vm=" + + System.getProperty("java.vm.name") + + ", vendor=" + + System.getProperty("java.vendor"), testTimestamp.getTime() - testCalendar.getTimeZone().getRawOffset(), inDefaultTZ.getTime()); } From 9fde063310bd5820cf26779b4e62d4738fbe77a6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Feb 2025 09:44:55 +0100 Subject: [PATCH 1583/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.88.0 (#1939) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 38792b7f522b..0251608b1a72 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.87.0 + 6.88.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index b9d7379df05f..2242e3d788ab 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.87.0 + 6.88.0 import pom From ed011f6a4d6eb606919b7e3766fcc1ac324126a1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 28 Feb 2025 10:23:18 +0100 Subject: [PATCH 1584/1979] chore(main): release 2.27.1 (#1936) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index a20633643ceb..b0b5090c7d99 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.27.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.27.0...v2.27.1) (2025-02-28) + + +### Bug Fixes + +* Include COLUMN_DEFAULT in the returned metadata ([#1937](https://github.com/googleapis/java-spanner-jdbc/issues/1937)) ([98eb542](https://github.com/googleapis/java-spanner-jdbc/commit/98eb542201330188570ef995e38fa2a690e1160f)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.59.0 ([#1938](https://github.com/googleapis/java-spanner-jdbc/issues/1938)) ([5458023](https://github.com/googleapis/java-spanner-jdbc/commit/54580230f61584f0691730693497171ff9bfc734)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.88.0 ([#1939](https://github.com/googleapis/java-spanner-jdbc/issues/1939)) ([3c23e90](https://github.com/googleapis/java-spanner-jdbc/commit/3c23e90b7a7dee52169db8041523f38a7ceeb6ad)) +* Update dependency com.google.cloud:google-cloud-trace to v2.59.0 ([#1940](https://github.com/googleapis/java-spanner-jdbc/issues/1940)) ([b31dd6e](https://github.com/googleapis/java-spanner-jdbc/commit/b31dd6e78b5f9b529b7cc7a9a34ea176231e22dc)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.44.0 ([#1931](https://github.com/googleapis/java-spanner-jdbc/issues/1931)) ([568a464](https://github.com/googleapis/java-spanner-jdbc/commit/568a464f29055383b7930deb42505bedad506339)) + + +### Documentation + +* Add defaultSequenceKind connection property documentation ([#1935](https://github.com/googleapis/java-spanner-jdbc/issues/1935)) ([c30b09a](https://github.com/googleapis/java-spanner-jdbc/commit/c30b09ab554d57adccaee72c36969407bbb1d4dd)) + ## [2.27.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.26.1...v2.27.0) (2025-02-21) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 85576faed795..a2fda612efb0 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.27.0 + 2.27.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.27.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.27.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.27.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.27.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0251608b1a72..a201ba9ba934 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.27.1-SNAPSHOT + 2.27.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index acab38c1c247..821d6dd7f402 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.1-SNAPSHOT + 2.27.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e675c53a8e84..4623cc481f8d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.27.0:2.27.1-SNAPSHOT +google-cloud-spanner-jdbc:2.27.1:2.27.1 From df02c62b8545bf8ed36ed1e67f733c52c29c3ba0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 19:07:29 +0100 Subject: [PATCH 1585/1979] chore(main): release 2.27.2-SNAPSHOT (#1941) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a201ba9ba934..061baab4b506 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.27.1 + 2.27.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 821d6dd7f402..8d7658d1d939 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.1 + 2.27.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4623cc481f8d..db559ad3af72 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.27.1:2.27.1 +google-cloud-spanner-jdbc:2.27.1:2.27.2-SNAPSHOT From 1331ee15a510011e6bdf51a67fb983b33621abd8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Mar 2025 14:32:22 +0100 Subject: [PATCH 1586/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.20.6 (#1947) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index f556e1f68eb9..b6e29ff7482e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.5 + 1.20.6 import pom From f400cd497498455a1ce62ce0c66f636429cbcbcb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Mar 2025 14:32:38 +0100 Subject: [PATCH 1587/1979] deps: update dependency org.testcontainers:testcontainers to v1.20.6 (#1946) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 061baab4b506..34131db65155 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.5 + 1.20.6 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 20eabefcfcda..af5a35c2cff7 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.5 + 1.20.6 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2135dd40e5a3..1ae813e49ef7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.5 + 1.20.6 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2242e3d788ab..22d6d8b448e0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.20.5 + 1.20.6 test From a9d314a016f17470ac51e4996bc215d117755997 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Mar 2025 14:32:50 +0100 Subject: [PATCH 1588/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.56.0 (#1945) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index af5a35c2cff7..c9add839b1dd 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.55.0 + 26.56.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 1ae813e49ef7..22d1ed54dd50 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.55.0 + 26.56.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 22d6d8b448e0..8d4f21a28e7d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.55.0 + 26.56.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index b6e29ff7482e..f62d71e44105 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.55.0 + 26.56.0 import pom From 8d4eb03282f7f67e4f7d8e09f0292a5c33b429cd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Mar 2025 14:33:32 +0100 Subject: [PATCH 1589/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.27.1 (#1942) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 9456eaec5014..8be01f537c6a 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.0 + 2.27.1 From 777220b2d7af62bd53ebd1ec422b5bb0d227bd3b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 7 Mar 2025 14:33:49 +0100 Subject: [PATCH 1590/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.3 (#1943) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index c9add839b1dd..999647d3571c 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.18.2 + 2.18.3 From df799efb8cf3d511ccdcae09d08bd73abf84bb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 10 Mar 2025 12:23:08 +0100 Subject: [PATCH 1591/1979] feat: return is_autoincrement for getColumns (#1944) Spanner now supports auto-increment columns through IDENTITY columns. This change adds support for this to the DatabaseMetaData#getColumns() method. --- .../jdbc/DatabaseMetaData_GetColumns.sql | 2 +- .../DatabaseMetaData_GetColumns.sql | 2 +- .../jdbc/it/ITJdbcDatabaseMetaDataTest.java | 30 ++++++++++++++----- .../jdbc/it/ITJdbcPreparedStatementTest.java | 3 +- .../spanner/jdbc/it/CreateMusicTables.sql | 1 + 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index b59f3b78a6a0..8509ee00f06f 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -78,7 +78,7 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU NULL AS SCOPE_SCHEMA, NULL AS SCOPE_TABLE, NULL AS SOURCE_DATA_TYPE, - 'NO' AS IS_AUTOINCREMENT, + IS_IDENTITY AS IS_AUTOINCREMENT, CASE WHEN (IS_GENERATED = 'NEVER') THEN 'NO' ELSE 'YES' diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index 5924f980f732..a8260ff1383c 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -72,7 +72,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A NULL AS "SCOPE_SCHEMA", NULL AS "SCOPE_TABLE", NULL AS "SOURCE_DATA_TYPE", - 'NO' AS "IS_AUTOINCREMENT", + IS_IDENTITY AS "IS_AUTOINCREMENT", CASE WHEN (IS_GENERATED = 'NEVER') THEN 'NO' ELSE 'YES' diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 0ebd0031aae2..6f514bed0966 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -118,6 +118,7 @@ private static final class Column { private final Integer charOctetLength; private final boolean computed; private final String defaultValue; + private final boolean autoIncrement; private Column( String name, @@ -138,7 +139,8 @@ private Column( nullable, charOctetLength, false, - null); + null, + false); } private Column( @@ -151,7 +153,8 @@ private Column( boolean nullable, Integer charOctetLength, boolean computed, - String defaultValue) { + String defaultValue, + boolean autoIncrement) { this.name = name; this.type = type; this.typeName = typeName; @@ -162,14 +165,17 @@ private Column( this.charOctetLength = charOctetLength; this.computed = computed; this.defaultValue = defaultValue; + this.autoIncrement = autoIncrement; } } private static final List EXPECTED_COLUMNS = Arrays.asList( new Column("ColInt64", Types.BIGINT, "INT64", 19, null, 10, false, null), - new Column("ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null, false, "0.0"), - new Column("ColFloat32", Types.REAL, "FLOAT32", 15, 16, 2, false, null, false, "0.0"), + new Column( + "ColFloat64", Types.DOUBLE, "FLOAT64", 15, 16, 2, false, null, false, "0.0", false), + new Column( + "ColFloat32", Types.REAL, "FLOAT32", 15, 16, 2, false, null, false, "0.0", false), new Column("ColBool", Types.BOOLEAN, "BOOL", null, null, null, false, null), new Column( "ColString", @@ -181,7 +187,8 @@ private Column( false, 100, false, - "'Hello World!'"), + "'Hello World!'", + false), new Column( "ColStringMax", Types.NVARCHAR, "STRING(MAX)", 2621440, null, null, false, 2621440), new Column("ColBytes", Types.BINARY, "BYTES(100)", 100, null, null, false, null), @@ -196,7 +203,8 @@ private Column( false, null, false, - "DATE '2000-01-01'"), + "DATE '2000-01-01'", + false), new Column("ColTimestamp", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColCommitTS", Types.TIMESTAMP, "TIMESTAMP", 35, null, null, false, null), new Column("ColNumeric", Types.NUMERIC, "NUMERIC", 15, null, 10, false, null), @@ -243,7 +251,10 @@ private Column( true, 2621440, true, - null)); + null, + false), + new Column( + "ColIdentity", Types.BIGINT, "INT64", 19, null, 10, true, null, false, null, true)); @Test public void testGetColumns() throws SQLException { @@ -301,8 +312,11 @@ public void testGetColumns() throws SQLException { assertNull(rs.getString("SCOPE_TABLE")); assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); - assertEquals("NO", rs.getString("IS_AUTOINCREMENT")); assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); + // TODO: Remove check when the emulator correctly returns IS_IDENTITY + if (!EmulatorSpannerHelper.isUsingEmulator()) { + assertEquals(col.autoIncrement ? "YES" : "NO", rs.getString("IS_AUTOINCREMENT")); + } assertEquals(24, rs.getMetaData().getColumnCount()); } assertFalse(rs.next()); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index a26137b217f0..60698799fb8b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -1129,7 +1129,7 @@ public void test09_MetaData_FromQuery() throws SQLException { try (PreparedStatement ps = con.prepareStatement("SELECT * FROM TableWithAllColumnTypes WHERE ColInt64=?")) { ResultSetMetaData metadata = ps.getMetaData(); - assertEquals(26, metadata.getColumnCount()); + assertEquals(27, metadata.getColumnCount()); int index = 0; assertEquals("ColInt64", metadata.getColumnLabel(++index)); assertEquals("ColFloat64", metadata.getColumnLabel(++index)); @@ -1157,6 +1157,7 @@ public void test09_MetaData_FromQuery() throws SQLException { assertEquals("ColNumericArray", metadata.getColumnLabel(++index)); assertEquals("ColJsonArray", metadata.getColumnLabel(++index)); assertEquals("ColComputed", metadata.getColumnLabel(++index)); + assertEquals("ColIdentity", metadata.getColumnLabel(++index)); } } } diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql index 8e4a60b246d4..712551f573a1 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/it/CreateMusicTables.sql @@ -96,6 +96,7 @@ CREATE TABLE TableWithAllColumnTypes ( ColJsonArray ARRAY, ColComputed STRING(MAX) AS (CONCAT(COALESCE(ColString, ''), ' ', COALESCE(ColStringMax, ''))) STORED, + ColIdentity INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE), ) PRIMARY KEY (ColInt64) ; From a859610724d9564142d7692df48e1c567c4c5dd2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 10 Mar 2025 15:34:17 +0100 Subject: [PATCH 1592/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.48.0 (#1950) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 8d4f21a28e7d..78747fb731e5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.47.0 + 1.48.0 pom import From f7ef68761c056211667c32676169dbb28ebc7d0d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 13 Mar 2025 10:03:58 +0100 Subject: [PATCH 1593/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.45.0 (#1951) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 7e8b9466746c..308196159b24 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.44.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.45.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 728751d048e9..ca806897bada 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.44.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.45.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 39151469c784..166f4079aeca 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.44.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.45.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 34131db65155..00ead76bb570 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.44.0 + 3.45.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 999647d3571c..ef4f2585707f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.44.0 + 3.45.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 22d1ed54dd50..5d0b87d39a0a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.44.0 + 3.45.0 From d72c34a80965a0bf517dca9d56302305bb9d7021 Mon Sep 17 00:00:00 2001 From: Sagnik Ghosh Date: Thu, 13 Mar 2025 14:53:07 +0530 Subject: [PATCH 1594/1979] chore: support spanner prefix jdbc url (#1927) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support spanner prefix jdbc url * test: add tests * modified unit test --------- Co-authored-by: Knut Olav Løite --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 4 +-- .../cloud/spanner/jdbc/JdbcDriverTest.java | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 3fb70106a113..7c9b46052166 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -216,7 +216,7 @@ public JdbcDriver() {} @Override public Connection connect(String url, Properties info) throws SQLException { - if (url != null && url.startsWith("jdbc:cloudspanner")) { + if (url != null && (url.startsWith("jdbc:cloudspanner") || url.startsWith("jdbc:spanner"))) { try { Matcher matcher = URL_PATTERN.matcher(url); Matcher matcherExternalHost = EXTERNAL_HOST_URL_PATTERN.matcher(url); @@ -271,7 +271,7 @@ private String appendPropertiesToUrl(String url, Properties info) { @Override public boolean acceptsURL(String url) { - return URL_PATTERN.matcher(url).matches(); + return URL_PATTERN.matcher(url).matches() || EXTERNAL_HOST_URL_PATTERN.matcher(url).matches(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index b4ae04f56801..494233fafc4e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -135,13 +135,14 @@ public void testRegister() throws SQLException { @Test public void testConnect() throws SQLException { - try (Connection connection = - DriverManager.getConnection( - String.format( - "jdbc:cloudspanner://localhost:%d/projects/some-company.com:test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s", - server.getPort(), TEST_KEY_PATH))) { - assertThat(connection.isClosed()).isFalse(); - } + for (String prefix : new String[] {"cloudspanner", "spanner"}) + try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:%s://localhost:%d/projects/some-company.com:test-project/instances/static-test-instance/databases/test-database;usePlainText=true;credentials=%s", + prefix, server.getPort(), TEST_KEY_PATH))) { + assertThat(connection.isClosed()).isFalse(); + } } @Test(expected = SQLException.class) @@ -215,6 +216,17 @@ public void testLenient() throws SQLException { } } + @Test + public void testAcceptsURL() throws SQLException { + JdbcDriver driver = JdbcDriver.getRegisteredDriver(); + assertTrue( + driver.acceptsURL( + "jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-database")); + assertTrue( + driver.acceptsURL( + "jdbc:spanner:/projects/my-project/instances/my-instance/databases/my-database")); + } + @Test public void testJdbcExternalHostFormat() { Matcher matcherWithoutInstance = From 70d8383f4c563f53952cbbe64ddb3030cec03afe Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 17 Mar 2025 08:57:17 +0100 Subject: [PATCH 1595/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.45.1 (#1952) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 308196159b24..6b4a8e5c55ae 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.45.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.45.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index ca806897bada..07ae08a9807a 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.45.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.45.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index 166f4079aeca..fb1979a33bab 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.45.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.45.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 00ead76bb570..1f2e982d7f95 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.45.0 + 3.45.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ef4f2585707f..2964c14c60d0 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.45.0 + 3.45.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5d0b87d39a0a..6224f029f69c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.45.0 + 3.45.1 From 0588a3d9e74f5c3ed53affc35120aa77b7644e0b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 17 Mar 2025 08:57:28 +0100 Subject: [PATCH 1596/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.4 (#1953) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 78747fb731e5..af8cb4c825f2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.3 + 2024.1.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index f62d71e44105..8ff56df91264 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.3 + 2024.1.4 import pom From 49b68319be2ec43274e42c523f813bcf0d2bb166 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Mar 2025 10:20:19 +0100 Subject: [PATCH 1597/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.34.0 (#1955) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index af8cb4c825f2..1fd118499ab7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -88,7 +88,7 @@ com.google.cloud.opentelemetry exporter-metrics - 0.33.0 + 0.34.0 From e569b7bcaf1acb9b67fa95f7fa779ce03dc869bf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Mar 2025 10:26:54 +0100 Subject: [PATCH 1598/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.34.0 (#1956) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1f2e982d7f95..70b4a9466336 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -204,7 +204,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.33.0 + 0.34.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 1fd118499ab7..5903bded6eec 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.33.0 + 0.34.0 com.google.cloud.opentelemetry From f19a5e15373ac2e8bcc476470c36ee4f2f21006c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 08:57:33 +0100 Subject: [PATCH 1599/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.60.0 (#1959) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 70b4a9466336..45d2a8219116 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.59.0 + 2.60.0 test From 999c24e6ffd071469e3c5c33d7d9b39b6e8270f6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 08:57:46 +0100 Subject: [PATCH 1600/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.60.0 (#1958) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 45d2a8219116..217fe3838b02 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.59.0 + 2.60.0 test From 0553552865f6eac3f4f76b35da80893c9ce6ec00 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 09:08:37 +0100 Subject: [PATCH 1601/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.89.0 (#1961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.89.0 * chore: update test cases and regenerate documentation The Spanner client now also uses a multiplexed session to determine the database dialect that is in use. This means that BatchCreateSessions is not being called at all in many cases. Also re-generates the connection properties documentation. The typo in the description of the new connection property must be fixed in the Spanner client, as the list here is generated based on the source in the client. * chore: run code formatter --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/documentation/connection_properties.md | 1 + java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 3 +-- .../cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java | 4 +--- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index 887278da12cc..abc9088421ed 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -31,6 +31,7 @@ The 'Context' value indicates whether the property can only be set when a connec | enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | true, false | STARTUP | | encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | | endpoint | The endpoint that the JDBC driver should connect to. The default is the default Spanner production endpoint when autoConfigEmulator=false, and the default Spanner emulator endpoint (localhost:9010) when autoConfigEmulator=true. This property takes precedence over any host name at the start of the connection URL. | | | STARTUP | +| isexperimentalhost | Set this value to true for communication with a Experimental Host. | false | true, false | STARTUP | | keeptransactionalive | Enabling this option will trigger the connection to keep read/write transactions alive by executing a SELECT 1 query once every 10 seconds if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time. | false | true, false | USER | | lenient | Silently ignore unknown properties in the connection string/properties (true/false) | false | true, false | STARTUP | | maxcommitdelay | The max delay that Spanner may apply to commit requests to improve throughput. | | | USER | diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 217fe3838b02..abf82c57ff70 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.88.0 + 6.89.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 5903bded6eec..e614c9c68cf5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.88.0 + 6.89.0 import pom diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index ba94647cbcfa..c337f64cf15c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -430,8 +430,7 @@ public void transactionalCreateSession() throws SQLException { @Test public void readOnlyCreateSession() throws SQLException { - mockSpanner.setBatchCreateSessionsExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java index 251dc34f3534..9fc6a89ddf9c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -205,8 +205,6 @@ public void testUsesMultiplexedSessionInCombinationWithSessionPoolOptions() thro CreateSessionRequest request = mockSpanner.getRequestsOfType(CreateSessionRequest.class).get(0); assertTrue(request.getSession().getMultiplexed()); // There should be no regular sessions in use. - // However, the query that detects the dialect that is used, uses a regular session. - // This should be fixed in the Java client. - assertEquals(1, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); } } From a17e7d4818bd648b20d9186934bd8b3c46e87f06 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 09:08:52 +0100 Subject: [PATCH 1602/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.4 (#1962) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2964c14c60d0..f39aa299c44a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.3 + 3.4.4 test From b4a293b3e7b5580be06c7b6b7be9d5677c8e0ab3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 09:09:04 +0100 Subject: [PATCH 1603/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.4 (#1963) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index e614c9c68cf5..6e2cbdf7ec25 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.3 + 3.4.4 From 4ac6db922ebae119ec24ddd0c524b08f37c0212d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 09:18:08 +0100 Subject: [PATCH 1604/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.4 (#1964) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 8ff56df91264..03b732041a1b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.3 + 3.4.4 From f3f82e71a891459b26c1daa15600084d7089ff64 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 09:52:06 +0100 Subject: [PATCH 1605/1979] chore(main): release 2.28.0 (#1948) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 31 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index b0b5090c7d99..4ef8ddf1fc9e 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [2.28.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.27.1...v2.28.0) (2025-03-21) + + +### Features + +* Return is_autoincrement for getColumns ([#1944](https://github.com/googleapis/java-spanner-jdbc/issues/1944)) ([b9fcae9](https://github.com/googleapis/java-spanner-jdbc/commit/b9fcae942b1f52f82bbd5ae4357e1d4e84bee5a4)) + + +### Performance Improvements + +* Get database dialect using multiplexed session ([c5f3297](https://github.com/googleapis/java-spanner-jdbc/commit/c5f32979a682643e135a40dfd7681de841bce0de)) +* Skip gRPC trailers for successful queries ([c5f3297](https://github.com/googleapis/java-spanner-jdbc/commit/c5f32979a682643e135a40dfd7681de841bce0de)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.18.3 ([#1943](https://github.com/googleapis/java-spanner-jdbc/issues/1943)) ([dc9af80](https://github.com/googleapis/java-spanner-jdbc/commit/dc9af80b20bbb798a7e6f4c6de577ab8249c426d)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.60.0 ([#1958](https://github.com/googleapis/java-spanner-jdbc/issues/1958)) ([37fca7b](https://github.com/googleapis/java-spanner-jdbc/commit/37fca7b47ca8480afc64f45db3e364218686674e)) +* Update dependency com.google.cloud:google-cloud-trace to v2.60.0 ([#1959](https://github.com/googleapis/java-spanner-jdbc/issues/1959)) ([f154740](https://github.com/googleapis/java-spanner-jdbc/commit/f15474061f8c4780fe2a8457882761598f1ecc8c)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.45.0 ([#1951](https://github.com/googleapis/java-spanner-jdbc/issues/1951)) ([00f163b](https://github.com/googleapis/java-spanner-jdbc/commit/00f163bdc016e5411d0f64af27fe353c2be75065)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.45.1 ([#1952](https://github.com/googleapis/java-spanner-jdbc/issues/1952)) ([c7c7363](https://github.com/googleapis/java-spanner-jdbc/commit/c7c7363736f105d9d0c2593d3a354d7789c1a801)) +* Update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.34.0 ([#1955](https://github.com/googleapis/java-spanner-jdbc/issues/1955)) ([b52cadd](https://github.com/googleapis/java-spanner-jdbc/commit/b52caddd2a08ead671db0f64dea48957bdb4ac1c)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.34.0 ([#1956](https://github.com/googleapis/java-spanner-jdbc/issues/1956)) ([2158ff2](https://github.com/googleapis/java-spanner-jdbc/commit/2158ff241c4adf27229fa409780282be4106dd5f)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.48.0 ([#1950](https://github.com/googleapis/java-spanner-jdbc/issues/1950)) ([99b70ce](https://github.com/googleapis/java-spanner-jdbc/commit/99b70ce1bac31dee520cb1ca3743c64c296fb901)) +* Update dependency org.springframework.boot:spring-boot to v3.4.4 ([#1962](https://github.com/googleapis/java-spanner-jdbc/issues/1962)) ([86b05e2](https://github.com/googleapis/java-spanner-jdbc/commit/86b05e2dba04603198f595e91fdc2f5b66f4eb80)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.4 ([#1963](https://github.com/googleapis/java-spanner-jdbc/issues/1963)) ([53d3e8b](https://github.com/googleapis/java-spanner-jdbc/commit/53d3e8b120806f9603f10dec47bb6745bfed493b)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.4 ([#1964](https://github.com/googleapis/java-spanner-jdbc/issues/1964)) ([bf5402b](https://github.com/googleapis/java-spanner-jdbc/commit/bf5402b0e85d3a0c854401a1121bc7b82c5d06a1)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.4 ([#1953](https://github.com/googleapis/java-spanner-jdbc/issues/1953)) ([fa65ead](https://github.com/googleapis/java-spanner-jdbc/commit/fa65ead20018c083749bb1bd1cc1993f48745ef9)) +* Update dependency org.testcontainers:testcontainers to v1.20.6 ([#1946](https://github.com/googleapis/java-spanner-jdbc/issues/1946)) ([2b3e1d8](https://github.com/googleapis/java-spanner-jdbc/commit/2b3e1d839d6d8b903c5b45f84a4c6db651f732db)) +* Update dependency org.testcontainers:testcontainers-bom to v1.20.6 ([#1947](https://github.com/googleapis/java-spanner-jdbc/issues/1947)) ([0b9fb38](https://github.com/googleapis/java-spanner-jdbc/commit/0b9fb3833fb79cf211bcb1de307194ff39fe18c8)) + ## [2.27.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.27.0...v2.27.1) (2025-02-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a2fda612efb0..53eaa14087d2 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.27.1 + 2.28.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.27.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.28.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.27.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.28.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index abf82c57ff70..16a221b07f44 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.27.2-SNAPSHOT + 2.28.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8d7658d1d939..f5f01ee078ad 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.2-SNAPSHOT + 2.28.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index db559ad3af72..3fd7810ad44b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.27.1:2.27.2-SNAPSHOT +google-cloud-spanner-jdbc:2.28.0:2.28.0 From ec0fbfad53e24593735b82d1a351955776a8078d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:56:21 +0000 Subject: [PATCH 1606/1979] chore(main): release 2.28.1-SNAPSHOT (#1966) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 16a221b07f44..999527f09963 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.28.0 + 2.28.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f5f01ee078ad..ca21dc659d63 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.28.0 + 2.28.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3fd7810ad44b..fc40cb452b34 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.28.0:2.28.0 +google-cloud-spanner-jdbc:2.28.0:2.28.1-SNAPSHOT From b15051dd964dd0e58df281be25504d79303f03f8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 19:24:54 +0100 Subject: [PATCH 1607/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.28.0 (#1967) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 8be01f537c6a..86d3c5fb49f4 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.27.1 + 2.28.0 From dbe132a205205f4e206814861a621fa10d542bdd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 21 Mar 2025 19:25:05 +0100 Subject: [PATCH 1608/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.57.0 (#1968) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f39aa299c44a..eb3eb8fdbdfd 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.56.0 + 26.57.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 6224f029f69c..4000fe786139 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.56.0 + 26.57.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 6e2cbdf7ec25..fb7d2f39aeed 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.56.0 + 26.57.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 03b732041a1b..681e6f2bfa50 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.56.0 + 26.57.0 import pom From 893ab63aa8d60384774afaed296a156a84884b41 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 30 Mar 2025 16:55:24 +0200 Subject: [PATCH 1609/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.58.0 (#1969) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index eb3eb8fdbdfd..744ca4f20c13 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.57.0 + 26.58.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 4000fe786139..2d716bdb5cd3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.57.0 + 26.58.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index fb7d2f39aeed..4bf54fdb3cb2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.57.0 + 26.58.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 681e6f2bfa50..d402998a0c41 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.57.0 + 26.58.0 import pom From 223f5266c19fea6c1b247ab01635febc2dbcd5d5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Apr 2025 07:05:30 +0200 Subject: [PATCH 1610/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.90.0 (#1970) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.90.0 * chore: regenerate properties and fix a NullPointerException * chore: skip test for graalvm * chore: use `--strict-image-heap` on native tests This follows from the recent configuration adjustments from bringing GraalVM for JDK 23, which enabled this option by default. This commit uses such option for the JDK 21 GraalVM tests to consume the configuration in the same way. --------- Co-authored-by: Knut Olav Løite Co-authored-by: diegomarquezp --- java-spanner-jdbc/documentation/connection_properties.md | 5 +++-- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- .../spanner/connection/ConnectionPropertiesHelper.java | 3 ++- .../connection/ConnectionPropertiesFileGenerator.java | 3 ++- .../cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java | 6 ++++-- .../google-cloud-spanner-jdbc/native-image.properties | 1 + 7 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index abc9088421ed..cedb01d0482a 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -10,7 +10,7 @@ The 'Context' value indicates whether the property can only be set when a connec | auto_batch_dml_update_count | DML statements that are executed when auto_batch_dml is set to true, are not directly sent to Spanner, but are buffered in the client until the batch is flushed. This property determines the update count that is returned for these DML statements. The default is 1, as that is the update count that is expected by most ORMs (e.g. Hibernate). | 1 | | USER | | auto_batch_dml_update_count_verification | The update count that is returned for DML statements that are buffered during an automatic DML batch is by default 1. This value can be changed by setting the connection variable auto_batch_dml_update_count. The update counts that are returned by Spanner when the DML statements are actually executed are verified against the update counts that were returned when they were buffered. If these do not match, a com.google.cloud.spanner.DmlBatchUpdateCountVerificationFailedException will be thrown. You can disable this verification by setting auto_batch_dml_update_count_verification to false. | true | true, false | USER | | autocommit | Should the connection start in autocommit (true/false) | true | true, false | USER | -| autocommit_dml_mode | Determines the transaction type that is used to execute DML statements when the connection is in auto-commit mode. | TRANSACTIONAL | TRANSACTIONAL, PARTITIONED_NON_ATOMIC, TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC | USER | +| autocommit_dml_mode | Determines the transaction type that is used to execute DML statements when the connection is in auto-commit mode. | TRANSACTIONAL | TRANSACTIONAL, PARTITIONED_NON_ATOMIC, TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC, null | USER | | autoconfigemulator | Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect. | false | true, false | STARTUP | | autopartitionmode | Execute all queries on this connection as partitioned queries. Executing a query that cannot be partitioned will fail. Executing a query in a read/write transaction will also fail. | false | true, false | USER | | channelprovider | The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider. | | | STARTUP | @@ -22,6 +22,7 @@ The 'Context' value indicates whether the property can only be set when a connec | databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | | databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | true, false | USER | | ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | FAIL, ALLOW_IN_EMPTY_TRANSACTION, AUTO_COMMIT_TRANSACTION | USER | +| default_isolation_level | The transaction isolation level that is used by default for read/write transactions. The default is isolation_level_unspecified, which means that the connection will use the default isolation level of the database that it is connected to. | ISOLATION_LEVEL_UNSPECIFIED | ISOLATION_LEVEL_UNSPECIFIED, SERIALIZABLE, REPEATABLE_READ | USER | | defaultsequencekind | The default sequence kind that should be used for the database. This property is only used when a DDL statement that requires a default sequence kind is executed on this connection. | | | USER | | delaytransactionstartuntilfirstwrite | Enabling this option will delay the actual start of a read/write transaction until the first write operation is seen in that transaction. All reads that happen before the first write in a transaction will instead be executed as if the connection was in auto-commit mode. Enabling this option will make read/write transactions lose their SERIALIZABLE isolation level. Read operations that are executed after the first write operation in a read/write transaction will be executed using the read/write transaction. Enabling this mode can reduce locking and improve performance for applications that can handle the lower transaction isolation semantics. | false | true, false | USER | | dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | GOOGLE_STANDARD_SQL, POSTGRESQL | STARTUP | @@ -48,7 +49,7 @@ The 'Context' value indicates whether the property can only be set when a connec | retryabortsinternally | Should the connection automatically retry Aborted errors (true/false) | true | true, false | USER | | returncommitstats | Request that Spanner returns commit statistics for read/write transactions (true/false) | false | true, false | USER | | routetoleader | Should read/write transactions and partitioned DML be routed to leader region (true/false) | true | true, false | STARTUP | -| rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | LOW, MEDIUM, HIGH, UNSPECIFIED | USER | +| rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | LOW, MEDIUM, HIGH, UNSPECIFIED, null | USER | | savepoint_support | Determines the behavior of the connection when savepoints are used. | FAIL_AFTER_ROLLBACK | ENABLED, FAIL_AFTER_ROLLBACK, DISABLED | USER | | tracing_prefix | The prefix that will be prepended to all OpenTelemetry traces that are generated by a Connection. | CloudSpanner | | STARTUP | | trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | true, false | STARTUP | diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 999527f09963..66429c409cf6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.89.0 + 6.90.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 4bf54fdb3cb2..2a29fa1c065a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.89.0 + 6.90.0 import pom diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java index 7e64b8f11650..cde651e02913 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java @@ -21,6 +21,7 @@ import java.sql.DriverPropertyInfo; import java.util.Arrays; import java.util.Comparator; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -50,7 +51,7 @@ public static DriverPropertyInfo toDriverPropertyInfo( connectionProperty.getValidValues() == null ? null : Arrays.stream(connectionProperty.getValidValues()) - .map(Object::toString) + .map(Objects::toString) .toArray(String[]::new); return result; } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java index fe8dd9c968df..4307fbcb0946 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java @@ -20,6 +20,7 @@ import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; +import java.util.Objects; import java.util.stream.Collectors; /** Generator for the documentation/connection_properties.md file. */ @@ -65,7 +66,7 @@ static String getValidValues(ConnectionProperty connectionProperty) { return connectionProperty.getValidValues() == null ? "" : Arrays.stream(connectionProperty.getValidValues()) - .map(Object::toString) + .map(Objects::toString) .collect(Collectors.joining(", ")); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 60698799fb8b..99ee0016516c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -745,7 +745,8 @@ public void test04_Timestamps() throws SQLException { // Then get it in the test timezone. if (testCalendar != null && !System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm")) { + && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm") + && !System.getProperty("java.vendor", "").toLowerCase().contains("oracle")) { Timestamp inOtherTZ = rs.getTimestamp(4, testCalendar); assertEquals( "Timezone: " @@ -768,7 +769,8 @@ public void test04_Timestamps() throws SQLException { if (testCalendar == null) { assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); } else if (!System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm")) { + && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm") + && !System.getProperty("java.vendor", "").toLowerCase().contains("oracle")) { assertEquals( "Timezone: " + testCalendar diff --git a/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties b/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties new file mode 100644 index 000000000000..714d90fb1510 --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties @@ -0,0 +1 @@ +Args=--strict-image-heap From 7a6660c4a30fe0fe0eaa848c8a47232aca16a4fa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Apr 2025 07:12:46 +0200 Subject: [PATCH 1611/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.59.0 (#1971) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 744ca4f20c13..5e35b63175d1 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.58.0 + 26.59.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 2d716bdb5cd3..e1919e95b289 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.58.0 + 26.59.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 2a29fa1c065a..380e4fad76c4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.58.0 + 26.59.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index d402998a0c41..1042f63401c5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.58.0 + 26.59.0 import pom From ea51d688ef1eba8d49b9833c8755d00f05783a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 3 Apr 2025 09:09:02 +0200 Subject: [PATCH 1612/1979] feat: support isolation level repeatable read (#1973) Adds support for setting the transaction isolation level to repeatable read. --- .../spanner/jdbc/AbstractJdbcConnection.java | 10 +-- .../spanner/jdbc/IsolationLevelConverter.java | 54 ++++++++++++++ .../spanner/jdbc/JdbcDatabaseMetaData.java | 7 +- .../jdbc/IsolationLevelConverterTest.java | 67 ++++++++++++++++++ .../spanner/jdbc/JdbcConnectionTest.java | 40 +++++------ .../jdbc/JdbcDatabaseMetaDataTest.java | 2 +- .../jdbc/TransactionMockServerTest.java | 70 ++++++++++++++++++- 7 files changed, 219 insertions(+), 31 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/IsolationLevelConverterTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java index 38430cf124db..00d0823f00cf 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcConnection.java @@ -41,8 +41,8 @@ abstract class AbstractJdbcConnection extends AbstractJdbcWrapper implements CloudSpannerJdbcConnection { private static final String CALLABLE_STATEMENTS_UNSUPPORTED = "Callable statements are not supported"; - private static final String ONLY_SERIALIZABLE = - "Only isolation level TRANSACTION_SERIALIZABLE is supported"; + private static final String ONLY_SERIALIZABLE_OR_REPEATABLE_READ = + "Only isolation levels TRANSACTION_SERIALIZABLE and TRANSACTION_REPEATABLE_READ are supported"; private static final String ONLY_CLOSE_ALLOWED = "Only holdability CLOSE_CURSORS_AT_COMMIT is supported"; private static final String SQLXML_UNSUPPORTED = "SQLXML is not supported"; @@ -147,13 +147,15 @@ public void setTransactionIsolation(int level) throws SQLException { || level == TRANSACTION_READ_COMMITTED, "Not a transaction isolation level"); JdbcPreconditions.checkSqlFeatureSupported( - level == TRANSACTION_SERIALIZABLE, ONLY_SERIALIZABLE); + JdbcDatabaseMetaData.supportsIsolationLevel(level), ONLY_SERIALIZABLE_OR_REPEATABLE_READ); + spanner.setDefaultIsolationLevel(IsolationLevelConverter.convertToSpanner(level)); } @Override public int getTransactionIsolation() throws SQLException { checkClosed(); - return TRANSACTION_SERIALIZABLE; + //noinspection MagicConstant + return IsolationLevelConverter.convertToJdbc(spanner.getDefaultIsolationLevel()); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java new file mode 100644 index 000000000000..3e3e10c9f9c1 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java @@ -0,0 +1,54 @@ +/* + * Copyright 2025 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.spanner.v1.TransactionOptions.IsolationLevel; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; + +class IsolationLevelConverter { + static IsolationLevel convertToSpanner(int jdbcIsolationLevel) throws SQLException { + switch (jdbcIsolationLevel) { + case Connection.TRANSACTION_SERIALIZABLE: + return IsolationLevel.SERIALIZABLE; + case Connection.TRANSACTION_REPEATABLE_READ: + return IsolationLevel.REPEATABLE_READ; + case Connection.TRANSACTION_READ_COMMITTED: + case Connection.TRANSACTION_READ_UNCOMMITTED: + case Connection.TRANSACTION_NONE: + throw new SQLFeatureNotSupportedException( + "Unsupported JDBC isolation level: " + jdbcIsolationLevel); + default: + throw new IllegalArgumentException("Invalid JDBC isolation level: " + jdbcIsolationLevel); + } + } + + static int convertToJdbc(IsolationLevel isolationLevel) { + switch (isolationLevel) { + // Translate UNSPECIFIED to SERIALIZABLE as that is the default isolation level. + case ISOLATION_LEVEL_UNSPECIFIED: + case SERIALIZABLE: + return Connection.TRANSACTION_SERIALIZABLE; + case REPEATABLE_READ: + return Connection.TRANSACTION_REPEATABLE_READ; + default: + throw new IllegalArgumentException( + "Unknown or unsupported isolation level: " + isolationLevel); + } + } +} diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index bdebcad89a82..b7fe95145a24 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -664,7 +664,12 @@ public boolean supportsTransactions() { @Override public boolean supportsTransactionIsolationLevel(int level) { - return Connection.TRANSACTION_SERIALIZABLE == level; + return supportsIsolationLevel(level); + } + + static boolean supportsIsolationLevel(int level) { + return Connection.TRANSACTION_SERIALIZABLE == level + || Connection.TRANSACTION_REPEATABLE_READ == level; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/IsolationLevelConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/IsolationLevelConverterTest.java new file mode 100644 index 000000000000..2be9e5ea472c --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/IsolationLevelConverterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2025 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 com.google.cloud.spanner.jdbc.IsolationLevelConverter.convertToJdbc; +import static com.google.cloud.spanner.jdbc.IsolationLevelConverter.convertToSpanner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import com.google.spanner.v1.TransactionOptions.IsolationLevel; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class IsolationLevelConverterTest { + + @Test + public void testConvertToSpanner() throws SQLException { + assertEquals( + IsolationLevel.SERIALIZABLE, convertToSpanner(Connection.TRANSACTION_SERIALIZABLE)); + assertEquals( + IsolationLevel.REPEATABLE_READ, convertToSpanner(Connection.TRANSACTION_REPEATABLE_READ)); + + assertThrows( + SQLFeatureNotSupportedException.class, + () -> convertToSpanner(Connection.TRANSACTION_READ_COMMITTED)); + assertThrows( + SQLFeatureNotSupportedException.class, + () -> convertToSpanner(Connection.TRANSACTION_READ_UNCOMMITTED)); + assertThrows( + SQLFeatureNotSupportedException.class, () -> convertToSpanner(Connection.TRANSACTION_NONE)); + + assertThrows(IllegalArgumentException.class, () -> convertToSpanner(-1)); + } + + @Test + public void testConvertToJdbc() { + // There is no 'unspecified' isolation level in JDBC, so we convert this to the default + // SERIALIZABLE isolation level in Spanner. + assertEquals( + Connection.TRANSACTION_SERIALIZABLE, + convertToJdbc(IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED)); + assertEquals(Connection.TRANSACTION_SERIALIZABLE, convertToJdbc(IsolationLevel.SERIALIZABLE)); + assertEquals( + Connection.TRANSACTION_REPEATABLE_READ, convertToJdbc(IsolationLevel.REPEATABLE_READ)); + + assertThrows(IllegalArgumentException.class, () -> convertToJdbc(IsolationLevel.UNRECOGNIZED)); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index e0ea49f6f7f2..d4cfeb8d0d7f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -366,34 +366,28 @@ private void testInvokeMethodOnClosedConnection(Method method, Object... args) public void testTransactionIsolation() throws SQLException { ConnectionOptions options = mockOptions(); try (JdbcConnection connection = createConnection(options)) { - assertThat(connection.getTransactionIsolation()) - .isEqualTo(Connection.TRANSACTION_SERIALIZABLE); - // assert that setting it to this value is ok. + assertEquals(Connection.TRANSACTION_SERIALIZABLE, connection.getTransactionIsolation()); + // assert that setting it to these values is ok. connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); + assertEquals(Connection.TRANSACTION_SERIALIZABLE, connection.getTransactionIsolation()); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + assertEquals(Connection.TRANSACTION_REPEATABLE_READ, connection.getTransactionIsolation()); // assert that setting it to something else is not ok. - int[] settings = + int[] invalidValues = new int[] { - Connection.TRANSACTION_READ_COMMITTED, - Connection.TRANSACTION_READ_UNCOMMITTED, - Connection.TRANSACTION_REPEATABLE_READ, - -100 + Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_READ_UNCOMMITTED, -100 }; - for (int setting : settings) { - boolean exception = false; - try { - connection.setTransactionIsolation(setting); - } catch (SQLException e) { - if (setting == -100) { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.INVALID_ARGUMENT); - } else { - exception = - (e instanceof JdbcSqlException - && ((JdbcSqlException) e).getCode() == Code.UNIMPLEMENTED); - } + for (int invalidValue : invalidValues) { + SQLException exception = + assertThrows( + SQLException.class, () -> connection.setTransactionIsolation(invalidValue)); + assertTrue(exception instanceof JdbcSqlException); + JdbcSqlException spannerException = (JdbcSqlException) exception; + if (invalidValue == -100) { + assertEquals(Code.INVALID_ARGUMENT, spannerException.getCode()); + } else { + assertEquals(Code.UNIMPLEMENTED, spannerException.getCode()); } - assertThat(exception).isTrue(); } } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 47ab2e549321..c8970fd76d52 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -265,12 +265,12 @@ public void testTrivialMethods() throws SQLException { assertFalse(meta.usesLocalFiles()); assertFalse(meta.usesLocalFilePerTable()); assertTrue(meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE)); + assertTrue(meta.supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ)); for (int level : new int[] { Connection.TRANSACTION_NONE, Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_READ_UNCOMMITTED, - Connection.TRANSACTION_REPEATABLE_READ }) { assertFalse(meta.supportsTransactionIsolationLevel(level)); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java index 954d12e80baf..91086055d35f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/TransactionMockServerTest.java @@ -17,10 +17,14 @@ package com.google.cloud.spanner.jdbc; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.SpannerPool; import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.TransactionOptions.IsolationLevel; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @@ -45,9 +49,13 @@ public void clearRequests() { } private String createUrl() { + return createUrl(""); + } + + private String createUrl(String extraOptions) { return String.format( - "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=false", - getPort(), "proj", "inst", "db"); + "jdbc:cloudspanner://localhost:%d/projects/%s/instances/%s/databases/%s?usePlainText=true;autoCommit=false%s", + getPort(), "proj", "inst", "db", extraOptions); } @Override @@ -98,4 +106,62 @@ public void testRollingBackEmptyExplicitTransactionIsNoOp() throws SQLException assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); } + + @Test + public void testUsesDefaultIsolationLevel() throws SQLException { + try (Connection connection = createJdbcConnection()) { + for (IsolationLevel isolationLevel : + new IsolationLevel[] {IsolationLevel.SERIALIZABLE, IsolationLevel.REPEATABLE_READ}) { + //noinspection MagicConstant + connection.setTransactionIsolation(IsolationLevelConverter.convertToJdbc(isolationLevel)); + runTestTransaction(connection, isolationLevel); + } + } + } + + @Test + public void testUsesManualIsolationLevel() throws SQLException { + try (Connection connection = createJdbcConnection()) { + connection.setAutoCommit(true); + for (IsolationLevel isolationLevel : + new IsolationLevel[] {IsolationLevel.SERIALIZABLE, IsolationLevel.REPEATABLE_READ}) { + connection + .createStatement() + .execute( + "begin transaction isolation level " + isolationLevel.toString().replace("_", " ")); + runTestTransaction(connection, isolationLevel); + } + } + } + + @Test + public void testUsesDefaultIsolationLevelInConnectionString() throws SQLException { + for (IsolationLevel isolationLevel : + new IsolationLevel[] {IsolationLevel.SERIALIZABLE, IsolationLevel.REPEATABLE_READ}) { + try (Connection connection = + DriverManager.getConnection( + createUrl(";default_isolation_level=" + isolationLevel.name()))) { + runTestTransaction(connection, isolationLevel); + } + } + } + + void runTestTransaction(Connection connection, IsolationLevel expectedIsolationLevel) + throws SQLException { + String sql = "insert into foo (id) values (1)"; + mockSpanner.putStatementResult( + StatementResult.update(com.google.cloud.spanner.Statement.of(sql), 1L)); + + assertEquals(1, connection.createStatement().executeUpdate(sql)); + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertEquals(expectedIsolationLevel, request.getTransaction().getBegin().getIsolationLevel()); + + mockSpanner.clearRequests(); + } } From ef4e7c3cd32f6fd1438081c3fb893b75a9fe8e96 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 8 Apr 2025 17:29:42 +0200 Subject: [PATCH 1613/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.49.0 (#1982) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 380e4fad76c4..d7cf3b959550 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.48.0 + 1.49.0 pom import From bd694dacf422f9c3cf0fd6476ad2700a6b636c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 14 Apr 2025 10:56:45 +0200 Subject: [PATCH 1614/1979] chore: set Hibernate user-agent automatically (#1975) Use the call stack the first time that a JDBC connection is being created to determine whether the connection should use the sp-jdbc or sp-hib user-agent token. --- .../google/cloud/spanner/jdbc/JdbcDriver.java | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 7c9b46052166..f7bdb3b09e2f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.ConnectionProperty; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Suppliers; import com.google.rpc.Code; import io.opentelemetry.api.OpenTelemetry; import java.sql.Connection; @@ -222,7 +223,9 @@ public Connection connect(String url, Properties info) throws SQLException { Matcher matcherExternalHost = EXTERNAL_HOST_URL_PATTERN.matcher(url); if (matcher.matches() || matcherExternalHost.matches()) { // strip 'jdbc:' from the URL, add any extra properties and pass on to the generic - // Connection API + // Connection API. Also set the user-agent if we detect that the connection + // comes from known framework like Hibernate, and there is no other user-agent set. + maybeAddUserAgent(info); String connectionUri = appendPropertiesToUrl(url.substring(5), info); ConnectionOptions options = buildConnectionOptions(connectionUri, info); JdbcConnection connection = new JdbcConnection(url, options); @@ -259,6 +262,48 @@ private ConnectionOptions buildConnectionOptions(String connectionUrl, Propertie return builder.build(); } + static void maybeAddUserAgent(Properties properties) { + if (properties.containsKey("userAgent")) { + return; + } + if (isHibernate()) { + properties.setProperty("userAgent", "sp-hib"); + } + } + + static boolean isHibernate() { + // Cache the result as the check is relatively expensive, and we also don't want to create + // multiple different Spanner instances just to get the correct user-agent in every case. + return Suppliers.memoize( + () -> { + try { + // First check if the Spanner Hibernate dialect is on the classpath. If it is, then + // we assume that Hibernate will (eventually) be used. + Class.forName( + "com.google.cloud.spanner.hibernate.SpannerDialect", + /*initialize=*/ false, + JdbcDriver.class.getClassLoader()); + return true; + } catch (Throwable ignore) { + } + + // If we did not find the Spanner Hibernate dialect on the classpath, then do a + // check if the connection is still being created by Hibernate using the built-in + // Spanner dialect in Hibernate. + try { + StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); + for (StackTraceElement element : callStack) { + if (element.getClassName().contains(".hibernate.")) { + return true; + } + } + } catch (Throwable ignore) { + } + return false; + }) + .get(); + } + private String appendPropertiesToUrl(String url, Properties info) { StringBuilder res = new StringBuilder(url); for (Entry entry : info.entrySet()) { From cb6b529c7989234ffbde3cf427f535abb64f07f5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 22 Apr 2025 09:13:02 +0100 Subject: [PATCH 1615/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.91.1 (#1993) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 66429c409cf6..78173b9149a0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.90.0 + 6.91.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index d7cf3b959550..05699cd74fca 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.90.0 + 6.91.1 import pom From 12a25ca950fb14255dedcb41e54e81104880229f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 22 Apr 2025 15:32:48 +0200 Subject: [PATCH 1616/1979] build: use span-cloud-testing for integration tests (#1994) --- java-spanner-jdbc/.kokoro/build.sh | 2 ++ .../.kokoro/presubmit/integration.cfg | 15 ++------------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index f4ea82a431c1..236faa2ad059 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -76,6 +76,8 @@ integration) -DtrimStackTrace=false \ -Dclirr.skip=true \ -Denforcer.skip=true \ + -Dspanner.testenv.instance=projects/span-cloud-testing/instances/java-client-integration-test \ + -Dspanner.gce.config.project_id=span-cloud-testing \ -fae \ verify RETURN_CODE=$? diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg index 5864c603e5ad..929a8b3467ca 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -11,24 +11,13 @@ env_vars: { value: "integration" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "gcloud-devel" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "secret_manager/java-it-service-account" + value: "secret_manager/java-client-testing" } env_vars: { key: "SECRET_MANAGER_KEYS" - value: "java-it-service-account" + value: "java-client-testing" } From 3b2181409ff1a11f35322482fb64fc4e01a6aad2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 22 Apr 2025 15:00:36 +0100 Subject: [PATCH 1617/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.46.0 (#1992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.46.0 * chore: reformat code --------- Co-authored-by: Knut Olav Løite --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- .../.kokoro/presubmit/graalvm-native-17.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- .../com/google/cloud/spanner/jdbc/JdbcStatement.java | 6 ++---- .../cloud/spanner/jdbc/AllTypesMockServerTest.java | 3 +-- .../google/cloud/spanner/jdbc/ExecuteMockServerTest.java | 9 +++------ .../cloud/spanner/jdbc/MultiplexedSessionsTest.java | 6 ++---- 10 files changed, 14 insertions(+), 22 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 6b4a8e5c55ae..fdc1fa6a6f08 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.45.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg index 07ae08a9807a..ed336a5a81ba 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.45.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg index fb1979a33bab..4477760a676f 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.45.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 78173b9149a0..eaf6acd0f2e3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.45.1 + 3.46.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 5e35b63175d1..49ad5f842223 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.45.1 + 3.46.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e1919e95b289..082c1993ed2e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.45.1 + 3.46.0 diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java index 5d8dfd9ee26b..0a764b351b4d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java @@ -201,15 +201,13 @@ Statement addReturningToStatement(Statement statement, ImmutableList gen if (generatedKeysColumns.size() == 1 && ALL_COLUMNS.get(0).equals(generatedKeysColumns.get(0))) { // Add a 'THEN RETURN/RETURNING *' clause to the statement. - return statement - .toBuilder() + 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() + return statement.toBuilder() .replace( generatedKeysColumns.stream() .map(this::quoteColumn) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java index cf4b7dfb589f..c3848933953f 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java @@ -144,8 +144,7 @@ public void testInsertAllTypes() { if (dialect == Dialect.POSTGRESQL) { Statement insertStatement = createInsertStatement(dialect); insertStatement = - insertStatement - .toBuilder() + insertStatement.toBuilder() .replace(insertStatement.getSql().replaceAll("@p", "\\$")) .bind("p16") .to( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java index 0da18144426a..c226bd6731eb 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java @@ -176,22 +176,19 @@ public void setupResults() { mockSpanner.putStatementResult( StatementResult.query( com.google.cloud.spanner.Statement.of(dmlReturning), - resultSet - .toBuilder() + 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() + 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() + returnIdResultSet.toBuilder() .setStats( ResultSetStats.newBuilder().setRowCountExact(LARGE_UPDATE_COUNT).build()) .build())); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java index b7b2d2869a04..17183241479b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsTest.java @@ -167,15 +167,13 @@ public void setupResults() { mockSpanner.putStatementResult( StatementResult.query( com.google.cloud.spanner.Statement.of(dmlReturning), - resultSet - .toBuilder() + 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() + returnIdResultSet.toBuilder() .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) .build())); } From 77c89949d093250ff9da00ea0e3b4e08e98eddbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 22 Apr 2025 16:24:32 +0200 Subject: [PATCH 1618/1979] test: test cause of BatchUpdateException (#1974) --- .../spanner/jdbc/BatchMockServerTest.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BatchMockServerTest.java diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BatchMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BatchMockServerTest.java new file mode 100644 index 000000000000..a6fb7a72dba3 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/BatchMockServerTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2025 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 com.google.cloud.spanner.jdbc.FallbackToPartitionedDMLMockServerTest.createTransactionMutationLimitExceededException; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; + +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.cloud.spanner.SpannerBatchUpdateException; +import com.google.cloud.spanner.TransactionMutationLimitExceededException; +import com.google.cloud.spanner.connection.AbstractMockServerTest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import java.sql.BatchUpdateException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class BatchMockServerTest extends AbstractMockServerTest { + private static final String NON_PARAMETERIZED_INSERT = + "insert into foo (id, value) values (1, 'One')"; + private static final String NON_PARAMETERIZED_UPDATE = "update foo set value='Zero' where id=0"; + private static final String LARGE_UPDATE = "update foo set value='Zero' where true"; + + @BeforeClass + public static void setup() { + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.of(NON_PARAMETERIZED_INSERT), 1L)); + mockSpanner.putStatementResult( + StatementResult.update( + com.google.cloud.spanner.Statement.of(NON_PARAMETERIZED_UPDATE), 1L)); + mockSpanner.putStatementResult( + StatementResult.exception( + com.google.cloud.spanner.Statement.of(LARGE_UPDATE), + createTransactionMutationLimitExceededException())); + } + + @After + public void clearRequests() { + mockSpanner.clearRequests(); + } + + @Test + public void testStatementBatch() throws SQLException { + try (Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + statement.addBatch(NON_PARAMETERIZED_INSERT); + statement.addBatch(NON_PARAMETERIZED_UPDATE); + assertArrayEquals(new int[] {1, 1}, statement.executeBatch()); + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testStatementBatchFailsDueToMutationLimit() throws SQLException { + try (Connection connection = createJdbcConnection()) { + try (Statement statement = connection.createStatement()) { + statement.addBatch(NON_PARAMETERIZED_INSERT); + statement.addBatch(LARGE_UPDATE); + + BatchUpdateException batchUpdateException = + assertThrows(BatchUpdateException.class, statement::executeBatch); + assertNotNull(batchUpdateException.getCause()); + assertEquals(SpannerBatchUpdateException.class, batchUpdateException.getCause().getClass()); + assertNotNull(batchUpdateException.getCause().getCause()); + assertEquals( + TransactionMutationLimitExceededException.class, + batchUpdateException.getCause().getCause().getClass()); + } + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } +} From 9a3dd44c73bd1a23d811203c9b9b8217950d13a9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 22 Apr 2025 16:10:25 +0100 Subject: [PATCH 1619/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.5 (#1995) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 05699cd74fca..9514cb50b242 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.4 + 2024.1.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index 1042f63401c5..c55f5b9547dc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.4 + 2024.1.5 import pom From 561216c1faa356914fb0761fe2ed4211b52a39dd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 22 Apr 2025 15:48:21 +0000 Subject: [PATCH 1620/1979] chore(main): release 2.29.0 (#1972) :robot: I have created a release *beep* *boop* --- ## [2.29.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.28.0...v2.29.0) (2025-04-22) ### Features * Support isolation level repeatable read ([#1973](https://togithub.com/googleapis/java-spanner-jdbc/issues/1973)) ([ea51d68](https://togithub.com/googleapis/java-spanner-jdbc/commit/ea51d688ef1eba8d49b9833c8755d00f05783a2b)) ### Dependencies * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.90.0 ([#1970](https://togithub.com/googleapis/java-spanner-jdbc/issues/1970)) ([223f526](https://togithub.com/googleapis/java-spanner-jdbc/commit/223f5266c19fea6c1b247ab01635febc2dbcd5d5)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.91.1 ([#1993](https://togithub.com/googleapis/java-spanner-jdbc/issues/1993)) ([cb6b529](https://togithub.com/googleapis/java-spanner-jdbc/commit/cb6b529c7989234ffbde3cf427f535abb64f07f5)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.46.0 ([#1992](https://togithub.com/googleapis/java-spanner-jdbc/issues/1992)) ([3b21814](https://togithub.com/googleapis/java-spanner-jdbc/commit/3b2181409ff1a11f35322482fb64fc4e01a6aad2)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.49.0 ([#1982](https://togithub.com/googleapis/java-spanner-jdbc/issues/1982)) ([ef4e7c3](https://togithub.com/googleapis/java-spanner-jdbc/commit/ef4e7c3cd32f6fd1438081c3fb893b75a9fe8e96)) * Update dependency org.springframework.data:spring-data-bom to v2024.1.5 ([#1995](https://togithub.com/googleapis/java-spanner-jdbc/issues/1995)) ([9a3dd44](https://togithub.com/googleapis/java-spanner-jdbc/commit/9a3dd44c73bd1a23d811203c9b9b8217950d13a9)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 16 ++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4ef8ddf1fc9e..711575150f6a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.29.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.28.0...v2.29.0) (2025-04-22) + + +### Features + +* Support isolation level repeatable read ([#1973](https://github.com/googleapis/java-spanner-jdbc/issues/1973)) ([010a502](https://github.com/googleapis/java-spanner-jdbc/commit/010a502310db88f8c676960c641a7e9a6581bf11)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.90.0 ([#1970](https://github.com/googleapis/java-spanner-jdbc/issues/1970)) ([7153c39](https://github.com/googleapis/java-spanner-jdbc/commit/7153c39464fd9b83609bb7cc2ada5c0f9aab3af8)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.91.1 ([#1993](https://github.com/googleapis/java-spanner-jdbc/issues/1993)) ([97d4840](https://github.com/googleapis/java-spanner-jdbc/commit/97d4840bd3e7cee7f1ddb9b26f3946f1b10ed894)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.46.0 ([#1992](https://github.com/googleapis/java-spanner-jdbc/issues/1992)) ([ea0b557](https://github.com/googleapis/java-spanner-jdbc/commit/ea0b55729d1bf9e8b5994758314841591ea0c883)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.49.0 ([#1982](https://github.com/googleapis/java-spanner-jdbc/issues/1982)) ([6b7ddf4](https://github.com/googleapis/java-spanner-jdbc/commit/6b7ddf4352d4db87eab6d9f3fd4945e5650e7798)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.5 ([#1995](https://github.com/googleapis/java-spanner-jdbc/issues/1995)) ([6bedf12](https://github.com/googleapis/java-spanner-jdbc/commit/6bedf124b9da233e6f4001dff2c1b56f0249aaad)) + ## [2.28.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.27.1...v2.28.0) (2025-03-21) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 53eaa14087d2..0ed64c5717d3 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.28.0 + 2.29.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.28.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.29.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.28.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.29.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index eaf6acd0f2e3..2b5a38a571b0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.28.1-SNAPSHOT + 2.29.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ca21dc659d63..a8ad559b30ac 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.28.1-SNAPSHOT + 2.29.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index fc40cb452b34..638e723bb87c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.28.0:2.28.1-SNAPSHOT +google-cloud-spanner-jdbc:2.29.0:2.29.0 From a0681bf8a2ca71687d43f1a84adc5dd0d5f67a82 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 11:11:49 +0200 Subject: [PATCH 1621/1979] chore(main): release 2.29.1-SNAPSHOT (#1996) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2b5a38a571b0..7b77128771e5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.29.0 + 2.29.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a8ad559b30ac..0b7b264ecd04 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.0 + 2.29.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 638e723bb87c..6b0586b71e97 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.29.0:2.29.0 +google-cloud-spanner-jdbc:2.29.0:2.29.1-SNAPSHOT From 7e6388bad4a09b97d5106caa49d591c56e060021 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Apr 2025 10:12:07 +0100 Subject: [PATCH 1622/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.29.0 (#1997) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 86d3c5fb49f4..2fcfba250f14 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.28.0 + 2.29.0 From 2828408550072027c2d90cae4ffd18805821f0ce Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Fri, 25 Apr 2025 01:04:15 -0400 Subject: [PATCH 1623/1979] build: introduce testing infra for GraalVM "C" (#1991) * build: introduce testing infra for GraalVM "C" * chore: update versions to the latest * test: try disable strict heap option * chore: use strict-image-heap only in image A * chore: remove custom flag to config behavior * chore: start emulator on all graalvm jobs * chore: fix commented out lines * chore: remove commented code --- .../.github/sync-repo-settings.yaml | 6 ++-- java-spanner-jdbc/.kokoro/build.sh | 9 ++--- .../.kokoro/presubmit/graalvm-native-a.cfg | 33 +++++++++++++++++++ ...raalvm-native.cfg => graalvm-native-b.cfg} | 4 +-- ...lvm-native-17.cfg => graalvm-native-c.cfg} | 4 +-- .../native-image.properties | 2 +- 6 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg rename java-spanner-jdbc/.kokoro/presubmit/{graalvm-native.cfg => graalvm-native-b.cfg} (97%) rename java-spanner-jdbc/.kokoro/presubmit/{graalvm-native-17.cfg => graalvm-native-c.cfg} (94%) diff --git a/java-spanner-jdbc/.github/sync-repo-settings.yaml b/java-spanner-jdbc/.github/sync-repo-settings.yaml index 7f0d9f2f041d..12478c8b245f 100644 --- a/java-spanner-jdbc/.github/sync-repo-settings.yaml +++ b/java-spanner-jdbc/.github/sync-repo-settings.yaml @@ -36,9 +36,9 @@ branchProtectionRules: - "units (11)" - "Kokoro - Test: Integration" - "cla/google" - - 'Kokoro - Test: Java GraalVM Native Image' - - 'Kokoro - Test: Java 17 GraalVM Native Image' - - javadoc + - 'Kokoro - Test: Java GraalVM Native Image A' + - 'Kokoro - Test: Java GraalVM Native Image B' + - 'Kokoro - Test: Java GraalVM Native Image C' - unmanaged_dependency_check # Identifies the protection rule pattern. Name of the branch to be protected. # Defaults to `main` diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 236faa2ad059..502fb4fd49d3 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -45,7 +45,7 @@ fi # Start the Spanner emulator if the environment variable for it has been set. # TODO: Change if statement once the env var can be set in the config. #if [[ ! -z "${SPANNER_EMULATOR_HOST}" ]]; then -if [[ "$JOB_TYPE" == "graalvm" ]] || [[ "$JOB_TYPE" == "graalvm17" ]]; then +if [[ "$JOB_TYPE" =~ ^graalvm ]]; then echo "Starting emulator" export SPANNER_EMULATOR_HOST=localhost:9010 docker pull gcr.io/cloud-spanner-emulator/emulator @@ -115,9 +115,10 @@ graalvm) mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; -graalvm17) - # Run Unit and Integration Tests with Native Image. - mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" +graalvmA) + # Run Unit and Integration Tests with Native Image A. + + NATIVE_IMAGE_OPTIONS="--strict-image-heap" mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Penable-integration-tests test "-Dtest=com.google.cloud.spanner.jdbc.it.**" RETURN_CODE=$? ;; samples) diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg new file mode 100644 index 000000000000..55d6ffb845f7 --- /dev/null +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -0,0 +1,33 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.2" +} + +env_vars: { + key: "JOB_TYPE" + value: "graalvmA" +} + +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_APPLICATION_CREDENTIALS" + value: "secret_manager/java-it-service-account" +} + +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "java-it-service-account" +} diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg similarity index 97% rename from java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg rename to java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 4477760a676f..666fed5370ae 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.2" } env_vars: { @@ -30,4 +30,4 @@ env_vars: { env_vars: { key: "SECRET_MANAGER_KEYS" value: "java-it-service-account" -} +} \ No newline at end of file diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg similarity index 94% rename from java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg rename to java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index ed336a5a81ba..4c404c2549b1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-17.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,12 +3,12 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.46.2" } env_vars: { key: "JOB_TYPE" - value: "graalvm17" + value: "graalvm" } # TODO: remove this after we've migrated all tests and scripts diff --git a/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties b/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties index 714d90fb1510..e686eeb6ef16 100644 --- a/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties +++ b/java-spanner-jdbc/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner-jdbc/native-image.properties @@ -1 +1 @@ -Args=--strict-image-heap +Args=--initialize-at-build-time=com.google.cloud.spanner.jdbc.it From 5be5ffc352f19d5696342d4abc7c675d91320422 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 10:27:04 +0100 Subject: [PATCH 1624/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.46.2 (#2014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.46.2 * test: use DST-aware offset in test --------- Co-authored-by: Knut Olav Løite --- .../workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- .../jdbc/it/ITJdbcPreparedStatementTest.java | 30 ++++++++++--------- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index fdc1fa6a6f08..e9e27d453b27 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.2 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7b77128771e5..683954fd9e89 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.46.0 + 3.46.2 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 49ad5f842223..b9158a36b67c 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.46.0 + 3.46.2 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 082c1993ed2e..8c15300cf086 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.46.0 + 3.46.2 diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java index 99ee0016516c..0d70c699487a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPreparedStatementTest.java @@ -650,9 +650,6 @@ public void test03_Dates() throws SQLException { @Test public void test04_Timestamps() throws SQLException { - assumeFalse( - "Timestamp type is not supported on POSTGRESQL dialect", - dialect.dialect == Dialect.POSTGRESQL); List expectedValues = new ArrayList<>(); expectedValues.add("2008-01-01 10:00:00"); expectedValues.add("2000-01-01 00:00:00"); @@ -711,8 +708,16 @@ public void test04_Timestamps() throws SQLException { Types.TIMESTAMP, Types.TIMESTAMP, Types.ARRAY), - ImmutableList.of( - "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), + dialect.dialect == Dialect.POSTGRESQL + ? ImmutableList.of( + "bigint", + "bigint", + "date", + "timestamp with time zone", + "timestamp with time zone", + "bigint[]") + : ImmutableList.of( + "INT64", "INT64", "DATE", "TIMESTAMP", "TIMESTAMP", "ARRAY"), ImmutableList.of( Long.class, Long.class, @@ -743,10 +748,7 @@ public void test04_Timestamps() throws SQLException { Timestamp inDefaultTZ = rs.getTimestamp(4); assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); // Then get it in the test timezone. - if (testCalendar != null - && !System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("oracle")) { + if (testCalendar != null) { Timestamp inOtherTZ = rs.getTimestamp(4, testCalendar); assertEquals( "Timezone: " @@ -759,7 +761,8 @@ public void test04_Timestamps() throws SQLException { + System.getProperty("java.vm.name") + ", vendor=" + System.getProperty("java.vendor"), - testTimestamp.getTime() + testCalendar.getTimeZone().getRawOffset(), + testTimestamp.getTime() + + testCalendar.getTimeZone().getOffset(inDefaultTZ.getTime()), inOtherTZ.getTime()); } @@ -768,9 +771,7 @@ public void test04_Timestamps() throws SQLException { inDefaultTZ = rs.getTimestamp(5); if (testCalendar == null) { assertEquals(testTimestamp.getTime(), inDefaultTZ.getTime()); - } else if (!System.getProperty("java.vm.name", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("graalvm") - && !System.getProperty("java.vendor", "").toLowerCase().contains("oracle")) { + } else { assertEquals( "Timezone: " + testCalendar @@ -782,7 +783,8 @@ public void test04_Timestamps() throws SQLException { + System.getProperty("java.vm.name") + ", vendor=" + System.getProperty("java.vendor"), - testTimestamp.getTime() - testCalendar.getTimeZone().getRawOffset(), + testTimestamp.getTime() + - testCalendar.getTimeZone().getOffset(inDefaultTZ.getTime()), inDefaultTZ.getTime()); } // Then get it in the test timezone. From e1a5f5f6877becaf2dc90917d739df9291b5449d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 11:30:04 +0100 Subject: [PATCH 1625/1979] deps: update dependency org.testcontainers:testcontainers to v1.21.0 (#2015) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 683954fd9e89..271aba8c7460 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.20.6 + 1.21.0 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index b9158a36b67c..038515b4de75 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.20.6 + 1.21.0 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 8c15300cf086..392436b2d2d4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.20.6 + 1.21.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index 9514cb50b242..ac2262b5687b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.20.6 + 1.21.0 test From c7a4c1d191b2adf77940279917a645f7109a185c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 11:54:42 +0100 Subject: [PATCH 1626/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.21.0 (#2016) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index c55f5b9547dc..e29ca4486389 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.20.6 + 1.21.0 import pom From 6b4fe7982394c124cdde1ad409938fb21e107450 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 11:54:53 +0100 Subject: [PATCH 1627/1979] deps: update dependency org.springframework.boot:spring-boot to v3.4.5 (#2017) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 038515b4de75..d0097c149aab 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.4 + 3.4.5 test From 86a120c4c88ed39fe9bca09436d54dd6f386df1c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 11:55:30 +0100 Subject: [PATCH 1628/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.5 (#2019) --- java-spanner-jdbc/samples/spring-data-mybatis/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml index e29ca4486389..80ac5eb9a34b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.4 + 3.4.5 From c2bb00a040e5a85ccefc28478569159fcd6f2c10 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 11:55:56 +0100 Subject: [PATCH 1629/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.0 (#2020) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d0097c149aab..5aa91d099b01 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.18.3 + 2.19.0 From 883ad7abfbe5a1ed0643d329f7c2e0bf913d560a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 25 Apr 2025 13:28:57 +0100 Subject: [PATCH 1630/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.5 (#2018) --- java-spanner-jdbc/samples/spring-data-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml index ac2262b5687b..032ad9fe0b80 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.4 + 3.4.5 From 10be7636871fd1c89051a8c495e52612589c5f7e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 17:14:56 +0200 Subject: [PATCH 1631/1979] chore(main): release 2.29.1 (#2021) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 711575150f6a..882dc0656929 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.29.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.29.0...v2.29.1) (2025-04-25) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.0 ([#2020](https://github.com/googleapis/java-spanner-jdbc/issues/2020)) ([0d4a663](https://github.com/googleapis/java-spanner-jdbc/commit/0d4a66366ca0e1d6849c8886a5875581473e1ffe)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.46.2 ([#2014](https://github.com/googleapis/java-spanner-jdbc/issues/2014)) ([4775d30](https://github.com/googleapis/java-spanner-jdbc/commit/4775d30b9e1448a4381545f84dae36b8dae4ec0e)) +* Update dependency org.springframework.boot:spring-boot to v3.4.5 ([#2017](https://github.com/googleapis/java-spanner-jdbc/issues/2017)) ([33e6f08](https://github.com/googleapis/java-spanner-jdbc/commit/33e6f08274612a1369aad799539f85fd43ceb93b)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.4.5 ([#2018](https://github.com/googleapis/java-spanner-jdbc/issues/2018)) ([9592099](https://github.com/googleapis/java-spanner-jdbc/commit/9592099ed5c7c1696186a34690cae3bf5a724e4f)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.4.5 ([#2019](https://github.com/googleapis/java-spanner-jdbc/issues/2019)) ([c6cf077](https://github.com/googleapis/java-spanner-jdbc/commit/c6cf077fc6bae591deed6d75ef97e5524fcffcbc)) +* Update dependency org.testcontainers:testcontainers to v1.21.0 ([#2015](https://github.com/googleapis/java-spanner-jdbc/issues/2015)) ([22c59bc](https://github.com/googleapis/java-spanner-jdbc/commit/22c59bc09f8b9b863e2e86d976e514922152c6bc)) +* Update dependency org.testcontainers:testcontainers-bom to v1.21.0 ([#2016](https://github.com/googleapis/java-spanner-jdbc/issues/2016)) ([5eab2e7](https://github.com/googleapis/java-spanner-jdbc/commit/5eab2e7b2628adcee9405da425c1ad5d3c89ef3e)) + ## [2.29.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.28.0...v2.29.0) (2025-04-22) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0ed64c5717d3..c2c8c96acb39 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.29.0 + 2.29.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.29.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.29.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.29.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.29.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 271aba8c7460..ff0e25ff309c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.29.1-SNAPSHOT + 2.29.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0b7b264ecd04..b5d9010831c0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.1-SNAPSHOT + 2.29.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 6b0586b71e97..9ebcf9ea5c9c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.29.0:2.29.1-SNAPSHOT +google-cloud-spanner-jdbc:2.29.1:2.29.1 From 8c6717250abe81318bb6d3467f070689e4014584 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 16:46:22 +0000 Subject: [PATCH 1632/1979] chore(main): release 2.29.2-SNAPSHOT (#2024) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ff0e25ff309c..01c6d79db00f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.29.1 + 2.29.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b5d9010831c0..6ed736fdd018 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.1 + 2.29.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 9ebcf9ea5c9c..cb7af1e689e5 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.29.1:2.29.1 +google-cloud-spanner-jdbc:2.29.1:2.29.2-SNAPSHOT From d04e8d2fc137f9124c21ba07f202e30dcd7b94bc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 29 Apr 2025 07:58:33 +0200 Subject: [PATCH 1633/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.29.1 (#2025) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 2fcfba250f14..225f089d9613 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.0 + 2.29.1 From 787096e91b60729074ace2844f60e417c4b3e653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 29 Apr 2025 12:11:20 +0200 Subject: [PATCH 1634/1979] docs: add sample for MyBatis with GoogleSQL (#2026) --- .../workflows/spring-data-mybatis-sample.yaml | 7 +- .../samples/spring-data-mybatis/README.md | 105 +- .../spring-data-mybatis/googlesql/README.md | 52 + .../spring-data-mybatis/googlesql/pom.xml | 130 +++ .../cloud/spanner/sample/Application.java | 161 +++ .../cloud/spanner/sample/DatabaseSeeder.java | 316 ++++++ .../spanner/sample/EmulatorInitializer.java | 57 + .../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 | 73 ++ .../spanner/sample/mappers/TrackMapper.java | 37 + .../spanner/sample/mappers/VenueMapper.java | 29 + .../spanner/sample/service/AlbumService.java | 49 + .../spanner/sample/service/SingerService.java | 67 ++ .../src/main/resources/application.properties | 36 + .../src/main/resources/create_schema.sql | 59 + .../src/main/resources/drop_schema.sql | 0 .../sample/ApplicationEmulatorTest.java | 42 + .../cloud/spanner/sample/ApplicationTest.java | 1001 +++++++++++++++++ .../spring-data-mybatis/postgresql/README.md | 100 ++ .../{ => postgresql}/pom.xml | 2 +- .../cloud/spanner/sample/Application.java | 0 .../cloud/spanner/sample/DatabaseSeeder.java | 0 .../spanner/sample/EmulatorInitializer.java | 0 .../spanner/sample/JdbcConfiguration.java | 0 .../sample/entities/AbstractEntity.java | 0 .../cloud/spanner/sample/entities/Album.java | 0 .../spanner/sample/entities/Concert.java | 0 .../cloud/spanner/sample/entities/Singer.java | 0 .../cloud/spanner/sample/entities/Track.java | 0 .../cloud/spanner/sample/entities/Venue.java | 0 .../spanner/sample/mappers/AlbumMapper.java | 0 .../spanner/sample/mappers/ConcertMapper.java | 0 .../spanner/sample/mappers/SingerMapper.java | 0 .../spanner/sample/mappers/TrackMapper.java | 0 .../spanner/sample/mappers/VenueMapper.java | 0 .../spanner/sample/service/AlbumService.java | 0 .../spanner/sample/service/SingerService.java | 0 .../main/resources/application-cs.properties | 0 .../main/resources/application-pg.properties | 0 .../src/main/resources/application.properties | 0 .../src/main/resources/create_schema.sql | 0 .../src/main/resources/drop_schema.sql | 5 + .../sample/ApplicationEmulatorTest.java | 0 .../cloud/spanner/sample/ApplicationTest.java | 0 51 files changed, 2721 insertions(+), 101 deletions(-) create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/README.md create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/create_schema.sql rename java-spanner-jdbc/samples/spring-data-mybatis/{ => googlesql}/src/main/resources/drop_schema.sql (100%) create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/postgresql/README.md rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/pom.xml (97%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/Application.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Album.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Track.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/resources/application-cs.properties (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/resources/application-pg.properties (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/resources/application.properties (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/main/resources/create_schema.sql (100%) create mode 100644 java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/drop_schema.sql rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java (100%) rename java-spanner-jdbc/samples/spring-data-mybatis/{ => postgresql}/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java (100%) diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index b19a17290723..e7dfbc7b36aa 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -25,6 +25,9 @@ jobs: with: distribution: temurin java-version: 17 - - name: Run tests + - name: Run GoogleSQL sample tests run: mvn test - working-directory: samples/spring-data-mybatis + working-directory: samples/spring-data-mybatis/googlesql + - name: Run PostgreSQL sample tests + run: mvn test + working-directory: samples/spring-data-mybatis/postgresql diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/README.md b/java-spanner-jdbc/samples/spring-data-mybatis/README.md index 61dc46f48eeb..04e1b0950b8f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/README.md +++ b/java-spanner-jdbc/samples/spring-data-mybatis/README.md @@ -1,100 +1,9 @@ -# Spring Data MyBatis Sample Application with Cloud Spanner PostgreSQL +# Spring Data MyBatis -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. +This directory contains two sample applications for using Spring Data MyBatis +with the Spanner JDBC driver. -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. -4. How to use the Spanner Emulator for development in combination with Spring Data. - -__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. -2. The sample by default starts an instance of the Spanner Emulator together with the application and - runs the application against the emulator. -3. Modify the default profile in the [application.properties](src/main/resources/application.properties) - file to run the sample on an open-source PostgreSQL database. -4. 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. -5. 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. -* [EmulatorInitializer.java](src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java): - This ApplicationListener automatically starts the Spanner emulator as a Docker container if the - sample has been configured to run on the emulator. -* [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. +- [GoogleSQL](googlesql): This sample uses the Spanner GoogleSQL dialect. +- [PostgreSQL](postgresql): This sample uses the Spanner PostgreSQL dialect and the Spanner JDBC + driver. It does not use PGAdapter. The sample application can also be configured to run on open + source PostgreSQL, and shows how a portable application be developed using this setup. diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/README.md b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/README.md new file mode 100644 index 000000000000..7badfb6980ff --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/README.md @@ -0,0 +1,52 @@ +# Spring Data MyBatis Sample Application with Spanner GoogleSQL + +This sample application shows how to develop applications using Spring Data MyBatis in +combination with Spanner GoogleSQL. + +This sample shows: + +1. How to use Spring Data MyBatis with a Spanner GoogleSQL database. +2. How to use bit-reversed identity columns to automatically generate primary key values for entities. +3. How to set the transaction isolation level that is used by the Spanner JDBC driver. +4. How to use the Spanner Emulator for development in combination with Spring Data. + +## 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. + +### Running the Application + +1. The sample by default starts an instance of the Spanner Emulator together with the application and + runs the application against the emulator. +2. To run the sample on a real Spanner database, modify + [application.properties](src/main/resources/application.properties) and set the + `spanner.emulator` property to `false`. Modify the `spanner.project`, `spanner.instance`, and + `spanner.database` properties to point to an existing Spanner database. + The database must use the GoogleSQL 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. +* [EmulatorInitializer.java](src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java): + This ApplicationListener automatically starts the Spanner emulator as a Docker container if the + sample has been configured to run on the emulator. You can disable this with the `spanner.emulator` + property in `application.properties`. +* [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) identity column. [Bit-reversed sequential values](https://cloud.google.com/spanner/docs/schema-design#bit_reverse_primary_key) + are considered a good choice for primary keys in 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml new file mode 100644 index 000000000000..47fb7b0a452e --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -0,0 +1,130 @@ + + + 4.0.0 + + org.example + cloud-spanner-spring-data-mybatis-googlesql-example + 1.0-SNAPSHOT + + Sample application showing how to use Spring Data MyBatis with Spanner GoogleSQL. + + + org.springframework.boot + spring-boot-starter-parent + 3.4.5 + + + + 17 + 17 + 17 + UTF-8 + + + + + + org.springframework.data + spring-data-bom + 2024.1.5 + import + pom + + + com.google.cloud + libraries-bom + 26.59.0 + import + pom + + + org.testcontainers + testcontainers-bom + 1.21.0 + import + pom + + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.4 + + + org.mybatis.dynamic-sql + mybatis-dynamic-sql + 1.5.2 + + + + + + com.google.cloud + google-cloud-spanner + 6.91.1 + + + com.google.cloud + google-cloud-spanner-jdbc + 2.29.1 + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + + + + org.testcontainers + testcontainers + + + + com.google.collections + google-collections + 1.0 + + + + + com.google.cloud + google-cloud-spanner + 6.91.1 + test-jar + test + + + com.google.api + gax-grpc + testlib + test + + + junit + junit + 4.13.2 + + + + + + + com.spotify.fmt + fmt-maven-plugin + 2.25 + + + + format + + + + + + + diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java new file mode 100644 index 000000000000..cf9ab71d34b8 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java @@ -0,0 +1,161 @@ +/* + * Copyright 2025 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.connection.SpannerPool; +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 java.util.concurrent.ThreadLocalRandom; +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) { + // Start the Spanner emulator in a Docker container if the `spanner.auto_start_emulator` + // property has been set to true. If not, then this is a no-op. + EmulatorInitializer emulatorInitializer = new EmulatorInitializer(); + try { + SpringApplication application = new SpringApplication(Application.class); + application.addListeners(emulatorInitializer); + application.run(args).close(); + } finally { + SpannerPool.closeSpannerPool(); + emulatorInitializer.stopEmulator(); + } + } + + 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()); + } + + // Execute an insert-or-update for a Singer record. + // For this, we either get a random Singer from the database, or create a new Singer entity + // and assign it a random ID. + logger.info("Executing an insert-or-update statement for a Singer record"); + Singer singer; + if (ThreadLocalRandom.current().nextBoolean()) { + singer = singerMapper.getRandom(); + } else { + singer = new Singer(); + singer.setId(ThreadLocalRandom.current().nextLong()); + } + singer.setFirstName("Beatriz"); + singer.setLastName("Russel"); + singer.setActive(true); + // This executes an INSERT OR UPDATE statement. + singerMapper.insertOrUpdate(singer); + } +} diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java new file mode 100644 index 000000000000..73898784ef13 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java @@ -0,0 +1,316 @@ +/* + * Copyright 2025 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.collect.ImmutableList; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +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 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; + + public DatabaseSeeder(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = 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); + } + } + + /** Removes all empty statements in the DDL script. */ + private String[] updateDdlStatements(String[] statements) { + // 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 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 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 where true", + "delete from venues where true", + "delete from tracks where true", + "delete from albums where true", + "delete from singers where true"); + } + + /** 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()).setScale(9, RoundingMode.HALF_UP); + } + + /** 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java new file mode 100644 index 000000000000..6c6130be6928 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java @@ -0,0 +1,57 @@ +/* + * Copyright 2025 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 org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; + +public class EmulatorInitializer + implements ApplicationListener { + private GenericContainer emulator; + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + ConfigurableEnvironment environment = event.getEnvironment(); + boolean useEmulator = + Boolean.TRUE.equals(environment.getProperty("spanner.emulator", Boolean.class)); + boolean autoStartEmulator = + Boolean.TRUE.equals(environment.getProperty("spanner.auto_start_emulator", Boolean.class)); + if (!(useEmulator && autoStartEmulator)) { + return; + } + + emulator = + new GenericContainer<>(DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator")); + emulator.withImagePullPolicy(PullPolicy.alwaysPull()); + emulator.addExposedPort(9010); + emulator.setWaitStrategy(Wait.forListeningPorts(9010)); + emulator.start(); + + System.setProperty("spanner.endpoint", "//localhost:" + emulator.getMappedPort(9010)); + } + + public void stopEmulator() { + if (this.emulator != null) { + this.emulator.stop(); + } + } +} diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java new file mode 100644 index 000000000000..dcf64a22d6a5 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java @@ -0,0 +1,73 @@ +/* + * Copyright 2025 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) identity column. */ + 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java new file mode 100644 index 000000000000..9ea238506da2 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java @@ -0,0 +1,84 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java new file mode 100644 index 000000000000..ac13102afd98 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java @@ -0,0 +1,78 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java new file mode 100644 index 000000000000..b3f6d1c4f97d --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java @@ -0,0 +1,73 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java new file mode 100644 index 000000000000..8191c696c757 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java @@ -0,0 +1,66 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java new file mode 100644 index 000000000000..f5eb4443d4a6 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java @@ -0,0 +1,43 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java new file mode 100644 index 000000000000..f39b08a338dc --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java new file mode 100644 index 000000000000..1b52c603fd8d --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java @@ -0,0 +1,29 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java new file mode 100644 index 000000000000..65ddb72edc2e --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java @@ -0,0 +1,73 @@ +/* + * Copyright 2025 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 TABLESAMPLE RESERVOIR (1 ROWS)") + Singer getRandom(); + + @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); + + /** + * Executes an insert-or-update statement for a Singer record. Note that the id must have been set + * manually on the Singer entity before calling this method. The statement only returns the + * 'fullName' property, because the 'id' is already known. + */ + @Insert( + "INSERT OR UPDATE singers (id, first_name, last_name, active) " + + "VALUES (#{id}, #{firstName}, #{lastName}, #{active})") + @Options(useGeneratedKeys = true, keyProperty = "fullName") + int insertOrUpdate(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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java new file mode 100644 index 000000000000..729c56fa63d2 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java @@ -0,0 +1,37 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java new file mode 100644 index 000000000000..be220f867fe1 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java @@ -0,0 +1,29 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java new file mode 100644 index 000000000000..1a7e125f09e6 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java @@ -0,0 +1,49 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000000..c56893a1b75e --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java @@ -0,0 +1,67 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties new file mode 100644 index 000000000000..bbe258dbfaae --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties @@ -0,0 +1,36 @@ + +# 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 + +# The sample by default uses the Spanner emulator. +# Disable this flag to run the sample on a real Spanner instance. +spanner.emulator=true + +# The sample by default starts an emulator instance in Docker. +# Disable this flag to run the sample on an Emulator instance that +# you start manually, for example if you don't have Docker installed +# on your local machine. Keep the 'spanner.emulator=true' line above +# to connect to the emulator that you have started. +spanner.auto_start_emulator=true + +# Update these properties to match your project, instance, and database. +spanner.project=my-project +spanner.instance=my-instance +spanner.database=mybatis-sample + +# Sets the isolation level that will be used by default for read/write transactions. +# Spanner supports the isolation levels SERIALIZABLE and REPEATABLE READ. +spanner.default_isolation_level=REPEATABLE_READ + +spring.datasource.url=jdbc:cloudspanner:${spanner.endpoint}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database};default_isolation_level=${spanner.default_isolation_level};autoConfigEmulator=${spanner.emulator};${spanner.additional_properties} +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver + + +# These properties are only used for testing. + +# This property is automatically set to point to the Spanner emulator that is automatically +# started together with the application. It remains empty if the application is executed +# against a real Spanner instance. +spanner.endpoint= +spanner.additional_properties= diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/create_schema.sql new file mode 100644 index 000000000000..f54ef649222a --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/create_schema.sql @@ -0,0 +1,59 @@ + +-- This script creates the database schema for this sample application. +-- The script is executed by the DatabaseSeeder class. + +CREATE TABLE IF NOT EXISTS singers ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + first_name STRING(MAX), + last_name STRING(MAX), + full_name STRING(MAX) 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 BOOL DEFAULT (TRUE), + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +); + +CREATE TABLE IF NOT EXISTS albums ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + title STRING(MAX) NOT NULL, + marketing_budget NUMERIC, + release_date DATE, + cover_picture BYTES(MAX), + singer_id INT64 NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + CONSTRAINT fk_albums_singers FOREIGN KEY (singer_id) REFERENCES singers (id) +); + +CREATE TABLE IF NOT EXISTS tracks ( + id INT64 NOT NULL, + track_number INT64 NOT NULL, + title STRING(MAX) NOT NULL, + sample_rate FLOAT64 NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +) PRIMARY KEY (id, track_number), INTERLEAVE IN PARENT albums ON DELETE CASCADE +; + +CREATE TABLE IF NOT EXISTS venues ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + name STRING(MAX) NOT NULL, + description JSON NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +); + +CREATE TABLE IF NOT EXISTS concerts ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + venue_id INT64 NOT NULL, + singer_id INT64 NOT NULL, + name STRING(MAX) NOT NULL, + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP 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/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/drop_schema.sql similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/drop_schema.sql rename to java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/drop_schema.sql diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java new file mode 100644 index 000000000000..abdfdcdef7de --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2025 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 org.junit.Assume.assumeTrue; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.testcontainers.DockerClientFactory; + +@RunWith(JUnit4.class) +public class ApplicationEmulatorTest { + + @BeforeClass + public static void checkDocker() { + assumeTrue( + "Docker is required for this test", DockerClientFactory.instance().isDockerAvailable()); + } + + @Test + public void testRunApplicationOnEmulator() { + System.setProperty("spanner.emulator", "true"); + System.setProperty("spanner.auto_start_emulator", "true"); + Application.main(new String[] {}); + } +} diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java new file mode 100644 index 000000000000..ade5d85c6567 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -0,0 +1,1001 @@ +/* + * Copyright 2025 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.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.concurrent.ThreadLocalRandom; +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; + +@RunWith(JUnit4.class) +public class ApplicationTest extends AbstractMockServerTest { + + @BeforeClass + public static void setupQueryResults() { + // 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 where true"), 0L)); + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from venues where true"), 0L)); + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from tracks where true"), 0L)); + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from albums where true"), 0L)); + mockSpanner.putStatementResult( + StatementResult.update(Statement.of("delete from singers where true"), 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 (@p1, @p2)") + .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 (@p1, @p2, @p3, @p4, @p5)"), + 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 = @p1"), + 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 = @p1") + .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())); + } + int singerIndex = ThreadLocalRandom.current().nextInt(INITIAL_SINGERS.size()); + Singer randomSinger = INITIAL_SINGERS.get(singerIndex); + mockSpanner.putStatementResult( + StatementResult.query( + Statement.of("SELECT * FROM singers TABLESAMPLE RESERVOIR (1 ROWS)"), + 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(singerIndex + 1))) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues( + Value.newBuilder().setStringValue(randomSinger.getLastName()).build()) + .addValues( + Value.newBuilder() + .setStringValue( + randomSinger.getFirstName() + " " + randomSinger.getLastName()) + .build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues( + Value.newBuilder().setStringValue(randomSinger.getFirstName()).build()) + .build()) + .build())); + + mockSpanner.putStatementResult( + StatementResult.query( + Statement.newBuilder( + "INSERT INTO singers (first_name, last_name, active) VALUES (@p1, @p2, @p3)\n" + + "THEN RETURN *") + .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 (@p1, @p2, @p3, @p4, @p5)\n" + + "THEN RETURN *"), + 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 (@p1, @p2, @p3, @p4)\n" + + "THEN RETURN *"), + 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, @p1)") + .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())); + mockSpanner.putPartialStatementResult( + StatementResult.query( + Statement.of( + "INSERT OR UPDATE singers (id, first_name, last_name, active) VALUES (@p1, @p2, @p3, @p4)\n" + + "THEN RETURN *"), + 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(ThreadLocalRandom.current().nextLong())) + .build()) + .addValues(Value.newBuilder().setBoolValue(true).build()) + .addValues(Value.newBuilder().setStringValue("Russel").build()) + .addValues(Value.newBuilder().setStringValue("Beatriz Russel").build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) + .addValues(Value.newBuilder().setStringValue("Beatriz").build()) + .build()) + .setStats(ResultSetStats.newBuilder().setRowCountExact(1L).build()) + .build())); + } + } + + @Test + public void testRunApplication() { + System.setProperty("spanner.emulator", "false"); + System.setProperty("spanner.endpoint", "//localhost:" + getPort()); + System.setProperty("spanner.additional_properties", "usePlainText=true"); + Application.main(new String[] {}); + + assertEquals( + 39, + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() + .filter( + request -> + !request.getSql().equals("SELECT 1") + && !request + .getSql() + .equals( + "SELECT * FROM singers ORDER BY sha256(last_name::bytea) LIMIT 1")) + .count()); + assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(6, mockSpanner.countRequestsOfType(CommitRequest.class)); + + // Verify that the service methods use transactions. + String insertSingerSql = + "INSERT INTO singers (first_name, last_name, active) VALUES (@p1, @p2, @p3)\nTHEN RETURN *"; + 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 (@p1, @p2, @p3, @p4, @p5)\nTHEN RETURN *"; + 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 (@p1, @p2, @p3, @p4)\nTHEN RETURN *"; + 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, @p1)"; + 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/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/README.md b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/README.md new file mode 100644 index 000000000000..61dc46f48eeb --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/README.md @@ -0,0 +1,100 @@ +# 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. +4. How to use the Spanner Emulator for development in combination with Spring Data. + +__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. +2. The sample by default starts an instance of the Spanner Emulator together with the application and + runs the application against the emulator. +3. Modify the default profile in the [application.properties](src/main/resources/application.properties) + file to run the sample on an open-source PostgreSQL database. +4. 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. +5. 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. +* [EmulatorInitializer.java](src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java): + This ApplicationListener automatically starts the Spanner emulator as a Docker container if the + sample has been configured to run on the emulator. +* [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/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml similarity index 97% rename from java-spanner-jdbc/samples/spring-data-mybatis/pom.xml rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 80ac5eb9a34b..ccc3499b716e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.example - cloud-spanner-spring-data-mybatis-example + cloud-spanner-spring-data-mybatis-postgresql-example 1.0-SNAPSHOT Sample application showing how to use Spring Data MyBatis with Cloud Spanner PostgreSQL. diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/Application.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/Application.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/Application.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Album.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Track.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/AlbumMapper.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/ConcertMapper.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/SingerMapper.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/TrackMapper.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/mappers/VenueMapper.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/service/AlbumService.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application-cs.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-cs.properties rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application-cs.properties diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application-pg.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application-pg.properties rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application-pg.properties diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/application.properties rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/application.properties diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/create_schema.sql similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/main/resources/create_schema.sql rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/create_schema.sql diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/main/resources/drop_schema.sql new file mode 100644 index 000000000000..23e7b65d3bb1 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/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/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-mybatis/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java rename to java-spanner-jdbc/samples/spring-data-mybatis/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java From a1b033f77abb34e6a12fcd91a92c781fce2f154c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 29 Apr 2025 12:22:25 +0200 Subject: [PATCH 1635/1979] docs: add sample for Spring Data JDBC with GoogleSQL (#2027) --- .../workflows/spring-data-jdbc-sample.yaml | 7 +- .../samples/spring-data-jdbc/README.md | 96 +---- .../spring-data-jdbc/googlesql/README.md | 57 +++ .../spring-data-jdbc/googlesql/pom.xml | 138 +++++++ .../cloud/spanner/sample/Application.java | 269 +++++++++++++ .../cloud/spanner/sample/DatabaseSeeder.java | 353 ++++++++++++++++++ .../spanner/sample/EmulatorInitializer.java | 57 +++ .../spanner/sample/JdbcConfiguration.java | 74 ++++ .../sample/OpenTelemetryConfiguration.java | 121 ++++++ .../cloud/spanner/sample/SpannerDialect.java | 139 +++++++ .../sample/SpannerDialectProvider.java | 46 +++ .../sample/entities/AbstractEntity.java | 80 ++++ .../cloud/spanner/sample/entities/Album.java | 88 +++++ .../spanner/sample/entities/Concert.java | 84 +++++ .../cloud/spanner/sample/entities/Singer.java | 75 ++++ .../cloud/spanner/sample/entities/Track.java | 88 +++++ .../cloud/spanner/sample/entities/Venue.java | 50 +++ .../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/META-INF/spring.factories | 1 + .../src/main/resources/application.properties | 36 ++ .../src/main/resources/create_schema.sql | 59 +++ .../src/main/resources/drop_schema.sql | 0 .../sample/ApplicationEmulatorTest.java | 69 ++++ .../spring-data-jdbc/postgresql/README.md | 95 +++++ .../spring-data-jdbc/{ => postgresql}/pom.xml | 2 +- .../cloud/spanner/sample/Application.java | 0 .../cloud/spanner/sample/DatabaseSeeder.java | 0 .../spanner/sample/JdbcConfiguration.java | 0 .../sample/OpenTelemetryConfiguration.java | 2 + .../sample/entities/AbstractEntity.java | 0 .../cloud/spanner/sample/entities/Album.java | 0 .../spanner/sample/entities/Concert.java | 0 .../cloud/spanner/sample/entities/Singer.java | 0 .../cloud/spanner/sample/entities/Track.java | 0 .../cloud/spanner/sample/entities/Venue.java | 0 .../sample/repositories/AlbumRepository.java | 0 .../repositories/ConcertRepository.java | 0 .../sample/repositories/SingerRepository.java | 0 .../sample/repositories/TrackRepository.java | 0 .../sample/repositories/VenueRepository.java | 0 .../spanner/sample/service/SingerService.java | 0 .../main/resources/application-cs.properties | 0 .../main/resources/application-pg.properties | 0 .../src/main/resources/application.properties | 0 .../src/main/resources/create_schema.sql | 0 .../src/main/resources/drop_schema.sql | 5 + .../sample/ApplicationEmulatorTest.java | 0 .../cloud/spanner/sample/ApplicationTest.java | 0 .../test/resources/application-cs.properties | 0 .../test/resources/application-pg.properties | 0 .../src/test/resources/application.properties | 0 56 files changed, 2214 insertions(+), 90 deletions(-) create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/README.md create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/META-INF/spring.factories create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/create_schema.sql rename java-spanner-jdbc/samples/spring-data-jdbc/{ => googlesql}/src/main/resources/drop_schema.sql (100%) create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/postgresql/README.md rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/pom.xml (98%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/Application.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java (97%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Album.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Track.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/resources/application-cs.properties (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/resources/application-pg.properties (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/resources/application.properties (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/main/resources/create_schema.sql (100%) create mode 100644 java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/drop_schema.sql rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/test/resources/application-cs.properties (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/test/resources/application-pg.properties (100%) rename java-spanner-jdbc/samples/spring-data-jdbc/{ => postgresql}/src/test/resources/application.properties (100%) diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index 0185a2905d78..7d5b4ea41334 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -25,6 +25,9 @@ jobs: with: distribution: temurin java-version: 17 - - name: Run tests + - name: Run tests on GoogleSQL run: mvn test - working-directory: samples/spring-data-jdbc + working-directory: samples/spring-data-jdbc/googlesql + - name: Run tests on PostgreSQL + run: mvn test + working-directory: samples/spring-data-jdbc/postgresql diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/README.md b/java-spanner-jdbc/samples/spring-data-jdbc/README.md index da1d69532e84..4b6dbcc57b91 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/README.md +++ b/java-spanner-jdbc/samples/spring-data-jdbc/README.md @@ -1,95 +1,17 @@ -# Spring Data JDBC Sample Application with Cloud Spanner PostgreSQL +# Spring Data JDBC -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 +This directory contains two sample applications for using Spring Data JDBC +with the Spanner JDBC driver. [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. +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. - +- [GoogleSQL](googlesql): This sample uses the Spanner GoogleSQL dialect. +- [PostgreSQL](postgresql): This sample uses the Spanner PostgreSQL dialect and the Spanner JDBC + driver. It does not use PGAdapter. The sample application can also be configured to run on open + source PostgreSQL, and shows how a portable application be developed using this setup. diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/README.md b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/README.md new file mode 100644 index 000000000000..7abe334efb22 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/README.md @@ -0,0 +1,57 @@ +# Spring Data JDBC Sample Application with Spanner GoogleSQL + +This sample application shows how to use Spring Data JDBC with Spanner GoogleSQL. + +This sample shows: + +1. How to use Spring Data JDBC with Spanner GoogleSQL. +2. How to use bit-reversed identity columns to automatically generate primary key values for entities. +3. How to set the transaction isolation level that is used by the Spanner JDBC driver. + +## 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. + +### Running the Application + +The application by default runs on the Spanner Emulator. + +1. Modify the [application.properties](src/main/resources/application.properties) to point to an existing + database. The database must use the GoogleSQL dialect. +2. 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. +* [SpannerDialectProvider](src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java): + Spring Data JDBC by default detects the database dialect based on the JDBC driver that is used. + Spanner GoogleSQL is not automatically recognized by Spring Data, so we add a dialect provider + for Spanner. +* [SpannerDialect](src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java): + Spring Data JDBC requires a dialect for the database, so it knows which features are supported, + and how to build clauses like `LIMIT` and `FOR UPDATE`. This class provides this information. It + is based on the built-in `AnsiDialect` in Spring Data JDBC. +* [JdbcConfiguration.java](src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java): + This configuration file serves two purposes: + 1. Make sure `OpenTelemetry` is initialized before any data sources. + 2. Add a converter for `LocalDate` properties. Spring Data JDBC by default map these to `TIMESTAMP` + columns, but a better fit in Spanner is `DATE`. +* [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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml new file mode 100644 index 000000000000..57b0dea29f5a --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -0,0 +1,138 @@ + + + 4.0.0 + + org.example + cloud-spanner-spring-data-jdbc-googlesql-example + 1.0-SNAPSHOT + + Sample application showing how to use Spring Data JDBC with Cloud Spanner GoogleSQL. + + + + 17 + 17 + 17 + UTF-8 + + + + + + org.springframework.data + spring-data-bom + 2024.1.5 + import + pom + + + com.google.cloud + google-cloud-spanner-bom + 6.91.1 + import + pom + + + com.google.cloud + libraries-bom + 26.59.0 + import + pom + + + io.opentelemetry + opentelemetry-bom + 1.49.0 + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-data-jdbc + 3.4.5 + + + + + com.google.cloud + google-cloud-spanner-jdbc + + + com.google.api.grpc + proto-google-cloud-spanner-executor-v1 + + + + + + + io.opentelemetry + opentelemetry-sdk + + + com.google.cloud.opentelemetry + exporter-trace + 0.34.0 + + + com.google.cloud.opentelemetry + exporter-metrics + 0.34.0 + + + + + org.testcontainers + testcontainers + 1.21.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 + + + + + + + com.spotify.fmt + fmt-maven-plugin + 2.25 + + + + format + + + + + + + diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java new file mode 100644 index 000000000000..a75ea2fec7dc --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/Application.java @@ -0,0 +1,269 @@ +/* + * Copyright 2025 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.connection.SavepointSupport; +import com.google.cloud.spanner.connection.SpannerPool; +import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; +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 io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.sql.Statement; +import javax.sql.DataSource; +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) { + // This automatically starts the Spanner emulator in a Docker container, unless the + // spanner.auto_start_emulator property has been set to false. In that case, it is a no-op. + EmulatorInitializer emulatorInitializer = new EmulatorInitializer(); + try { + SpringApplication application = new SpringApplication(Application.class); + application.addListeners(emulatorInitializer); + application.run(args).close(); + } finally { + SpannerPool.closeSpannerPool(); + emulatorInitializer.stopEmulator(); + } + } + + private final DatabaseSeeder databaseSeeder; + + private final SingerService singerService; + + private final SingerRepository singerRepository; + + private final AlbumRepository albumRepository; + + private final TrackRepository trackRepository; + + private final Tracer tracer; + + private final DataSource dataSource; + + public Application( + SingerService singerService, + DatabaseSeeder databaseSeeder, + SingerRepository singerRepository, + AlbumRepository albumRepository, + TrackRepository trackRepository, + Tracer tracer, + DataSource dataSource) { + this.databaseSeeder = databaseSeeder; + this.singerService = singerService; + this.singerRepository = singerRepository; + this.albumRepository = albumRepository; + this.trackRepository = trackRepository; + this.tracer = tracer; + this.dataSource = dataSource; + } + + @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()); + } + + // Run two concurrent transactions that conflict with each other to show the automatic retry + // behavior built into the JDBC driver. + concurrentTransactions(); + + // Use a savepoint to roll back to a previous point in a transaction. + savepoints(); + } + + void concurrentTransactions() { + // Create two transactions that conflict with each other to trigger a transaction retry. + // This sample is intended to show a couple of things: + // 1. Spanner will abort transactions that conflict. The Spanner JDBC driver will automatically + // retry aborted transactions internally, which ensures that both these transactions + // succeed without any errors. See + // https://cloud.google.com/spanner/docs/jdbc-session-mgmt-commands#retry_aborts_internally + // for more information on how the JDBC driver retries aborted transactions. + // 2. The JDBC driver adds information to the OpenTelemetry tracing that makes it easier to find + // transactions that were aborted and retried. + logger.info("Executing two concurrent transactions"); + Span span = tracer.spanBuilder("update-singers").startSpan(); + try (Scope ignore = span.makeCurrent(); + Connection connection1 = dataSource.getConnection(); + Connection connection2 = dataSource.getConnection(); + Statement statement1 = connection1.createStatement(); + Statement statement2 = connection2.createStatement()) { + statement1.execute("begin"); + statement1.execute("set transaction_tag='update-singer-1'"); + statement2.execute("begin"); + statement2.execute("set transaction_tag='update-singer-2'"); + long id = 0L; + statement1.execute("set statement_tag='fetch-singer-id'"); + try (ResultSet resultSet = statement1.executeQuery("select id from singers limit 1")) { + while (resultSet.next()) { + id = resultSet.getLong(1); + } + } + String sql = "update singers set active=not active where id=?"; + statement1.execute("set statement_tag='update-singer-1'"); + try (PreparedStatement preparedStatement = connection1.prepareStatement(sql)) { + preparedStatement.setLong(1, id); + preparedStatement.executeUpdate(); + } + statement2.execute("set statement_tag='update-singer-2'"); + try (PreparedStatement preparedStatement = connection2.prepareStatement(sql)) { + preparedStatement.setLong(1, id); + preparedStatement.executeUpdate(); + } + statement1.execute("commit"); + statement2.execute("commit"); + } catch (SQLException exception) { + span.recordException(exception); + throw new RuntimeException(exception); + } finally { + span.end(); + } + } + + void savepoints() { + // Run a transaction with a savepoint, and rollback to that savepoint. + logger.info("Executing a transaction with a savepoint"); + Span span = tracer.spanBuilder("savepoint-sample").startSpan(); + try (Scope ignore = span.makeCurrent(); + Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement()) { + // Enable savepoints for this connection. + connection + .unwrap(CloudSpannerJdbcConnection.class) + .setSavepointSupport(SavepointSupport.ENABLED); + + statement.execute("begin"); + statement.execute("set transaction_tag='transaction-with-savepoint'"); + + // Fetch a random album. + long id = 0L; + try (ResultSet resultSet = + statement.executeQuery( + "/*@statement_tag='fetch-album-id'*/ select id from albums limit 1")) { + while (resultSet.next()) { + id = resultSet.getLong(1); + } + } + // Set a savepoint that we can roll back to at a later moment in the transaction. + // Note that the savepoint name must be a valid identifier. + Savepoint savepoint = connection.setSavepoint("fetched_album_id"); + + String sql = + "/*@statement_tag='update-album-marketing-budget-by-10-percent'*/ update albums set marketing_budget=marketing_budget * 1.1 where id=?"; + try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setLong(1, id); + preparedStatement.executeUpdate(); + } + + // Rollback to the savepoint that we set at an earlier stage, and then update the marketing + // budget by 20 percent instead. + connection.rollback(savepoint); + + sql = + "/*@statement_tag='update-album-marketing-budget-by-20-percent'*/ update albums set marketing_budget=marketing_budget * 1.2 where id=?"; + try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + preparedStatement.setLong(1, id); + preparedStatement.executeUpdate(); + } + statement.execute("commit"); + + // Reset the state of the connection before returning it to the connection pool. + statement.execute("reset all"); + } catch (SQLException exception) { + span.recordException(exception); + throw new RuntimeException(exception); + } finally { + span.end(); + } + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java new file mode 100644 index 000000000000..3e370a097a86 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java @@ -0,0 +1,353 @@ +/* + * Copyright 2025 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.collect.ImmutableList; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +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 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; + + private final Tracer tracer; + + @Value("classpath:create_schema.sql") + private Resource createSchemaFile; + + @Value("classpath:drop_schema.sql") + private Resource dropSchemaFile; + + public DatabaseSeeder(JdbcTemplate jdbcTemplate, Tracer tracer) { + this.jdbcTemplate = jdbcTemplate; + this.tracer = tracer; + } + + /** 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); + } + } + + /** + * 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) { + // 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() { + Span span = tracer.spanBuilder("deleteTestData").startSpan(); + try (Scope ignore = span.makeCurrent()) { + // Delete all data in one batch. + jdbcTemplate.execute("set statement_tag='batch_delete_test_data'"); + jdbcTemplate.batchUpdate( + "delete from concerts where true", + "delete from venues where true", + "delete from tracks where true", + "delete from albums where true", + "delete from singers where true"); + } catch (Throwable t) { + span.recordException(t); + throw t; + } finally { + span.end(); + } + } + + /** Inserts some initial test data into the database. */ + public void insertTestData() { + Span span = tracer.spanBuilder("insertTestData").startSpan(); + try (Scope ignore = span.makeCurrent()) { + jdbcTemplate.execute("begin"); + jdbcTemplate.execute("set transaction_tag='insert_test_data'"); + jdbcTemplate.execute("set statement_tag='insert_singers'"); + 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.execute("set statement_tag='insert_albums'"); + 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; + } + }); + jdbcTemplate.execute("commit"); + } catch (Throwable t) { + try { + jdbcTemplate.execute("rollback"); + } catch (Exception ignore) { + } + span.recordException(t); + throw t; + } finally { + span.end(); + } + } + + /** 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()).setScale(9, RoundingMode.HALF_UP); + } + + /** 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java new file mode 100644 index 000000000000..afc55890e7ea --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/EmulatorInitializer.java @@ -0,0 +1,57 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.sample; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.env.ConfigurableEnvironment; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; + +public class EmulatorInitializer + implements ApplicationListener { + private GenericContainer emulator; + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + ConfigurableEnvironment environment = event.getEnvironment(); + boolean useEmulator = + Boolean.TRUE.equals(environment.getProperty("spanner.emulator", Boolean.class)); + boolean autoStartEmulator = + Boolean.TRUE.equals(environment.getProperty("spanner.auto_start_emulator", Boolean.class)); + if (!(useEmulator && autoStartEmulator)) { + return; + } + + emulator = + new GenericContainer<>(DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator")); + emulator.withImagePullPolicy(PullPolicy.alwaysPull()); + emulator.addExposedPort(9010); + emulator.setWaitStrategy(Wait.forListeningPorts(9010)); + emulator.start(); + + System.setProperty("spanner.endpoint", "//localhost:" + emulator.getMappedPort(9010)); + } + + public void stopEmulator() { + if (this.emulator != null) { + this.emulator.stop(); + } + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java new file mode 100644 index 000000000000..2537ed7d7d7d --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -0,0 +1,74 @@ +/* + * Copyright 2025 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 java.sql.JDBCType; +import java.sql.SQLType; +import java.time.LocalDate; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.context.annotation.Lazy; +import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; +import org.springframework.data.jdbc.core.convert.JdbcArrayColumns; +import org.springframework.data.jdbc.core.convert.JdbcConverter; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; +import org.springframework.data.jdbc.core.convert.RelationResolver; +import org.springframework.data.jdbc.core.dialect.JdbcDialect; +import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; +import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration; +import org.springframework.data.relational.core.dialect.Dialect; +import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; + +/** + * This configuration class is registered as depending on OpenTelemetry, as the JDBC driver uses the + * globally registered OpenTelemetry instance. It also overrides the default jdbcConverter + * implementation to map LocalDate to the JDBC type DATE (the default implementation maps LocalDate + * to TIMESTAMP). + */ +@DependsOn("openTelemetry") +@Configuration +public class JdbcConfiguration extends AbstractJdbcConfiguration { + + @Bean + @Override + public JdbcConverter jdbcConverter( + JdbcMappingContext mappingContext, + NamedParameterJdbcOperations operations, + @Lazy RelationResolver relationResolver, + JdbcCustomConversions conversions, + Dialect dialect) { + JdbcArrayColumns arrayColumns = + dialect instanceof JdbcDialect + ? ((JdbcDialect) dialect).getArraySupport() + : JdbcArrayColumns.DefaultSupport.INSTANCE; + DefaultJdbcTypeFactory jdbcTypeFactory = + new DefaultJdbcTypeFactory(operations.getJdbcOperations(), arrayColumns); + return new MappingJdbcConverter( + mappingContext, relationResolver, conversions, jdbcTypeFactory) { + @Override + public SQLType getTargetSqlType(RelationalPersistentProperty property) { + if (property.getActualType().equals(LocalDate.class)) { + return JDBCType.DATE; + } + return super.getTargetSqlType(property); + } + }; + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java new file mode 100644 index 000000000000..076554473838 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java @@ -0,0 +1,121 @@ +/* + * Copyright 2025 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.auth.oauth2.GoogleCredentials; +import com.google.cloud.opentelemetry.metric.GoogleCloudMetricExporter; +import com.google.cloud.opentelemetry.metric.MetricConfiguration; +import com.google.cloud.opentelemetry.trace.TraceConfiguration; +import com.google.cloud.opentelemetry.trace.TraceExporter; +import com.google.cloud.spanner.SpannerOptions; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +// @AutoConfiguration(before = DataSourceAutoConfiguration.class) +@Configuration +public class OpenTelemetryConfiguration { + + @Value("${open_telemetry.enabled}") + private boolean enabled; + + @Value("${spanner.emulator}") + private boolean emulator; + + @Value("${open_telemetry.project}") + private String project; + + @Bean + public OpenTelemetry openTelemetry() { + if (!enabled || emulator) { + return OpenTelemetry.noop(); + } + + // Enable OpenTelemetry tracing in Spanner. + SpannerOptions.enableOpenTelemetryTraces(); + SpannerOptions.enableOpenTelemetryMetrics(); + + if (!hasDefaultCredentials()) { + // Create a no-op OpenTelemetry object if this environment does not have any default + // credentials configured. This could for example be on local test environments that use + // the Spanner emulator. + return OpenTelemetry.noop(); + } + + TraceConfiguration.Builder traceConfigurationBuilder = TraceConfiguration.builder(); + TraceConfiguration traceConfiguration = traceConfigurationBuilder.setProjectId(project).build(); + SpanExporter traceExporter = TraceExporter.createWithConfiguration(traceConfiguration); + + MetricConfiguration.Builder metricConfigurationBuilder = MetricConfiguration.builder(); + MetricConfiguration metricConfiguration = + metricConfigurationBuilder.setProjectId(project).build(); + MetricExporter metricExporter = + GoogleCloudMetricExporter.createWithConfiguration(metricConfiguration); + + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .registerMetricReader(PeriodicMetricReader.builder(metricExporter).build()) + .build(); + + // Create an OpenTelemetry object and register it as the global OpenTelemetry object. This + // will automatically be picked up by the Spanner libraries and used for tracing. + return OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + // Set sampling to 'AlwaysOn' in this example. In production, you want to reduce + // this to a smaller fraction to limit the number of traces that are being + // collected. + .setSampler(Sampler.alwaysOn()) + .setResource( + Resource.builder() + .put( + "service.name", + "spanner-jdbc-spring-data-sample-" + + ThreadLocalRandom.current().nextInt()) + .build()) + .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) + .build()) + .setMeterProvider(sdkMeterProvider) + .buildAndRegisterGlobal(); + } + + private boolean hasDefaultCredentials() { + try { + return GoogleCredentials.getApplicationDefault() != null; + } catch (IOException exception) { + return false; + } + } + + @Bean + public Tracer tracer(OpenTelemetry openTelemetry) { + return openTelemetry.getTracer("com.google.cloud.spanner.jdbc.sample.spring-data-jdbc"); + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java new file mode 100644 index 000000000000..b895005849a2 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialect.java @@ -0,0 +1,139 @@ +/* + * Copyright 2025 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.time.ZoneId.systemDefault; + +import com.google.common.collect.ImmutableList; +import java.sql.JDBCType; +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.Collection; +import java.util.Date; +import javax.annotation.Nonnull; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.ReadingConverter; +import org.springframework.data.convert.WritingConverter; +import org.springframework.data.jdbc.core.mapping.JdbcValue; +import org.springframework.data.relational.core.dialect.AnsiDialect; +import org.springframework.data.relational.core.dialect.LimitClause; +import org.springframework.data.relational.core.sql.IdentifierProcessing; +import org.springframework.data.relational.core.sql.IdentifierProcessing.LetterCasing; +import org.springframework.data.relational.core.sql.IdentifierProcessing.Quoting; + +/** + * The Spanner GoogleSQL dialect is relatively close to the standard ANSI dialect. We therefore + * create a custom dialect based on ANSI, but with a few overrides. + */ +public class SpannerDialect extends AnsiDialect { + public static final SpannerDialect INSTANCE = new SpannerDialect(); + + /** Spanner uses backticks for identifier quoting. */ + private static final Quoting QUOTING = new Quoting("`"); + + /** Spanner supports mixed-case identifiers. */ + private static final IdentifierProcessing IDENTIFIER_PROCESSING = + IdentifierProcessing.create(QUOTING, LetterCasing.AS_IS); + + private static final LimitClause LIMIT_CLAUSE = + new LimitClause() { + private static final long DEFAULT_LIMIT_FOR_OFFSET = Long.MAX_VALUE / 2; + + @Nonnull + @Override + public String getLimit(long limit) { + return String.format("LIMIT %d", limit); + } + + @Nonnull + @Override + public String getOffset(long offset) { + // Spanner does not support an OFFSET clause without a LIMIT clause. + return String.format("LIMIT %d OFFSET %d", DEFAULT_LIMIT_FOR_OFFSET, offset); + } + + @Nonnull + @Override + public String getLimitOffset(long limit, long offset) { + return String.format("LIMIT %d OFFSET %d", limit, offset); + } + + @Nonnull + @Override + public Position getClausePosition() { + return Position.AFTER_ORDER_BY; + } + }; + + private SpannerDialect() {} + + @Nonnull + @Override + public IdentifierProcessing getIdentifierProcessing() { + return IDENTIFIER_PROCESSING; + } + + @Nonnull + @Override + public LimitClause limit() { + return LIMIT_CLAUSE; + } + + @Nonnull + @Override + public Collection getConverters() { + return ImmutableList.of( + TimestampAtUtcToOffsetDateTimeConverter.INSTANCE, + OffsetDateTimeToTimestampJdbcValueConverter.INSTANCE, + LocalDateTimeToDateConverter.INSTANCE); + } + + @ReadingConverter + enum TimestampAtUtcToOffsetDateTimeConverter implements Converter { + INSTANCE; + + private static final ZoneId UTC = ZoneId.of("UTC"); + + @Override + public OffsetDateTime convert(Timestamp timestamp) { + return OffsetDateTime.ofInstant(timestamp.toInstant(), UTC); + } + } + + @WritingConverter + enum OffsetDateTimeToTimestampJdbcValueConverter implements Converter { + INSTANCE; + + @Override + public JdbcValue convert(@Nonnull OffsetDateTime source) { + return JdbcValue.of(source, JDBCType.TIMESTAMP); + } + } + + @ReadingConverter + enum LocalDateTimeToDateConverter implements Converter { + INSTANCE; + + @Nonnull + @Override + public Date convert(LocalDateTime source) { + return Date.from(source.atZone(systemDefault()).toInstant()); + } + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java new file mode 100644 index 000000000000..8f9f5ce46755 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/SpannerDialectProvider.java @@ -0,0 +1,46 @@ +/* + * Copyright 2025 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 java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Locale; +import java.util.Optional; +import org.springframework.data.jdbc.repository.config.DialectResolver; +import org.springframework.data.relational.core.dialect.Dialect; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.lang.Nullable; + +public class SpannerDialectProvider implements DialectResolver.JdbcDialectProvider { + @Override + public Optional getDialect(JdbcOperations operations) { + return Optional.ofNullable( + operations.execute((ConnectionCallback) SpannerDialectProvider::getDialect)); + } + + @Nullable + private static Dialect getDialect(Connection connection) throws SQLException { + DatabaseMetaData metaData = connection.getMetaData(); + String name = metaData.getDatabaseProductName().toLowerCase(Locale.ENGLISH); + if (name.contains("spanner")) { + return SpannerDialect.INSTANCE; + } + return null; + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java new file mode 100644 index 000000000000..251acd1a85a9 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 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.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.annotation.PersistenceCreator; + +public abstract class AbstractEntity { + + /** This ID is generated using a (bit-reversed) sequence. */ + @Id private Long id; + + @CreatedDate private OffsetDateTime createdAt; + + @LastModifiedDate private OffsetDateTime updatedAt; + + @PersistenceCreator + public AbstractEntity() {} + + @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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java new file mode 100644 index 000000000000..36674c609de7 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java @@ -0,0 +1,88 @@ +/* + * Copyright 2025 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.annotation.PersistenceCreator; +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; + + @PersistenceCreator + 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java new file mode 100644 index 000000000000..5c1fb0a4f4a1 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java @@ -0,0 +1,84 @@ +/* + * Copyright 2025 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.PersistenceCreator; +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; + + @PersistenceCreator + public Concert() {} + + 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java new file mode 100644 index 000000000000..a6f8fdfc4ec2 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java @@ -0,0 +1,75 @@ +/* + * Copyright 2025 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.PersistenceCreator; +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; + + @PersistenceCreator + 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java new file mode 100644 index 000000000000..1a8e031b23b2 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java @@ -0,0 +1,88 @@ +/* + * Copyright 2025 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.PersistenceCreator; +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; + + @PersistenceCreator + public Track() {} + + 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java new file mode 100644 index 000000000000..78137ebc0976 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java @@ -0,0 +1,50 @@ +/* + * Copyright 2025 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.PersistenceCreator; +import org.springframework.data.relational.core.mapping.Table; + +@Table("venues") +public class Venue extends AbstractEntity { + private String name; + + private String description; + + @PersistenceCreator + public Venue() {} + + 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java new file mode 100644 index 000000000000..ae6bf52d3108 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java new file mode 100644 index 000000000000..dbfb82ccc06a --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java new file mode 100644 index 000000000000..c542d69fb210 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java new file mode 100644 index 000000000000..7b1147024565 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java new file mode 100644 index 000000000000..58ce3bc17f87 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java new file mode 100644 index 000000000000..55f4ee5b90fa --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java @@ -0,0 +1,67 @@ +/* + * Copyright 2025 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/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/META-INF/spring.factories b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000000..3dc08db94b04 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=org.springframework.data.jdbc.repository.config.DialectResolver.DefaultDialectProvider,com.google.cloud.spanner.sample.SpannerDialectProvider diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties new file mode 100644 index 000000000000..a38d9ab98308 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties @@ -0,0 +1,36 @@ + +# This application uses a Spanner GoogleSQL database. + +spanner.project=my-project +spanner.instance=my-instance +spanner.database=spring-data-jdbc + +# Sets the isolation level that will be used by default for read/write transactions. +# Spanner supports the isolation levels SERIALIZABLE and REPEATABLE READ. +spanner.default_isolation_level=REPEATABLE_READ + +# The sample by default uses the Spanner emulator. +# Disable this flag to run the sample on a real Spanner instance. +spanner.emulator=true + +# The sample by default starts an emulator instance in Docker. +# Disable this flag to run the sample on an Emulator instance that +# you start manually, for example if you don't have Docker installed +# on your local machine. Keep the 'spanner.emulator=true' line above +# to connect to the emulator that you have started. +spanner.auto_start_emulator=true + +# Setting this property to true instructs the Spanner JDBC driver to include the SQL statement that +# is executed in the trace. This makes it easier to identify slow queries in your application. +spanner.enable_extended_tracing=true + +spring.datasource.url=jdbc:cloudspanner:${spanner.endpoint}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database};default_isolation_level=${spanner.default_isolation_level};autoConfigEmulator=${spanner.emulator};enableExtendedTracing=${spanner.enable_extended_tracing};${spanner.additional_properties} +spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver + +# Enable/disable OpenTelemetry tracing and export these to Google Cloud Trace. +open_telemetry.enabled=true +open_telemetry.project=${spanner.project} + +# Used for testing +spanner.endpoint= +spanner.additional_properties= diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/create_schema.sql new file mode 100644 index 000000000000..f54ef649222a --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/create_schema.sql @@ -0,0 +1,59 @@ + +-- This script creates the database schema for this sample application. +-- The script is executed by the DatabaseSeeder class. + +CREATE TABLE IF NOT EXISTS singers ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + first_name STRING(MAX), + last_name STRING(MAX), + full_name STRING(MAX) 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 BOOL DEFAULT (TRUE), + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +); + +CREATE TABLE IF NOT EXISTS albums ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + title STRING(MAX) NOT NULL, + marketing_budget NUMERIC, + release_date DATE, + cover_picture BYTES(MAX), + singer_id INT64 NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + CONSTRAINT fk_albums_singers FOREIGN KEY (singer_id) REFERENCES singers (id) +); + +CREATE TABLE IF NOT EXISTS tracks ( + id INT64 NOT NULL, + track_number INT64 NOT NULL, + title STRING(MAX) NOT NULL, + sample_rate FLOAT64 NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +) PRIMARY KEY (id, track_number), INTERLEAVE IN PARENT albums ON DELETE CASCADE +; + +CREATE TABLE IF NOT EXISTS venues ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + name STRING(MAX) NOT NULL, + description JSON NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), +); + +CREATE TABLE IF NOT EXISTS concerts ( + id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE) PRIMARY KEY, + venue_id INT64 NOT NULL, + singer_id INT64 NOT NULL, + name STRING(MAX) NOT NULL, + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP NOT NULL, + created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP), + updated_at TIMESTAMP 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/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/drop_schema.sql similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/drop_schema.sql rename to java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/drop_schema.sql diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java new file mode 100644 index 000000000000..7681e2a6861e --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2025 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 org.junit.Assume.assumeTrue; + +import com.google.cloud.spanner.connection.SpannerPool; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.springframework.boot.SpringApplication; +import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; + +@RunWith(JUnit4.class) +public class ApplicationEmulatorTest { + private static GenericContainer emulator; + + @BeforeClass + public static void startEmulator() { + assumeTrue(DockerClientFactory.instance().isDockerAvailable()); + + emulator = + new GenericContainer<>( + DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) + .withImagePullPolicy(PullPolicy.alwaysPull()) + .withExposedPorts(9010) + .waitingFor(Wait.forListeningPorts(9010)); + emulator.start(); + } + + @AfterClass + public static void cleanup() { + SpannerPool.closeSpannerPool(); + if (emulator != null) { + emulator.stop(); + } + } + + @Test + public void testRunApplication() { + System.setProperty("open_telemetry.enabled", "false"); + System.setProperty("open_telemetry.project", "test-project"); + System.setProperty("spanner.emulator", "true"); + System.setProperty("spanner.auto_start_emulator", "false"); + System.setProperty( + "spanner.endpoint", String.format("//localhost:%d", emulator.getMappedPort(9010))); + SpringApplication.run(Application.class).close(); + } +} diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/README.md b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/README.md new file mode 100644 index 000000000000..da1d69532e84 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/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/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml similarity index 98% rename from java-spanner-jdbc/samples/spring-data-jdbc/pom.xml rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 032ad9fe0b80..5e04a256d717 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.example - cloud-spanner-spring-data-jdbc-example + cloud-spanner-spring-data-jdbc-postgresql-example 1.0-SNAPSHOT Sample application showing how to use Spring Data JDBC with Cloud Spanner PostgreSQL. diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/Application.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/Application.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/Application.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/DatabaseSeeder.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java similarity index 97% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java index b833e48b7c50..f1e615290212 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java @@ -36,6 +36,8 @@ import java.io.IOException; import java.util.concurrent.ThreadLocalRandom; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/AbstractEntity.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Album.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Album.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Concert.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Singer.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Track.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Track.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/entities/Venue.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/AlbumRepository.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/ConcertRepository.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/SingerRepository.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/TrackRepository.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/repositories/VenueRepository.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/service/SingerService.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application-cs.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-cs.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application-cs.properties diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application-pg.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application-pg.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application-pg.properties diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/application.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/application.properties diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/create_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/create_schema.sql similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/main/resources/create_schema.sql rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/create_schema.sql diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/drop_schema.sql b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/resources/drop_schema.sql new file mode 100644 index 000000000000..23e7b65d3bb1 --- /dev/null +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/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/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationEmulatorTest.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-cs.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application-cs.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-cs.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application-cs.properties diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-pg.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application-pg.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application-pg.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application-pg.properties diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application.properties similarity index 100% rename from java-spanner-jdbc/samples/spring-data-jdbc/src/test/resources/application.properties rename to java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/test/resources/application.properties From c09d04df26c51fa475d9aba90481df405d9a47b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 29 Apr 2025 13:52:35 +0200 Subject: [PATCH 1636/1979] chore: cleanup MyBatis sample for GoogleSQL (#2029) --- .../samples/spring-data-mybatis/googlesql/pom.xml | 14 +++++++------- .../cloud/spanner/sample/ApplicationTest.java | 11 ----------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 47fb7b0a452e..1b797834499b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -32,6 +32,13 @@ import pom + + com.google.cloud + google-cloud-spanner-bom + 6.91.1 + import + pom + com.google.cloud libraries-bom @@ -62,16 +69,9 @@ - - - com.google.cloud - google-cloud-spanner - 6.91.1 - com.google.cloud google-cloud-spanner-jdbc - 2.29.1 com.google.api.grpc diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java index ade5d85c6567..348f31281a43 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/test/java/com/google/cloud/spanner/sample/ApplicationTest.java @@ -850,17 +850,6 @@ public void testRunApplication() { System.setProperty("spanner.additional_properties", "usePlainText=true"); Application.main(new String[] {}); - assertEquals( - 39, - mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() - .filter( - request -> - !request.getSql().equals("SELECT 1") - && !request - .getSql() - .equals( - "SELECT * FROM singers ORDER BY sha256(last_name::bytea) LIMIT 1")) - .count()); assertEquals(3, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); assertEquals(6, mockSpanner.countRequestsOfType(CommitRequest.class)); From 91064fdf930fe86a7524b0d69a62d146546e8a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 29 Apr 2025 14:16:26 +0200 Subject: [PATCH 1637/1979] chore: cleanup MyBatis sample for GoogleSQL (#2029) From 1ace711f28b7a9b68d680b17367939db534f7569 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 1 May 2025 14:20:05 +0200 Subject: [PATCH 1638/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.61.0 (#2035) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 01c6d79db00f..a1bad478f02f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.60.0 + 2.61.0 test From 14d63c44608c09f9c4f398b20b9cad53781bbc1a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 1 May 2025 14:20:25 +0200 Subject: [PATCH 1639/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.61.0 (#2034) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a1bad478f02f..12a65bf79bde 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.60.0 + 2.61.0 test From 2dbcd4f97e5d4241c28939ee13300583245fe388 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 1 May 2025 15:23:46 +0200 Subject: [PATCH 1640/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.92.0 (#2032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.92.0 * feat: add support for UUID data type --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 2 +- .../spring-data-jdbc/googlesql/pom.xml | 2 +- .../spring-data-jdbc/postgresql/pom.xml | 2 +- .../spring-data-mybatis/googlesql/pom.xml | 2 +- .../cloud/spanner/jdbc/JdbcDataType.java | 27 +++++ .../spanner/jdbc/JdbcParameterStore.java | 11 ++ .../cloud/spanner/jdbc/JdbcResultSet.java | 100 +++++++++++++----- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 7 +- .../google/cloud/spanner/jdbc/UuidType.java | 61 +++++++++++ .../spanner/jdbc/AllTypesMockServerTest.java | 44 ++++++-- .../spanner/jdbc/JdbcParameterStoreTest.java | 7 +- .../jdbc/PartitionedQueryMockServerTest.java | 2 +- .../spanner/jdbc/RandomResultSetTest.java | 9 +- 13 files changed, 228 insertions(+), 48 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 12a65bf79bde..9e3398e41ec0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.91.1 + 6.92.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 57b0dea29f5a..a84f3067ff6f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.91.1 + 6.92.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 5e04a256d717..7bedf6ce22e5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.91.1 + 6.92.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 1b797834499b..b4cc9e0b9ea9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.91.1 + 6.92.0 import pom diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index d73233c32369..6a77cecc2ddc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -29,6 +29,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.UUID; /** Enum for mapping Cloud Spanner data types to Java classes and JDBC SQL {@link Types}. */ enum JdbcDataType { @@ -379,6 +380,32 @@ public Type getSpannerType() { return Type.timestamp(); } }, + UUID { + @Override + public int getSqlType() { + return UuidType.VENDOR_TYPE_NUMBER; + } + + @Override + public Class getJavaClass() { + return UUID.class; + } + + @Override + public Code getCode() { + return Code.UUID; + } + + @Override + public List getArrayElements(ResultSet rs, int columnIndex) { + return rs.getUuidList(columnIndex); + } + + @Override + public Type getSpannerType() { + return Type.uuid(); + } + }, STRUCT { @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 47d096261dbd..0964db08799e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -729,6 +729,12 @@ private Builder setParamWithUnknownType(ValueBinder binder, Object valu } else if (Time.class.isAssignableFrom(value.getClass())) { Time timeValue = (Time) value; return binder.to(JdbcTypeConverter.toGoogleTimestamp(new Timestamp(timeValue.getTime()))); + } else if (UUID.class.isAssignableFrom(value.getClass())) { + // Bind UUID values as untyped strings to allow them to be used with all types that support + // string values (e.g. STRING, UUID). + return binder.to( + Value.untyped( + com.google.protobuf.Value.newBuilder().setStringValue(value.toString()).build())); } else if (String.class.isAssignableFrom(value.getClass())) { String stringVal = (String) value; return binder.to(stringVal); @@ -853,6 +859,9 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu com.google.protobuf.Value.newBuilder() .setNullValue(NullValue.NULL_VALUE) .build())); + case UuidType.VENDOR_TYPE_NUMBER: + case UuidType.SHORT_VENDOR_TYPE_NUMBER: + return binder.toUuidArray(null); default: return binder.to( Value.untyped( @@ -907,6 +916,8 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu return binder.toDateArray(JdbcTypeConverter.toGoogleDates((Date[]) value)); } else if (Timestamp[].class.isAssignableFrom(value.getClass())) { return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value)); + } else if (UUID[].class.isAssignableFrom(value.getClass())) { + return binder.toUuidArray(Arrays.asList((UUID[]) value)); } else if (String[].class.isAssignableFrom(value.getClass())) { if (type == JsonType.VENDOR_TYPE_NUMBER || type == JsonType.SHORT_VENDOR_TYPE_NUMBER) { return binder.toJsonArray(Arrays.asList((String[]) value)); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index 00df251162c3..d9bfe818b729 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -52,6 +52,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.UUID; import javax.annotation.Nonnull; /** Implementation of {@link ResultSet} for Cloud Spanner */ @@ -623,6 +624,38 @@ public Timestamp getTimestamp(int columnIndex) throws SQLException { } } + public UUID getUUID(int columnIndex) throws SQLException { + checkClosedAndValidRow(); + if (isNull(columnIndex)) { + return null; + } + int spannerIndex = columnIndex - 1; + Code type = getMainTypeCode(spanner.getColumnType(spannerIndex)); + switch (type) { + case UUID: + return spanner.getUuid(spannerIndex); + case STRING: + return UUID.fromString(spanner.getString(spannerIndex)); + case BYTES: + case DATE: + case TIMESTAMP: + case BOOL: + case FLOAT32: + case FLOAT64: + case INT64: + case NUMERIC: + case PG_NUMERIC: + case JSON: + case PG_JSONB: + case STRUCT: + case PROTO: + case ENUM: + case ARRAY: + default: + throw createInvalidToGetAs("uuid", type); + } + } + private InputStream getInputStream(String val, Charset charset) { if (val == null) return null; byte[] b = val.getBytes(charset); @@ -764,35 +797,46 @@ public Object getObject(int columnIndex) throws SQLException { } private Object getObject(Type type, int columnIndex) throws SQLException { - // TODO: Refactor to check based on type code. - if (type == Type.bool()) return getBoolean(columnIndex); - if (type == Type.bytes()) return getBytes(columnIndex); - if (type == Type.date()) return getDate(columnIndex); - if (type == Type.float32()) { - return getFloat(columnIndex); - } - if (type == Type.float64()) return getDouble(columnIndex); - if (type == Type.int64() || type == Type.pgOid()) { - return getLong(columnIndex); - } - if (type == Type.numeric()) return getBigDecimal(columnIndex); - if (type == Type.pgNumeric()) { - final String value = getString(columnIndex); - try { - return parseBigDecimal(value); - } catch (Exception e) { - return parseDouble(value); - } - } - if (type == Type.string()) return getString(columnIndex); - if (type == Type.json() || type == Type.pgJsonb()) { - return getString(columnIndex); + JdbcPreconditions.checkArgument(type != null, "type is null"); + switch (type.getCode()) { + case BOOL: + return getBoolean(columnIndex); + case BYTES: + case PROTO: + return getBytes(columnIndex); + case DATE: + return getDate(columnIndex); + case FLOAT32: + return getFloat(columnIndex); + case FLOAT64: + return getDouble(columnIndex); + case INT64: + case PG_OID: + case ENUM: + return getLong(columnIndex); + case NUMERIC: + return getBigDecimal(columnIndex); + case PG_NUMERIC: + final String value = getString(columnIndex); + try { + return parseBigDecimal(value); + } catch (Exception e) { + return parseDouble(value); + } + case STRING: + case JSON: + case PG_JSONB: + return getString(columnIndex); + case TIMESTAMP: + return getTimestamp(columnIndex); + case UUID: + return getUUID(columnIndex); + case ARRAY: + return getArray(columnIndex); + default: + throw JdbcSqlExceptionFactory.of( + "Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT); } - if (type == Type.timestamp()) return getTimestamp(columnIndex); - if (type.getCode() == Code.PROTO) return getBytes(columnIndex); - if (type.getCode() == Code.ENUM) return getLong(columnIndex); - if (type.getCode() == Code.ARRAY) return getArray(columnIndex); - throw JdbcSqlExceptionFactory.of("Unknown type: " + type, com.google.rpc.Code.INVALID_ARGUMENT); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index b98340332c88..942be1587ea8 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -82,6 +82,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (value == null) { return null; } + if (value.getClass().equals(targetType)) { + return value; + } try { if (targetType.equals(Value.class)) { return convertToSpannerValue(value, type); @@ -370,7 +373,9 @@ private static Value convertToSpannerValue(Object value, Type type) throws SQLEx private static void checkValidTypeAndValueForConvert(Type type, Object value) throws SQLException { - if (value == null) return; + if (value == null) { + return; + } JdbcPreconditions.checkArgument( type.getCode() != Code.ARRAY || Array.class.isAssignableFrom(value.getClass()), "input type is array, but input value is not an instance of java.sql.Array"); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java new file mode 100644 index 000000000000..46317b4353a4 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java @@ -0,0 +1,61 @@ +/* + * Copyright 2025 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.spanner.v1.TypeCode; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLType; + +/** + * Custom SQL type for Spanner UUID data type. This type (or the vendor type number) must be used + * when setting a UUID parameter using {@link PreparedStatement#setObject(int, Object, SQLType)}. + */ +public class UuidType implements SQLType { + public static final UuidType INSTANCE = new UuidType(); + /** + * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid + * conflicts with the type numbers in java.sql.Types. + */ + public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.UUID_VALUE; + /** + * Define a short type number as well, as this is what is expected to be returned in {@link + * DatabaseMetaData#getTypeInfo()}. + */ + public static final short SHORT_VENDOR_TYPE_NUMBER = (short) VENDOR_TYPE_NUMBER; + + private UuidType() {} + + @Override + public String getName() { + return "UUID"; + } + + @Override + public String getVendor() { + return UuidType.class.getPackage().getName(); + } + + @Override + public Integer getVendorTypeNumber() { + return VENDOR_TYPE_NUMBER; + } + + public String toString() { + return getName(); + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java index c3848933953f..7cb9729dc9f3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AllTypesMockServerTest.java @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,6 +75,7 @@ public void testSelectAllTypes() { new java.sql.Date( DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth()), resultSet.getDate(++col)); + assertEquals(UUID_VALUE, resultSet.getObject(++col, UUID.class)); assertEquals(TIMESTAMP_VALUE.toSqlTimestamp(), resultSet.getTimestamp(++col)); if (dialect == Dialect.POSTGRESQL) { assertEquals(PG_OID_VALUE, resultSet.getLong(++col)); @@ -120,6 +122,8 @@ public void testSelectAllTypes() { date.getYear() - 1900, date.getMonth() - 1, date.getDayOfMonth())) .collect(Collectors.toList()), Arrays.asList((Date[]) resultSet.getArray(++col).getArray())); + assertEquals( + UUID_ARRAY_VALUE, Arrays.asList((UUID[]) resultSet.getArray(++col).getArray())); assertEquals( TIMESTAMP_ARRAY_VALUE.stream() .map(timestamp -> timestamp == null ? null : timestamp.toSqlTimestamp()) @@ -140,13 +144,13 @@ public void testSelectAllTypes() { @Override @Test public void testInsertAllTypes() { - // TODO: Remove when PG_NUMERIC NaN is supported. + Statement insertStatement = createInsertStatement(dialect); if (dialect == Dialect.POSTGRESQL) { - Statement insertStatement = createInsertStatement(dialect); + // TODO: Remove when PG_NUMERIC NaN is supported. insertStatement = insertStatement.toBuilder() .replace(insertStatement.getSql().replaceAll("@p", "\\$")) - .bind("p16") + .bind("p17") .to( com.google.cloud.spanner.Value.pgNumericArray( NUMERIC_ARRAY_VALUE.stream() @@ -155,8 +159,10 @@ public void testInsertAllTypes() { bigDecimal == null ? null : bigDecimal.toEngineeringString()) .collect(Collectors.toList()))) .build(); - mockSpanner.putStatementResult(StatementResult.update(insertStatement, 1L)); } + // The JDBC driver binds UUID values as untyped strings, so we need to add it as 'partial' + // result, meaning that the match will only be made based on the SQL string. + mockSpanner.putPartialStatementResult(StatementResult.update(insertStatement, 1L)); try (Connection connection = createJdbcConnection()) { try (PreparedStatement statement = connection.prepareStatement( @@ -184,6 +190,7 @@ public void testInsertAllTypes() { DATE_VALUE.getYear() - 1900, DATE_VALUE.getMonth() - 1, DATE_VALUE.getDayOfMonth())); + statement.setObject(++param, UUID_VALUE); statement.setTimestamp(++param, TIMESTAMP_VALUE.toSqlTimestamp()); if (dialect == Dialect.POSTGRESQL) { statement.setLong(++param, PG_OID_VALUE); @@ -243,6 +250,8 @@ public void testInsertAllTypes() { date.getMonth() - 1, date.getDayOfMonth())) .toArray(Date[]::new))); + statement.setArray( + ++param, connection.createArrayOf("UUID", UUID_ARRAY_VALUE.toArray(new UUID[0]))); statement.setArray( ++param, connection.createArrayOf( @@ -262,8 +271,10 @@ public void testInsertAllTypes() { ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); Map paramTypes = request.getParamTypesMap(); Map params = request.getParams().getFieldsMap(); - assertEquals(dialect == Dialect.POSTGRESQL ? 22 : 20, paramTypes.size()); - assertEquals(dialect == Dialect.POSTGRESQL ? 22 : 20, params.size()); + // UUID is sent without any type information to allow it to be used with any type of column + // that accepts a STRING value. + assertEquals(dialect == Dialect.POSTGRESQL ? 23 : 21, paramTypes.size()); + assertEquals(dialect == Dialect.POSTGRESQL ? 24 : 22, params.size()); // Verify param types. ImmutableList expectedTypes = @@ -277,18 +288,25 @@ public void testInsertAllTypes() { TypeCode.JSON, TypeCode.BYTES, TypeCode.DATE, + TypeCode.TYPE_CODE_UNSPECIFIED, // UUID TypeCode.TIMESTAMP); if (dialect == Dialect.POSTGRESQL) { expectedTypes = ImmutableList.builder().addAll(expectedTypes).add(TypeCode.INT64).build(); } for (int col = 0; col < expectedTypes.size(); col++) { - assertEquals(expectedTypes.get(col), paramTypes.get("p" + (col + 1)).getCode()); + TypeCode expectedType = expectedTypes.get(col); + if (expectedType == TypeCode.TYPE_CODE_UNSPECIFIED) { + assertFalse(paramTypes.containsKey("p" + (col + 1))); + } else { + assertEquals(expectedType, paramTypes.get("p" + (col + 1)).getCode()); + } int arrayCol = col + expectedTypes.size(); assertEquals(TypeCode.ARRAY, paramTypes.get("p" + (arrayCol + 1)).getCode()); - assertEquals( - expectedTypes.get(col), - paramTypes.get("p" + (arrayCol + 1)).getArrayElementType().getCode()); + if (expectedType != TypeCode.TYPE_CODE_UNSPECIFIED) { + assertEquals( + expectedType, paramTypes.get("p" + (arrayCol + 1)).getArrayElementType().getCode()); + } } // Verify param values. @@ -306,6 +324,7 @@ public void testInsertAllTypes() { Base64.getEncoder().encodeToString(BYTES_VALUE), params.get("p" + ++col).getStringValue()); assertEquals(DATE_VALUE.toString(), params.get("p" + ++col).getStringValue()); + assertEquals(UUID_VALUE.toString(), params.get("p" + ++col).getStringValue()); assertEquals(TIMESTAMP_VALUE.toString(), params.get("p" + ++col).getStringValue()); if (dialect == Dialect.POSTGRESQL) { assertEquals(String.valueOf(PG_OID_VALUE), params.get("p" + ++col).getStringValue()); @@ -376,6 +395,11 @@ public void testInsertAllTypes() { ? null : com.google.cloud.Date.parseDate(value.getStringValue())) .collect(Collectors.toList())); + assertEquals( + UUID_ARRAY_VALUE, + params.get("p" + ++col).getListValue().getValuesList().stream() + .map(value -> value.hasNullValue() ? null : UUID.fromString(value.getStringValue())) + .collect(Collectors.toList())); assertEquals( TIMESTAMP_ARRAY_VALUE, params.get("p" + ++col).getListValue().getValuesList().stream() diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java index d77c932c1b9e..699f36c994ff 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcParameterStoreTest.java @@ -729,7 +729,12 @@ public void testSetParameterWithoutType() throws SQLException { verifyParameter(params, Value.string("test")); params.setParameter(1, UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), (Integer) null); assertEquals(UUID.fromString("83b988cf-1f4e-428a-be3d-cc712621942e"), params.getParameter(1)); - verifyParameter(params, Value.string("83b988cf-1f4e-428a-be3d-cc712621942e")); + verifyParameter( + params, + Value.untyped( + com.google.protobuf.Value.newBuilder() + .setStringValue("83b988cf-1f4e-428a-be3d-cc712621942e") + .build())); String jsonString = "{\"test\": \"value\"}"; params.setParameter(1, Value.json(jsonString), (Integer) null); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java index 1ee80983bf6a..42c59b4c3c47 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PartitionedQueryMockServerTest.java @@ -74,7 +74,7 @@ public void clearRequests() { private int getExpectedColumnCount(Dialect dialect) { // GoogleSQL also adds 4 PROTO columns. // PostgreSQL adds 2 OID columns. - return dialect == Dialect.GOOGLE_STANDARD_SQL ? 24 : 22; + return dialect == Dialect.GOOGLE_STANDARD_SQL ? 26 : 24; } private String createUrl() { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java index e00907ee94d5..a6b585578259 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/RandomResultSetTest.java @@ -28,6 +28,7 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; +import java.util.UUID; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -77,6 +78,7 @@ public void testSelectRandomResults() throws SQLException { assertEquals(Types.NVARCHAR, metadata.getColumnType(++col)); assertEquals(Types.BINARY, metadata.getColumnType(++col)); assertEquals(Types.DATE, metadata.getColumnType(++col)); + assertEquals(Types.OTHER, metadata.getColumnType(++col)); assertEquals(Types.TIMESTAMP, metadata.getColumnType(++col)); if (dialect == Dialect.POSTGRESQL) { assertEquals(Types.BIGINT, metadata.getColumnType(++col)); @@ -91,6 +93,7 @@ public void testSelectRandomResults() throws SQLException { assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // nvarchar assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // binary assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // date + assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // uuid assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // timestamp if (dialect == Dialect.POSTGRESQL) { assertEquals(Types.ARRAY, metadata.getColumnType(++col)); // oid @@ -112,9 +115,7 @@ public void testSelectRandomResults() throws SQLException { while (resultSet.next()) { // Verify that we can get all columns as an object. for (col = 1; col <= resultSet.getMetaData().getColumnCount(); col++) { - if (dialect == Dialect.GOOGLE_STANDARD_SQL && col > 20) { - // Proto columns are not yet supported, so skipping. - } else if (dialect == Dialect.POSTGRESQL && col == 16) { + if (dialect == Dialect.POSTGRESQL && col == 17) { // getObject for ARRAY tries to get the array as a List. // That fails if the array contains a NaN, so skipping. } else { @@ -133,6 +134,7 @@ public void testSelectRandomResults() throws SQLException { resultSet.getString(++col); // JSON resultSet.getBytes(++col); resultSet.getDate(++col); + resultSet.getObject(++col, UUID.class); resultSet.getTimestamp(++col); if (dialect == Dialect.POSTGRESQL) { resultSet.getLong(++col); // oid @@ -154,6 +156,7 @@ public void testSelectRandomResults() throws SQLException { resultSet.getArray(++col); resultSet.getArray(++col); resultSet.getArray(++col); + resultSet.getArray(++col); if (dialect == Dialect.POSTGRESQL) { resultSet.getArray(++col); // oid[] } From 35826afcb8037662a8f22aecf1c9977a72a8c4ac Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 1 May 2025 15:53:39 +0200 Subject: [PATCH 1641/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.92.0 (#2031) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index b4cc9e0b9ea9..d57e4131e40b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.91.1 + 6.92.0 test-jar test From 199cb6eaa51c8dd76d8388bc6da9d4fac07cd3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 1 May 2025 19:49:01 +0200 Subject: [PATCH 1642/1979] feat: add UUID data type (#2036) --- .../spanner/jdbc/JdbcDatabaseMetaData.java | 38 +++++++++++++++++++ .../jdbc/DatabaseMetaData_GetColumns.sql | 2 + .../jdbc/JdbcDatabaseMetaDataTest.java | 4 ++ 3 files changed, 44 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index b7fe95145a24..67c6976c7a24 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -1290,6 +1290,44 @@ public ResultSet getTypeInfo() { .set("NUM_PREC_RADIX") .to(10) .build(), + Struct.newBuilder() + .set("TYPE_NAME") + .to("UUID") + .set("DATA_TYPE") + .to(Types.OTHER) // There's no JDBC-specific type code for UUID. + .set("PRECISION") + .to((Long) null) + .set("LITERAL_PREFIX") + .to("UUID ") + .set("LITERAL_SUFFIX") + .to((String) null) + .set("CREATE_PARAMS") + .to((String) null) + .set("NULLABLE") + .to(DatabaseMetaData.typeNullable) + .set("CASE_SENSITIVE") + .to(false) + .set("SEARCHABLE") + .to(DatabaseMetaData.typeSearchable) + .set("UNSIGNED_ATTRIBUTE") + .to(true) + .set("FIXED_PREC_SCALE") + .to(false) + .set("AUTO_INCREMENT") + .to(false) + .set("LOCAL_TYPE_NAME") + .to("UUID") + .set("MINIMUM_SCALE") + .to(0) + .set("MAXIMUM_SCALE") + .to(0) + .set("SQL_DATA_TYPE") + .to((Long) null) + .set("SQL_DATETIME_SUB") + .to((Long) null) + .set("NUM_PREC_RADIX") + .to((Long) null) + .build(), getJsonType(connection.getDialect()))), // Allow column 2 to be cast to short without any range checks. ImmutableSet.of(2)); diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql index 8509ee00f06f..818b45ae3b92 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/DatabaseMetaData_GetColumns.sql @@ -27,6 +27,8 @@ SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLU WHEN SPANNER_TYPE LIKE 'STRING%' THEN -9 WHEN SPANNER_TYPE = 'JSON' THEN -9 WHEN SPANNER_TYPE = 'TIMESTAMP' THEN 93 + WHEN SPANNER_TYPE = 'UUID' THEN 1111 + ELSE 1111 END AS DATA_TYPE, SPANNER_TYPE AS TYPE_NAME, CASE diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index c8970fd76d52..7dc4667e4857 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -510,6 +510,10 @@ public void testGetTypeInfo() throws SQLException { assertEquals(Types.NUMERIC, rs.getInt("DATA_TYPE")); assertEquals(Types.NUMERIC, rs.getShort("DATA_TYPE")); assertTrue(rs.next()); + assertEquals("UUID", rs.getString("TYPE_NAME")); + assertEquals(Types.OTHER, rs.getInt("DATA_TYPE")); + assertEquals(Types.OTHER, rs.getShort("DATA_TYPE")); + assertTrue(rs.next()); if (dialect == Dialect.POSTGRESQL) { assertEquals("JSONB", rs.getString("TYPE_NAME")); assertEquals(PgJsonbType.VENDOR_TYPE_NUMBER, rs.getInt("DATA_TYPE")); From b8a46b315c57d2365c626fe4348931ec0a5ac549 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 20:21:36 +0200 Subject: [PATCH 1643/1979] chore(main): release 2.30.0 (#2028) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 21 +++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 882dc0656929..24968a857c9c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [2.30.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.29.1...v2.30.0) (2025-05-01) + + +### Features + +* Add UUID data type ([#2036](https://github.com/googleapis/java-spanner-jdbc/issues/2036)) ([0df29fc](https://github.com/googleapis/java-spanner-jdbc/commit/0df29fc8e88d4ad285fe22125b75b860ad21c371)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.61.0 ([#2034](https://github.com/googleapis/java-spanner-jdbc/issues/2034)) ([d5b88db](https://github.com/googleapis/java-spanner-jdbc/commit/d5b88dbc66c5e4d33493dba6308be43f1601a5af)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.92.0 ([#2031](https://github.com/googleapis/java-spanner-jdbc/issues/2031)) ([4fe13a3](https://github.com/googleapis/java-spanner-jdbc/commit/4fe13a31e6fdcd65860047b9f29f370039c54db8)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.92.0 ([#2032](https://github.com/googleapis/java-spanner-jdbc/issues/2032)) ([d313e3e](https://github.com/googleapis/java-spanner-jdbc/commit/d313e3e60d23e1adeff50da496dd5207bc78fb84)) +* Update dependency com.google.cloud:google-cloud-trace to v2.61.0 ([#2035](https://github.com/googleapis/java-spanner-jdbc/issues/2035)) ([9b2712e](https://github.com/googleapis/java-spanner-jdbc/commit/9b2712e2b9950a8d1cb49c3a91b178726821d3b3)) + + +### Documentation + +* Add sample for MyBatis with GoogleSQL ([#2026](https://github.com/googleapis/java-spanner-jdbc/issues/2026)) ([5d7b9de](https://github.com/googleapis/java-spanner-jdbc/commit/5d7b9de545015655a095f4336c301148b4a9640d)) +* Add sample for Spring Data JDBC with GoogleSQL ([#2027](https://github.com/googleapis/java-spanner-jdbc/issues/2027)) ([3476106](https://github.com/googleapis/java-spanner-jdbc/commit/347610686406c7e4129e0ed101924926f4dca2b5)) + ## [2.29.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.29.0...v2.29.1) (2025-04-25) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c2c8c96acb39..b398f8a89fd9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.29.1 + 2.30.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.29.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.29.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9e3398e41ec0..87b037480fe7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.29.2-SNAPSHOT + 2.30.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6ed736fdd018..2203e93c39c5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.2-SNAPSHOT + 2.30.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index cb7af1e689e5..630246c9044a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.29.1:2.29.2-SNAPSHOT +google-cloud-spanner-jdbc:2.30.0:2.30.0 From 64ccd5343ec997038e69e003b83d3048b9557dff Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 10:25:12 +0200 Subject: [PATCH 1644/1979] chore(main): release 2.30.1-SNAPSHOT (#2037) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 87b037480fe7..75e8d94389e7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.0 + 2.30.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2203e93c39c5..e4e6669005d2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.0 + 2.30.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 630246c9044a..e1273f78f547 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.0:2.30.0 +google-cloud-spanner-jdbc:2.30.0:2.30.1-SNAPSHOT From 6cd1c7a1d95a8d265e8562a98304ecc454e25e08 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 2 May 2025 10:31:38 +0200 Subject: [PATCH 1645/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.30.0 (#2038) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 225f089d9613..b16b39dc8f08 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.29.1 + 2.30.0 From a75dd64fa920bbee28b1d5a7d530a011c30152eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 3 May 2025 07:07:07 +0200 Subject: [PATCH 1646/1979] chore: use serializable as default isolation level (#2040) --- .../googlesql/src/main/resources/application.properties | 2 +- .../googlesql/src/main/resources/application.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties index a38d9ab98308..07724fdfb036 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/resources/application.properties @@ -7,7 +7,7 @@ spanner.database=spring-data-jdbc # Sets the isolation level that will be used by default for read/write transactions. # Spanner supports the isolation levels SERIALIZABLE and REPEATABLE READ. -spanner.default_isolation_level=REPEATABLE_READ +spanner.default_isolation_level=SERIALIZABLE # The sample by default uses the Spanner emulator. # Disable this flag to run the sample on a real Spanner instance. diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties index bbe258dbfaae..e3eb847a68bd 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/src/main/resources/application.properties @@ -21,7 +21,7 @@ spanner.database=mybatis-sample # Sets the isolation level that will be used by default for read/write transactions. # Spanner supports the isolation levels SERIALIZABLE and REPEATABLE READ. -spanner.default_isolation_level=REPEATABLE_READ +spanner.default_isolation_level=SERIALIZABLE spring.datasource.url=jdbc:cloudspanner:${spanner.endpoint}/projects/${spanner.project}/instances/${spanner.instance}/databases/${spanner.database};default_isolation_level=${spanner.default_isolation_level};autoConfigEmulator=${spanner.emulator};${spanner.additional_properties} spring.datasource.driver-class-name=com.google.cloud.spanner.jdbc.JdbcDriver From 053a868caa56c33c27eb3590df2850587ad92be9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 3 May 2025 07:16:58 +0200 Subject: [PATCH 1647/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.46.3 (#2039) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index e9e27d453b27..688659942104 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.2 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.3 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 55d6ffb845f7..114780ae9616 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.3" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 666fed5370ae..100969ebaf49 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.3" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 4c404c2549b1..3adf7cfdb5b4 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.46.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.46.3" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 75e8d94389e7..4323536e8b06 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.46.2 + 3.46.3 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 5aa91d099b01..5bc71d3bcbe9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.46.2 + 3.46.3 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 392436b2d2d4..194fa9843623 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.46.2 + 3.46.3 From c2229384538eb5f30977973140ca0548435a0ca4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 8 May 2025 15:42:15 +0200 Subject: [PATCH 1648/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.62.0 (#2045) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4323536e8b06..d871029a65a5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.61.0 + 2.62.0 test From 3b96b2502471ae41eadeed5f0f781f21f0525382 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 8 May 2025 15:43:09 +0200 Subject: [PATCH 1649/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.62.0 (#2044) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d871029a65a5..17e0bd06ca9e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.61.0 + 2.62.0 test From f7c1d8d7f37275de4e832461005a6131617b38f4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 8 May 2025 15:46:05 +0200 Subject: [PATCH 1650/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.27 (#2042) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a84f3067ff6f..3650afc719f9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -124,7 +124,7 @@ com.spotify.fmt fmt-maven-plugin - 2.25 + 2.27 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 7bedf6ce22e5..28906823850f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -129,7 +129,7 @@ com.spotify.fmt fmt-maven-plugin - 2.25 + 2.27 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d57e4131e40b..c97d84541756 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -116,7 +116,7 @@ com.spotify.fmt fmt-maven-plugin - 2.25 + 2.27 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index ccc3499b716e..0cd43877cb44 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -113,7 +113,7 @@ com.spotify.fmt fmt-maven-plugin - 2.25 + 2.27 From 6890e18512d62361e1fe9e0c7ac3868434932077 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 9 May 2025 12:33:57 +0200 Subject: [PATCH 1651/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.47.0 (#2043) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 688659942104..d74a2b264260 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.46.3 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.47.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 114780ae9616..fcb138739ea4 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.46.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.47.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 100969ebaf49..f8ab2d6e516f 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.46.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.47.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 3adf7cfdb5b4..fa345ea0a4c2 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.46.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.47.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 17e0bd06ca9e..9a647b5ed839 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.46.3 + 3.47.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 5bc71d3bcbe9..c32aba479059 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.46.3 + 3.47.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 194fa9843623..a648f3ba6a9b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.46.3 + 3.47.0 From 1b9ea5d92b5363c1d8b574f9be4ad6e7e1325f87 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 9 May 2025 17:55:12 +0200 Subject: [PATCH 1652/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.93.0 (#2047) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9a647b5ed839..97a7f881f5cb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.92.0 + 6.93.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 3650afc719f9..783e25edeb12 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.92.0 + 6.93.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 28906823850f..78439fba4bd5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.92.0 + 6.93.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index c97d84541756..4cef2ced918d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.92.0 + 6.93.0 import pom From c8f39b79252908c760d503b95919a2db964176ad Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 9 May 2025 17:55:31 +0200 Subject: [PATCH 1653/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.93.0 (#2046) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 4cef2ced918d..bcf10d7de9b2 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.92.0 + 6.93.0 test-jar test From b67de2140a2e7ec4d3ee2499fe1e9c14830e9353 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 14:05:21 -0400 Subject: [PATCH 1654/1979] chore(main): release 2.30.1 (#2041) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 24968a857c9c..24d44110255a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.30.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.0...v2.30.1) (2025-05-09) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.62.0 ([#2044](https://github.com/googleapis/java-spanner-jdbc/issues/2044)) ([92b082a](https://github.com/googleapis/java-spanner-jdbc/commit/92b082a11f14b253f2e3f369be711cd89f5279db)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.93.0 ([#2046](https://github.com/googleapis/java-spanner-jdbc/issues/2046)) ([7badfc7](https://github.com/googleapis/java-spanner-jdbc/commit/7badfc73a69119618749e7d61a2cfd2e2924039d)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.93.0 ([#2047](https://github.com/googleapis/java-spanner-jdbc/issues/2047)) ([0bb369c](https://github.com/googleapis/java-spanner-jdbc/commit/0bb369cd09d1132a5111d2686c32becefe166405)) +* Update dependency com.google.cloud:google-cloud-trace to v2.62.0 ([#2045](https://github.com/googleapis/java-spanner-jdbc/issues/2045)) ([7f43114](https://github.com/googleapis/java-spanner-jdbc/commit/7f43114856fa7ea7bef319c74620c55201cc9833)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.46.3 ([#2039](https://github.com/googleapis/java-spanner-jdbc/issues/2039)) ([6da7077](https://github.com/googleapis/java-spanner-jdbc/commit/6da70771a552ae1bc218691a3badb13fbb846107)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.47.0 ([#2043](https://github.com/googleapis/java-spanner-jdbc/issues/2043)) ([7208cbc](https://github.com/googleapis/java-spanner-jdbc/commit/7208cbc9f661db2d5908bcc3c824539bbd14cc6a)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.27 ([#2042](https://github.com/googleapis/java-spanner-jdbc/issues/2042)) ([e612954](https://github.com/googleapis/java-spanner-jdbc/commit/e61295402b9c5dbf5d64217450a2f567db2cff55)) + ## [2.30.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.29.1...v2.30.0) (2025-05-01) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index b398f8a89fd9..4ddfd3ece7ce 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.0 + 2.30.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 97a7f881f5cb..e208c4426933 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.1-SNAPSHOT + 2.30.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e4e6669005d2..d8c1b122b56e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.1-SNAPSHOT + 2.30.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e1273f78f547..caed6594281d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.0:2.30.1-SNAPSHOT +google-cloud-spanner-jdbc:2.30.1:2.30.1 From 389fa21f089188c6036bc0a5053a6fa97af04bfa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 14:57:45 -0400 Subject: [PATCH 1655/1979] chore(main): release 2.30.2-SNAPSHOT (#2048) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e208c4426933..c71d11476d27 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.1 + 2.30.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d8c1b122b56e..d1a93cd123cc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.1 + 2.30.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index caed6594281d..b12bbecad99d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.1:2.30.1 +google-cloud-spanner-jdbc:2.30.1:2.30.2-SNAPSHOT From c47b9f83604af47e2f5b80d8c6145888e4bef870 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Tue, 13 May 2025 05:29:32 -0400 Subject: [PATCH 1656/1979] chore: update linter groupd ID to the latest (#2052) * chore: update linter groupd ID to the latest Follows from https://github.com/googleapis/java-shared-config/pull/1003 * chore: update jvm to 17 in lint job * chore: reformat files --- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- java-spanner-jdbc/.kokoro/build.sh | 2 +- .../jdbc/AbstractJdbcPreparedStatement.java | 3 +- .../spanner/jdbc/AbstractJdbcResultSet.java | 1 + .../jdbc/CloudSpannerJdbcConnection.java | 12 +++-- .../spanner/jdbc/IsolationLevelConverter.java | 2 +- .../cloud/spanner/jdbc/JdbcConstants.java | 1 + .../cloud/spanner/jdbc/JdbcDataSource.java | 8 +++- .../google/cloud/spanner/jdbc/JdbcDriver.java | 6 ++- .../cloud/spanner/jdbc/JdbcSqlException.java | 12 +++-- .../google/cloud/spanner/jdbc/JsonType.java | 2 + .../cloud/spanner/jdbc/PgJsonbType.java | 2 + .../cloud/spanner/jdbc/ProtoEnumType.java | 2 + .../cloud/spanner/jdbc/ProtoMessageType.java | 2 + .../cloud/spanner/jdbc/SpannerPool.java | 8 +++- .../google/cloud/spanner/jdbc/UuidType.java | 2 + .../cloud/spanner/jdbc/DdlMockServerTest.java | 8 ++-- .../spanner/jdbc/JdbcConnectionTest.java | 15 ++++-- .../spanner/jdbc/JdbcSqlScriptVerifier.java | 1 + .../cloud/spanner/jdbc/it/SingerProto.java | 47 +++++++++++++++++++ 20 files changed, 114 insertions(+), 24 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index b91fa381f56b..4dd9974f263f 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -104,7 +104,7 @@ jobs: - uses: actions/setup-java@v4 with: distribution: temurin - java-version: 11 + java-version: 17 - run: java -version - run: .kokoro/build.sh env: diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index 502fb4fd49d3..d7dbf59de306 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -62,7 +62,7 @@ test) RETURN_CODE=$? ;; lint) - mvn com.coveo:fmt-maven-plugin:check -B -ntp + mvn com.spotify.fmt:fmt-maven-plugin:check -B -ntp RETURN_CODE=$? ;; javadoc) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java index 9c58a5239167..be8df4aff16b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcPreparedStatement.java @@ -81,8 +81,7 @@ public void addBatch(String sql) throws SQLException { @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { checkClosed(); - parameters.setParameter( - parameterIndex, /* value = */ null, sqlType, /* scaleOrLength = */ null); + parameters.setParameter(parameterIndex, /* value= */ null, sqlType, /* scaleOrLength= */ null); } @Override diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java index 652ed0b25e27..4b6ac4c130fd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcResultSet.java @@ -39,6 +39,7 @@ abstract class AbstractJdbcResultSet extends AbstractJdbcWrapper implements ResultSet { /** The underlying Cloud Spanner {@link com.google.cloud.spanner.ResultSet}. */ final com.google.cloud.spanner.ResultSet spanner; + /** Current fetch size hint for this result set. */ private int fetchSize; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java index 359854c9049a..50f1f5328f89 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java @@ -88,7 +88,9 @@ default void setTransactionTag(String tag) throws SQLException { throw new UnsupportedOperationException(); } - /** @return The transaction tag of the current transaction. */ + /** + * @return The transaction tag of the current transaction. + */ default String getTransactionTag() throws SQLException { throw new UnsupportedOperationException(); } @@ -242,7 +244,9 @@ default String getStatementTag() throws SQLException { */ void setReturnCommitStats(boolean returnCommitStats) throws SQLException; - /** @return true if this connection requests commit statistics from Cloud Spanner. */ + /** + * @return true if this connection requests commit statistics from Cloud Spanner. + */ boolean isReturnCommitStats() throws SQLException; /** @@ -359,7 +363,9 @@ default String getStatementTag() throws SQLException { */ String getConnectionUrl(); - /** @return The {@link Dialect} that is used by this connection. */ + /** + * @return The {@link Dialect} that is used by this connection. + */ default Dialect getDialect() { return Dialect.GOOGLE_STANDARD_SQL; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java index 3e3e10c9f9c1..cabf08057734 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/IsolationLevelConverter.java @@ -40,7 +40,7 @@ static IsolationLevel convertToSpanner(int jdbcIsolationLevel) throws SQLExcepti static int convertToJdbc(IsolationLevel isolationLevel) { switch (isolationLevel) { - // Translate UNSPECIFIED to SERIALIZABLE as that is the default isolation level. + // Translate UNSPECIFIED to SERIALIZABLE as that is the default isolation level. case ISOLATION_LEVEL_UNSPECIFIED: case SERIALIZABLE: return Connection.TRANSACTION_SERIALIZABLE; diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java index 164aec0ee50c..8de8c7f0ee58 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConstants.java @@ -27,6 +27,7 @@ public final class JdbcConstants { * was executed with {@link Statement#execute(String)} returned a {@link ResultSet}. */ public static final int STATEMENT_RESULT_SET = -1; + /** * Special value that is used to indicate that a statement had no result. The method {@link * Statement#getUpdateCount()} will return this value if the previous statement that was executed diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java index 026406e2b5dc..d4f415d273fd 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java @@ -114,12 +114,16 @@ public boolean isClosed() { return false; } - /** @return the JDBC URL to use for this {@link DataSource}. */ + /** + * @return the JDBC URL to use for this {@link DataSource}. + */ public String getUrl() { return url; } - /** @param url The JDBC URL to use for this {@link DataSource}. */ + /** + * @param url The JDBC URL to use for this {@link DataSource}. + */ public void setUrl(String url) { this.url = url; } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index f7bdb3b09e2f..838d3e4c049a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -196,7 +196,9 @@ static void deregister() throws SQLException { registeredDriver = null; } - /** @return {@code true} if the driver is registered against {@link DriverManager} */ + /** + * @return {@code true} if the driver is registered against {@link DriverManager} + */ static boolean isRegistered() { return registeredDriver != null; } @@ -281,7 +283,7 @@ static boolean isHibernate() { // we assume that Hibernate will (eventually) be used. Class.forName( "com.google.cloud.spanner.hibernate.SpannerDialect", - /*initialize=*/ false, + /* initialize= */ false, JdbcDriver.class.getClassLoader()); return true; } catch (Throwable ignore) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java index c36b8134a8d8..90f6df0434bc 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSqlException.java @@ -25,13 +25,19 @@ */ public interface JdbcSqlException { - /** @see Throwable#getMessage() */ + /** + * @see Throwable#getMessage() + */ String getMessage(); - /** @see Throwable#getCause() */ + /** + * @see Throwable#getCause() + */ Throwable getCause(); - /** @see SQLException#getSQLState() */ + /** + * @see SQLException#getSQLState() + */ String getSQLState(); /** Returns the gRPC error code as an int */ diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java index 3e69adea4445..747f8732ead3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JsonType.java @@ -27,11 +27,13 @@ */ public class JsonType implements SQLType { public static final JsonType INSTANCE = new JsonType(); + /** * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.JSON_VALUE; + /** * Define a short type number as well, as this is what is expected to be returned in {@link * DatabaseMetaData#getTypeInfo()}. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java index b0a819b0db72..d447233ca7c0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/PgJsonbType.java @@ -22,12 +22,14 @@ public class PgJsonbType implements SQLType { public static final PgJsonbType INSTANCE = new PgJsonbType(); + /** * Spanner/Spangres does not have any type numbers, but the code values are unique. Add 200,000 to * avoid conflicts with the type numbers in java.sql.Types. Native Cloud Spanner types already use * the range starting at 100,000 (see {@link JsonType}). */ public static final int VENDOR_TYPE_NUMBER = 200_000 + TypeCode.JSON_VALUE; + /** * Define a short type number as well, as this is what is expected to be returned in {@link * DatabaseMetaData#getTypeInfo()}. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java index 953fb73b39c5..7c710bc90d71 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoEnumType.java @@ -27,11 +27,13 @@ */ public class ProtoEnumType implements SQLType { public static final ProtoEnumType INSTANCE = new ProtoEnumType(); + /** * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.ENUM_VALUE; + /** * Define a short type number as well, as this is what is expected to be returned in {@link * DatabaseMetaData#getTypeInfo()}. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java index 2a7f6f705d8c..df5fd98a2036 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ProtoMessageType.java @@ -27,11 +27,13 @@ */ public class ProtoMessageType implements SQLType { public static final ProtoMessageType INSTANCE = new ProtoMessageType(); + /** * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.PROTO_VALUE; + /** * Define a short type number as well, as this is what is expected to be returned in {@link * DatabaseMetaData#getTypeInfo()}. diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java index 8bcbcc1952c0..2122d7dc4028 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/SpannerPool.java @@ -16,12 +16,16 @@ package com.google.cloud.spanner.jdbc; -/** @see com.google.cloud.spanner.connection.SpannerPool */ +/** + * @see com.google.cloud.spanner.connection.SpannerPool + */ @Deprecated public class SpannerPool { private SpannerPool() {} - /** @see com.google.cloud.spanner.connection.SpannerPool#closeSpannerPool() */ + /** + * @see com.google.cloud.spanner.connection.SpannerPool#closeSpannerPool() + */ @Deprecated public static void closeSpannerPool() { com.google.cloud.spanner.connection.SpannerPool.closeSpannerPool(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java index 46317b4353a4..22bf3666b8b7 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/UuidType.java @@ -27,11 +27,13 @@ */ public class UuidType implements SQLType { public static final UuidType INSTANCE = new UuidType(); + /** * Spanner does not have any type numbers, but the code values are unique. Add 100,000 to avoid * conflicts with the type numbers in java.sql.Types. */ public static final int VENDOR_TYPE_NUMBER = 100_000 + TypeCode.UUID_VALUE; + /** * Define a short type number as well, as this is what is expected to be returned in {@link * DatabaseMetaData#getTypeInfo()}. diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java index 7bca2369a713..0646a73bc497 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/DdlMockServerTest.java @@ -62,7 +62,7 @@ public void testGetDatabaseDdl() throws SQLException { mockDatabaseAdmin.addResponse( GetDatabaseDdlResponse.newBuilder().addAllStatements(expectedDdl).build()); - try (Connection connection = createConnection(/* autoCommit = */ true)) { + try (Connection connection = createConnection(/* autoCommit= */ true)) { CloudSpannerJdbcConnection spannerJdbcConnection = connection.unwrap(CloudSpannerJdbcConnection.class); List ddl = @@ -85,7 +85,7 @@ public void testDdlInAutoCommitIsTrue_succeeds() throws SQLException { .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) .build()); - try (Connection connection = createConnection(/* autoCommit = */ true)) { + try (Connection connection = createConnection(/* autoCommit= */ true)) { assertFalse( connection.createStatement().execute("create table foo (id int64) primary key (id)")); } @@ -100,7 +100,7 @@ public void testDdlInAutoCommitIsFalse_succeedsWithNoActiveTransaction() throws .setMetadata(Any.pack(UpdateDatabaseDdlMetadata.getDefaultInstance())) .build()); - try (Connection connection = createConnection(/* autoCommit = */ false)) { + try (Connection connection = createConnection(/* autoCommit= */ false)) { assertFalse( connection.createStatement().execute("create table foo (id int64) primary key (id)")); } @@ -111,7 +111,7 @@ public void testDdlInAutoCommitIsFalse_failsWithActiveTransaction() throws SQLEx mockSpanner.putStatementResult( StatementResult.update(Statement.of("update foo set bar=1 where true"), 1L)); - try (Connection connection = createConnection(/* autoCommit = */ false)) { + try (Connection connection = createConnection(/* autoCommit= */ false)) { assertFalse(connection.createStatement().execute("update foo set bar=1 where true")); SQLException exception = assertThrows( diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java index d4cfeb8d0d7f..69bb4fba8d54 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionTest.java @@ -192,7 +192,10 @@ public void testRollback() throws SQLException { @Test public void testClosedJdbcConnection() - throws SQLException, NoSuchMethodException, SecurityException, IllegalAccessException, + throws SQLException, + NoSuchMethodException, + SecurityException, + IllegalAccessException, IllegalArgumentException { testClosed(Connection.class, "getCatalog"); testClosed(Connection.class, "getWarnings"); @@ -328,14 +331,20 @@ public void testClosedJdbcConnection() } private void testClosed(Class clazz, String name) - throws NoSuchMethodException, SecurityException, SQLException, IllegalAccessException, + throws NoSuchMethodException, + SecurityException, + SQLException, + IllegalAccessException, IllegalArgumentException { testClosed(clazz, name, null, null); } private void testClosed( Class clazz, String name, Class[] paramTypes, Object[] args) - throws NoSuchMethodException, SecurityException, SQLException, IllegalAccessException, + throws NoSuchMethodException, + SecurityException, + SQLException, + IllegalAccessException, IllegalArgumentException { Method method = clazz.getDeclaredMethod(name, paramTypes); testInvokeMethodOnClosedConnection(method, args); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java index 51e1213370d1..10a9327b42c0 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcSqlScriptVerifier.java @@ -119,6 +119,7 @@ protected Object getFirstValue() throws Exception { public static class JdbcGenericConnection extends GenericConnection { private final CloudSpannerJdbcConnection connection; + /** * Use this to strip comments from a statement before the statement is executed. This should * only be used when the connection is used in a unit test with a mocked underlying connection. diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java index 00e44bb30873..2a93d1c980a3 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/SingerProto.java @@ -28,6 +28,7 @@ public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLi public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); } + /** Protobuf enum {@code examples.spanner.music.Genre} */ public enum Genre implements com.google.protobuf.ProtocolMessageEnum { /** POP = 0; */ @@ -43,10 +44,13 @@ public enum Genre implements com.google.protobuf.ProtocolMessageEnum { /** POP = 0; */ public static final int POP_VALUE = 0; + /** JAZZ = 1; */ public static final int JAZZ_VALUE = 1; + /** FOLK = 2; */ public static final int FOLK_VALUE = 2; + /** ROCK = 3; */ public static final int ROCK_VALUE = 3; @@ -144,6 +148,7 @@ public interface SingerInfoOrBuilder * @return Whether the singerId field is set. */ boolean hasSingerId(); + /** * optional int64 singer_id = 1; * @@ -157,12 +162,14 @@ public interface SingerInfoOrBuilder * @return Whether the birthDate field is set. */ boolean hasBirthDate(); + /** * optional string birth_date = 2; * * @return The birthDate. */ String getBirthDate(); + /** * optional string birth_date = 2; * @@ -176,12 +183,14 @@ public interface SingerInfoOrBuilder * @return Whether the nationality field is set. */ boolean hasNationality(); + /** * optional string nationality = 3; * * @return The nationality. */ String getNationality(); + /** * optional string nationality = 3; * @@ -195,12 +204,14 @@ public interface SingerInfoOrBuilder * @return Whether the genre field is set. */ boolean hasGenre(); + /** * optional .examples.spanner.music.Genre genre = 4; * * @return The enum numeric value on the wire for genre. */ int getGenreValue(); + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -208,12 +219,14 @@ public interface SingerInfoOrBuilder */ Genre getGenre(); } + /** Protobuf type {@code examples.spanner.music.SingerInfo} */ public static final class SingerInfo extends com.google.protobuf.GeneratedMessageV3 implements // @@protoc_insertion_point(message_implements:examples.spanner.music.SingerInfo) SingerInfoOrBuilder { private static final long serialVersionUID = 0L; + // Use SingerInfo.newBuilder() to construct. private SingerInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); @@ -244,6 +257,7 @@ protected FieldAccessorTable internalGetFieldAccessorTable() { private int bitField0_; public static final int SINGER_ID_FIELD_NUMBER = 1; private long singerId_ = 0L; + /** * optional int64 singer_id = 1; * @@ -253,6 +267,7 @@ protected FieldAccessorTable internalGetFieldAccessorTable() { public boolean hasSingerId() { return ((bitField0_ & 0x00000001) != 0); } + /** * optional int64 singer_id = 1; * @@ -267,6 +282,7 @@ public long getSingerId() { @SuppressWarnings("serial") private volatile Object birthDate_ = ""; + /** * optional string birth_date = 2; * @@ -276,6 +292,7 @@ public long getSingerId() { public boolean hasBirthDate() { return ((bitField0_ & 0x00000002) != 0); } + /** * optional string birth_date = 2; * @@ -293,6 +310,7 @@ public String getBirthDate() { return s; } } + /** * optional string birth_date = 2; * @@ -315,6 +333,7 @@ public com.google.protobuf.ByteString getBirthDateBytes() { @SuppressWarnings("serial") private volatile Object nationality_ = ""; + /** * optional string nationality = 3; * @@ -324,6 +343,7 @@ public com.google.protobuf.ByteString getBirthDateBytes() { public boolean hasNationality() { return ((bitField0_ & 0x00000004) != 0); } + /** * optional string nationality = 3; * @@ -341,6 +361,7 @@ public String getNationality() { return s; } } + /** * optional string nationality = 3; * @@ -361,6 +382,7 @@ public com.google.protobuf.ByteString getNationalityBytes() { public static final int GENRE_FIELD_NUMBER = 4; private int genre_ = 0; + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -370,6 +392,7 @@ public com.google.protobuf.ByteString getNationalityBytes() { public boolean hasGenre() { return ((bitField0_ & 0x00000008) != 0); } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -379,6 +402,7 @@ public boolean hasGenre() { public int getGenreValue() { return genre_; } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -593,6 +617,7 @@ protected Builder newBuilderForType(BuilderParent parent) { Builder builder = new Builder(parent); return builder; } + /** Protobuf type {@code examples.spanner.music.SingerInfo} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder @@ -808,6 +833,7 @@ public Builder mergeFrom( private int bitField0_; private long singerId_; + /** * optional int64 singer_id = 1; * @@ -817,6 +843,7 @@ public Builder mergeFrom( public boolean hasSingerId() { return ((bitField0_ & 0x00000001) != 0); } + /** * optional int64 singer_id = 1; * @@ -826,6 +853,7 @@ public boolean hasSingerId() { public long getSingerId() { return singerId_; } + /** * optional int64 singer_id = 1; * @@ -839,6 +867,7 @@ public Builder setSingerId(long value) { onChanged(); return this; } + /** * optional int64 singer_id = 1; * @@ -852,6 +881,7 @@ public Builder clearSingerId() { } private Object birthDate_ = ""; + /** * optional string birth_date = 2; * @@ -860,6 +890,7 @@ public Builder clearSingerId() { public boolean hasBirthDate() { return ((bitField0_ & 0x00000002) != 0); } + /** * optional string birth_date = 2; * @@ -876,6 +907,7 @@ public String getBirthDate() { return (String) ref; } } + /** * optional string birth_date = 2; * @@ -892,6 +924,7 @@ public com.google.protobuf.ByteString getBirthDateBytes() { return (com.google.protobuf.ByteString) ref; } } + /** * optional string birth_date = 2; * @@ -907,6 +940,7 @@ public Builder setBirthDate(String value) { onChanged(); return this; } + /** * optional string birth_date = 2; * @@ -918,6 +952,7 @@ public Builder clearBirthDate() { onChanged(); return this; } + /** * optional string birth_date = 2; * @@ -936,6 +971,7 @@ public Builder setBirthDateBytes(com.google.protobuf.ByteString value) { } private Object nationality_ = ""; + /** * optional string nationality = 3; * @@ -944,6 +980,7 @@ public Builder setBirthDateBytes(com.google.protobuf.ByteString value) { public boolean hasNationality() { return ((bitField0_ & 0x00000004) != 0); } + /** * optional string nationality = 3; * @@ -960,6 +997,7 @@ public String getNationality() { return (String) ref; } } + /** * optional string nationality = 3; * @@ -976,6 +1014,7 @@ public com.google.protobuf.ByteString getNationalityBytes() { return (com.google.protobuf.ByteString) ref; } } + /** * optional string nationality = 3; * @@ -991,6 +1030,7 @@ public Builder setNationality(String value) { onChanged(); return this; } + /** * optional string nationality = 3; * @@ -1002,6 +1042,7 @@ public Builder clearNationality() { onChanged(); return this; } + /** * optional string nationality = 3; * @@ -1020,6 +1061,7 @@ public Builder setNationalityBytes(com.google.protobuf.ByteString value) { } private int genre_ = 0; + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -1029,6 +1071,7 @@ public Builder setNationalityBytes(com.google.protobuf.ByteString value) { public boolean hasGenre() { return ((bitField0_ & 0x00000008) != 0); } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -1038,6 +1081,7 @@ public boolean hasGenre() { public int getGenreValue() { return genre_; } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -1050,6 +1094,7 @@ public Builder setGenreValue(int value) { onChanged(); return this; } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -1060,6 +1105,7 @@ public Genre getGenre() { Genre result = Genre.forNumber(genre_); return result == null ? Genre.UNRECOGNIZED : result; } + /** * optional .examples.spanner.music.Genre genre = 4; * @@ -1075,6 +1121,7 @@ public Builder setGenre(Genre value) { onChanged(); return this; } + /** * optional .examples.spanner.music.Genre genre = 4; * From 1774e788b4223f8d2dffe7117a4ee97785b8b2eb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 13 May 2025 11:34:18 +0200 Subject: [PATCH 1657/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.50.0 (#2051) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 783e25edeb12..75cf7b654d32 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.49.0 + 1.50.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 78439fba4bd5..b87e4f7d8476 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.49.0 + 1.50.0 pom import From 95baec843d22fc1c78c2dee1ccbc39c403e7552f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 13 May 2025 11:34:29 +0200 Subject: [PATCH 1658/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.60.0 (#2050) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index c32aba479059..d3d34da8ff34 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a648f3ba6a9b..a32d14b36ba6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 75cf7b654d32..a29d2534449b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b87e4f7d8476..be390ad9fd1f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index bcf10d7de9b2..d65e35e78f22 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 0cd43877cb44..8b573fd65d00 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.59.0 + 26.60.0 import pom From 197ec9d5cb2517d5e5bb2d51c96ef961cccd018d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 13 May 2025 11:34:41 +0200 Subject: [PATCH 1659/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.30.1 (#2049) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index b16b39dc8f08..87ee932804b2 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.0 + 2.30.1 From 957c325df7622ce0cee42f7e8325c7ad49c94a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 13 May 2025 17:01:38 +0200 Subject: [PATCH 1660/1979] test: enable proto column tests on emulator (#2056) --- .../spanner/jdbc/it/ITJdbcConnectTest.java | 5 ++-- .../spanner/jdbc/it/ITProtoColumnsTest.java | 23 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index 17bd657854a0..b42e81e5e593 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -27,8 +27,9 @@ import com.google.cloud.spanner.jdbc.CloudSpannerJdbcConnection; import com.google.cloud.spanner.jdbc.JdbcDataSource; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -229,7 +230,7 @@ public void testConnectWithDataSourceWithConflictingValues() throws SQLException public void testConnectWithOAuthToken() throws Exception { GoogleCredentials credentials; if (hasValidKeyFile()) { - credentials = GoogleCredentials.fromStream(new FileInputStream(getKeyFile())); + credentials = GoogleCredentials.fromStream(Files.newInputStream(Paths.get(getKeyFile()))); } else { try { credentials = GoogleCredentials.getApplicationDefault(); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java index aa09aea6efee..74a38183491d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITProtoColumnsTest.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.jdbc.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.SPANNER_EMULATOR_HOST; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -34,7 +36,6 @@ import com.google.cloud.spanner.jdbc.ProtoMessageType; import com.google.cloud.spanner.jdbc.it.SingerProto.Genre; import com.google.cloud.spanner.jdbc.it.SingerProto.SingerInfo; -import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.cloud.spanner.testing.RemoteSpannerHelper; import java.io.InputStream; import java.sql.Connection; @@ -68,8 +69,6 @@ public static boolean isUsingGraalVm() { @BeforeClass public static void setup() throws Exception { - assumeFalse( - "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); RemoteSpannerHelper testHelper = env.getTestHelper(); final String projectId = testHelper.getInstanceId().getProject(); @@ -87,7 +86,12 @@ public static void setup() throws Exception { .setDialect(Dialect.GOOGLE_STANDARD_SQL) .setProtoDescriptors(in) .build(); - final String host = SpannerTestHost.getHost(); + final String host; + if (isUsingEmulator()) { + host = System.getenv(SPANNER_EMULATOR_HOST); + } else { + host = SpannerTestHost.getHost(); + } database = databaseAdminClient @@ -109,6 +113,9 @@ public static void setup() throws Exception { in.close(); url = "jdbc:cloudspanner://" + host + "/" + database.getId(); + if (isUsingEmulator()) { + url += "?autoConfigEmulator=true"; + } } @AfterClass @@ -121,8 +128,6 @@ public static void teardown() { @Test public void testNonNullElements() throws Exception { - assumeFalse( - "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); SingerInfo singerInfo = SingerInfo.newBuilder() @@ -166,8 +171,6 @@ public void testNonNullElements() throws Exception { @Test public void testNullElements() throws Exception { - assumeFalse( - "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); try (Connection connection = DriverManager.getConnection(url); PreparedStatement ps = @@ -201,8 +204,6 @@ public void testNullElements() throws Exception { @Test public void testUntypedNullElements() throws Exception { - assumeFalse( - "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); try (Connection connection = DriverManager.getConnection(url); PreparedStatement ps = @@ -231,8 +232,6 @@ public void testUntypedNullElements() throws Exception { @Test public void testInterCompatibility() throws Exception { - assumeFalse( - "Proto columns is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); assumeFalse("Skipping tests on GraalVM", isUsingGraalVm()); SingerInfo singerInfo = SingerInfo.newBuilder() From 6a0f63ebb39bffca0ebd7f24ae906be0f71ccf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 13 May 2025 17:01:49 +0200 Subject: [PATCH 1661/1979] chore: move generator into jdbc package (#2055) --- java-spanner-jdbc/clirr-ignored-differences.xml | 4 ++++ java-spanner-jdbc/pom.xml | 2 +- .../ConnectionPropertiesHelper.java | 17 ++++++++--------- .../google/cloud/spanner/jdbc/JdbcDriver.java | 1 - .../ConnectionPropertiesFileGenerator.java | 3 ++- .../cloud/spanner/jdbc/JdbcDriverTest.java | 1 - 6 files changed, 15 insertions(+), 13 deletions(-) rename java-spanner-jdbc/src/main/java/com/google/cloud/spanner/{connection => jdbc}/ConnectionPropertiesHelper.java (80%) rename java-spanner-jdbc/src/test/java/com/google/cloud/spanner/{connection => jdbc}/ConnectionPropertiesFileGenerator.java (96%) diff --git a/java-spanner-jdbc/clirr-ignored-differences.xml b/java-spanner-jdbc/clirr-ignored-differences.xml index 547c9c44c7f3..f8e168c5f0b7 100644 --- a/java-spanner-jdbc/clirr-ignored-differences.xml +++ b/java-spanner-jdbc/clirr-ignored-differences.xml @@ -123,4 +123,8 @@ com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection com.google.cloud.spanner.DatabaseId getDatabaseId() + + 8001 + com/google/cloud/spanner/connection/ConnectionPropertiesHelper + diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c71d11476d27..c50b1e07777b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -351,7 +351,7 @@ java - com.google.cloud.spanner.connection.ConnectionPropertiesFileGenerator + com.google.cloud.spanner.jdbc.ConnectionPropertiesFileGenerator test false diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesHelper.java similarity index 80% rename from java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java rename to java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesHelper.java index cde651e02913..4f8db86b0bfb 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/connection/ConnectionPropertiesHelper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesHelper.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.google.cloud.spanner.connection; +package com.google.cloud.spanner.jdbc; -import com.google.api.core.InternalApi; +import com.google.cloud.spanner.connection.ConnectionProperties; +import com.google.cloud.spanner.connection.ConnectionProperty; import com.google.common.collect.ImmutableList; import java.sql.DriverPropertyInfo; import java.util.Arrays; @@ -26,16 +27,14 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -// TODO: Remove this class when the Connection API has made the list of properties public. -@InternalApi -public class ConnectionPropertiesHelper { - public static ImmutableList> VALID_CONNECTION_PROPERTIES = +class ConnectionPropertiesHelper { + static ImmutableList> VALID_CONNECTION_PROPERTIES = ImmutableList.copyOf( - ConnectionProperties.CONNECTION_PROPERTIES.values().stream() + ConnectionProperties.VALID_CONNECTION_PROPERTIES.stream() .sorted(Comparator.comparing(ConnectionProperty::getName)) .collect(Collectors.toList())); - public static DriverPropertyInfo toDriverPropertyInfo( + static DriverPropertyInfo toDriverPropertyInfo( String connectionUri, ConnectionProperty connectionProperty) { DriverPropertyInfo result = new DriverPropertyInfo( @@ -56,7 +55,7 @@ public static DriverPropertyInfo toDriverPropertyInfo( return result; } - public static String getConnectionPropertyName(ConnectionProperty connectionProperty) { + static String getConnectionPropertyName(ConnectionProperty connectionProperty) { return connectionProperty.getName(); } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 838d3e4c049a..120880fee29d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -23,7 +23,6 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptionsHelper; -import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.ConnectionProperty; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Suppliers; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java similarity index 96% rename from java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java rename to java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java index 4307fbcb0946..9efc63b9ed4e 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/connection/ConnectionPropertiesFileGenerator.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package com.google.cloud.spanner.connection; +package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.connection.ConnectionProperty; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java index 494233fafc4e..9ae33fa6f294 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDriverTest.java @@ -26,7 +26,6 @@ import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.MockSpannerServiceImpl; -import com.google.cloud.spanner.connection.ConnectionPropertiesHelper; import com.google.cloud.spanner.connection.SpannerPool; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; From 8616f5bc326c5a80d979b2f3d9128ab0dfa77e15 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 May 2025 17:23:27 +0200 Subject: [PATCH 1662/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.48.0 (#2057) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index d74a2b264260..667eb33aeb2f 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.47.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.48.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index fcb138739ea4..49bf3f1e1f9c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.47.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.48.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index f8ab2d6e516f..af1210bdcbf4 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.47.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.48.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index fa345ea0a4c2..10457a1ace21 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.47.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.48.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c50b1e07777b..c2dc5c04321f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.47.0 + 3.48.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d3d34da8ff34..83374c8bc4e9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.47.0 + 3.48.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a32d14b36ba6..170fd5af72a3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.47.0 + 3.48.0 From 9277909fcdcb53928c5c6985c4fc97e263cac13f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 May 2025 17:28:15 +0200 Subject: [PATCH 1663/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.63.0 (#2058) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c2dc5c04321f..aee9d8b585ff 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.62.0 + 2.63.0 test From b49a49aef2a43dfac2f5676e71c186a31fcd4402 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 May 2025 17:28:28 +0200 Subject: [PATCH 1664/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.63.0 (#2059) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index aee9d8b585ff..d490dcf8d23f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.62.0 + 2.63.0 test From 08e794fc9c22463974ba8585670c12f72fce7f0a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 19 May 2025 17:28:40 +0200 Subject: [PATCH 1665/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.6 (#2060) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a29d2534449b..27a6ccb9bac1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.5 + 2024.1.6 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index be390ad9fd1f..e97e948d0ece 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.5 + 2024.1.6 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d65e35e78f22..58b98b1d5cd3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.5 + 2024.1.6 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 8b573fd65d00..e7e1ff505477 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.5 + 2024.1.6 import pom From 96d829779b48110932705b10ba0061c78eb8469b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 22 May 2025 18:43:47 +0200 Subject: [PATCH 1666/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.94.0 (#2064) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 58b98b1d5cd3..09ca8e152ea1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.93.0 + 6.94.0 test-jar test From 06414cd92de3107044c2e41d130a58e76e5f22ef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 22 May 2025 18:44:37 +0200 Subject: [PATCH 1667/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.94.0 (#2065) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d490dcf8d23f..8a171bd9bbc3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.93.0 + 6.94.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 27a6ccb9bac1..2d19f32724b9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.93.0 + 6.94.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index e97e948d0ece..b9fe1385dd8e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.93.0 + 6.94.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 09ca8e152ea1..2b8bd89147d8 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.93.0 + 6.94.0 import pom From 102e119dd475cde2af1a40857e6d6d062d62447e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 13:08:11 -0400 Subject: [PATCH 1668/1979] chore(main): release 2.30.2 (#2054) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 13 +++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 24d44110255a..cc27fb6c6b7b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [2.30.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.1...v2.30.2) (2025-05-22) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.63.0 ([#2058](https://github.com/googleapis/java-spanner-jdbc/issues/2058)) ([da82fea](https://github.com/googleapis/java-spanner-jdbc/commit/da82feacf3de8c7d441cf8686c6f7385f5274bc9)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.94.0 ([#2064](https://github.com/googleapis/java-spanner-jdbc/issues/2064)) ([1b789e5](https://github.com/googleapis/java-spanner-jdbc/commit/1b789e50a4a3b06782923479cc1024ee7c2e102b)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.94.0 ([#2065](https://github.com/googleapis/java-spanner-jdbc/issues/2065)) ([1154c13](https://github.com/googleapis/java-spanner-jdbc/commit/1154c13ae1ca44a9a52cafc2d24628f53a9d121e)) +* Update dependency com.google.cloud:google-cloud-trace to v2.63.0 ([#2059](https://github.com/googleapis/java-spanner-jdbc/issues/2059)) ([86a49bb](https://github.com/googleapis/java-spanner-jdbc/commit/86a49bbf29d0752aa2fdcf5fe73587f72fc6630e)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.48.0 ([#2057](https://github.com/googleapis/java-spanner-jdbc/issues/2057)) ([c6f47d4](https://github.com/googleapis/java-spanner-jdbc/commit/c6f47d4753e73ef58e21d5d13f4d380b67a80a55)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.50.0 ([#2051](https://github.com/googleapis/java-spanner-jdbc/issues/2051)) ([1d2a3b7](https://github.com/googleapis/java-spanner-jdbc/commit/1d2a3b728f5a56b948412bea493e2b5b70a89ab2)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.6 ([#2060](https://github.com/googleapis/java-spanner-jdbc/issues/2060)) ([91c30e4](https://github.com/googleapis/java-spanner-jdbc/commit/91c30e425fdb8a1a4a9d55fdc5df254ff17aa201)) + ## [2.30.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.0...v2.30.1) (2025-05-09) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 4ddfd3ece7ce..0409981be79b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.1 + 2.30.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8a171bd9bbc3..12159cf86227 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.2-SNAPSHOT + 2.30.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d1a93cd123cc..abcfd572261d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.2-SNAPSHOT + 2.30.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b12bbecad99d..d2ed8e8c6596 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.1:2.30.2-SNAPSHOT +google-cloud-spanner-jdbc:2.30.2:2.30.2 From 3b68390c4619ce180880cb0270509e0582c62e02 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 21:39:15 +0200 Subject: [PATCH 1669/1979] chore(main): release 2.30.3-SNAPSHOT (#2066) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 12159cf86227..214acbd50faf 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.2 + 2.30.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index abcfd572261d..3bbbedd8ca75 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.2 + 2.30.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d2ed8e8c6596..065d238631cc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.2:2.30.2 +google-cloud-spanner-jdbc:2.30.2:2.30.3-SNAPSHOT From 82c1c630c81f76c2c1e10d020df98b7710a4876e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 May 2025 13:42:09 +0200 Subject: [PATCH 1670/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.61.0 (#2069) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 83374c8bc4e9..f1b9e2ea74d7 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 170fd5af72a3..c4a2845e94eb 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 2d19f32724b9..4ce798b251d4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b9fe1385dd8e..7c55fd2cfc41 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 2b8bd89147d8..42a21b6fdb9d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index e7e1ff505477..326f6a131be3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.60.0 + 26.61.0 import pom From 2a079f5e7ed29aed5143256d9ae05f945a99c656 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 May 2025 13:42:19 +0200 Subject: [PATCH 1671/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.30.2 (#2068) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 87ee932804b2..d4473772af09 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.1 + 2.30.2 From 980ac80931b5532f77cb2932668aa9815cd4ad02 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 May 2025 13:42:41 +0200 Subject: [PATCH 1672/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.0 (#2067) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 42a21b6fdb9d..7251ed3c6290 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.5 + 3.5.0 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 326f6a131be3..7bab0db7fa51 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.5 + 3.5.0 From 4453cb659242f19ccbce0f093811102ad23f551f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 May 2025 13:43:03 +0200 Subject: [PATCH 1673/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.0 (#2063) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 4ce798b251d4..a9279a6b29e1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.5 + 3.5.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 7c55fd2cfc41..59d1a8118fc1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.4.5 + 3.5.0 From b40b56685af48b8ccad29e2269ae0f8022f68310 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 27 May 2025 13:43:24 +0200 Subject: [PATCH 1674/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.0 (#2062) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f1b9e2ea74d7..ded824cc6659 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.4.5 + 3.5.0 test From c56efd8982ffacd168bc735cc62fa6eec6007fab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:19:18 +0200 Subject: [PATCH 1675/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.95.0 (#2079) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 7251ed3c6290..8c51821661bc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.94.0 + 6.95.0 test-jar test From 709fd45751aa3da820a2788f8e1d2e6ea2065f19 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:19:31 +0200 Subject: [PATCH 1676/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.64.0 (#2078) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 214acbd50faf..3ba6d886a728 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.63.0 + 2.64.0 test From 48015d587d76321c79fb75b0e391167407911273 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:19:42 +0200 Subject: [PATCH 1677/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.21.1 (#2076) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 8c51821661bc..3f33db8ef86e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 1.21.0 + 1.21.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 7bab0db7fa51..e3923a040669 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.21.0 + 1.21.1 import pom From 9313f64734f38f68236d11c653a090ac7a7b59a8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:19:55 +0200 Subject: [PATCH 1678/1979] deps: update dependency org.testcontainers:testcontainers to v1.21.1 (#2075) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3ba6d886a728..f25e5bcd0e59 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.21.0 + 1.21.1 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ded824cc6659..145524f70cdd 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.21.0 + 1.21.1 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c4a2845e94eb..c4838e0eee15 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.21.0 + 1.21.1 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a9279a6b29e1..db2559a927ed 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 1.21.0 + 1.21.1 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 59d1a8118fc1..7265efbe501c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.21.0 + 1.21.1 test From cf0c953490f83584a688d34280c2eb48afad1b68 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:20:06 +0200 Subject: [PATCH 1679/1979] deps: update dependency org.postgresql:postgresql to v42.7.6 (#2074) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 7265efbe501c..9b0ee622ea69 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -72,7 +72,7 @@ org.postgresql postgresql - 42.7.5 + 42.7.6 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index e3923a040669..f808d9a3fb76 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.5 + 42.7.6 org.testcontainers From c68b802de29e1cd9811b906961603bcf67cfad6a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:20:18 +0200 Subject: [PATCH 1680/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.35.0 (#2073) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f25e5bcd0e59..efe71b0661e3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -204,7 +204,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.34.0 + 0.35.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index db2559a927ed..ba405b2e7b6f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -78,7 +78,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.34.0 + 0.35.0 com.google.cloud.opentelemetry diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 9b0ee622ea69..352a69646ba0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.34.0 + 0.35.0 com.google.cloud.opentelemetry From 8ebbbaed6e818977be7f379c13ca594590a30da9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:20:33 +0200 Subject: [PATCH 1681/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.35.0 (#2072) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index ba405b2e7b6f..1e77b08bdf35 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-metrics - 0.34.0 + 0.35.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 352a69646ba0..9a735e3ab85f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -88,7 +88,7 @@ com.google.cloud.opentelemetry exporter-metrics - 0.34.0 + 0.35.0 From 88893897d17042d6169d16a1fb6a0379fd35b8ad Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:21:28 +0200 Subject: [PATCH 1682/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.5.1 (#2071) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 145524f70cdd..4b7f76ab166b 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.5.0 + 3.5.1 com.google.cloud.jdbc.quickperf.QuickPerf From 9c8493ee1f02a6dc0c56efc5de08d039520f885a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 17:42:43 +0200 Subject: [PATCH 1683/1979] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.6.1 (#2077) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index d4473772af09..ec9a9033f01d 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.6.0 + 3.6.1 add-snippets-source diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3bbbedd8ca75..9c8297a6fcce 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.6.0 + 3.6.1 add-snippets-source From 9c9ed4720ae88efe737ae3782f6c958f0ae94b84 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 18:07:34 +0200 Subject: [PATCH 1684/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.64.0 (#2081) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index efe71b0661e3..a852cc8812cd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.63.0 + 2.64.0 test From 625503eba6e8b3d152e5c60a26a3500fff3af062 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 18:07:47 +0200 Subject: [PATCH 1685/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.95.0 (#2080) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a852cc8812cd..f10efd3753e2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.94.0 + 6.95.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 1e77b08bdf35..40b2f1cf82cc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.94.0 + 6.95.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 9a735e3ab85f..4547612ee0d8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.94.0 + 6.95.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 3f33db8ef86e..4e8624351d2c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.94.0 + 6.95.0 import pom From 2a9af6ac1d76ba80fc1551c8afad1d954bbbcde8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 18:34:47 +0200 Subject: [PATCH 1686/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.51.0 (#2083) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 40b2f1cf82cc..43a930fbbf93 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.50.0 + 1.51.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4547612ee0d8..7962d7306b88 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.50.0 + 1.51.0 pom import From 18f374691a3a8cd807c7d7053c5e0eae4e7a9c5c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 9 Jun 2025 18:35:07 +0200 Subject: [PATCH 1687/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.49.0 (#2082) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 667eb33aeb2f..57c18dcb73b2 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.48.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.49.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 49bf3f1e1f9c..b2565b8eaae9 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.48.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index af1210bdcbf4..80881c2910e1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.48.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 10457a1ace21..cf82898b7954 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.48.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f10efd3753e2..80aa212f27c1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.48.0 + 3.49.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4b7f76ab166b..4ac5fff3fd87 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.48.0 + 3.49.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c4838e0eee15..11e7fb312d5e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.48.0 + 3.49.0 From 731be02821d4659b0daa6071727609488507f29c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 19:50:33 +0200 Subject: [PATCH 1688/1979] chore(main): release 2.30.3 (#2070) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index cc27fb6c6b7b..432ea76f9e0a 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.30.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.2...v2.30.3) (2025-06-09) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.64.0 ([#2078](https://github.com/googleapis/java-spanner-jdbc/issues/2078)) ([afe3977](https://github.com/googleapis/java-spanner-jdbc/commit/afe39772a4945254c1850d673ee14dc826eb4bc1)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.95.0 ([#2079](https://github.com/googleapis/java-spanner-jdbc/issues/2079)) ([ce8db80](https://github.com/googleapis/java-spanner-jdbc/commit/ce8db80fd7b352c565ed1a3031795e3f23d90f04)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.95.0 ([#2080](https://github.com/googleapis/java-spanner-jdbc/issues/2080)) ([1802eec](https://github.com/googleapis/java-spanner-jdbc/commit/1802eecc6b9c3d81d05caf40673b1104c019b550)) +* Update dependency com.google.cloud:google-cloud-trace to v2.64.0 ([#2081](https://github.com/googleapis/java-spanner-jdbc/issues/2081)) ([8051cc4](https://github.com/googleapis/java-spanner-jdbc/commit/8051cc41fa55abd6b9b26218bbb9900b63b21390)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.49.0 ([#2082](https://github.com/googleapis/java-spanner-jdbc/issues/2082)) ([ffdf940](https://github.com/googleapis/java-spanner-jdbc/commit/ffdf940503a5e13367d1874875eaa40570af96c4)) +* Update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.35.0 ([#2072](https://github.com/googleapis/java-spanner-jdbc/issues/2072)) ([818e569](https://github.com/googleapis/java-spanner-jdbc/commit/818e5693162e25298fd3ee2580063c5c458ad638)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.35.0 ([#2073](https://github.com/googleapis/java-spanner-jdbc/issues/2073)) ([7c352f4](https://github.com/googleapis/java-spanner-jdbc/commit/7c352f403873116bd58da968c1c2613b007a43fa)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.51.0 ([#2083](https://github.com/googleapis/java-spanner-jdbc/issues/2083)) ([34a2b0a](https://github.com/googleapis/java-spanner-jdbc/commit/34a2b0a066cb74bda697dc83c061810d12f4c300)) +* Update dependency org.postgresql:postgresql to v42.7.6 ([#2074](https://github.com/googleapis/java-spanner-jdbc/issues/2074)) ([7faf24d](https://github.com/googleapis/java-spanner-jdbc/commit/7faf24dee74706af47fb61a3fb0c82b4ed91ce73)) +* Update dependency org.springframework.boot:spring-boot to v3.5.0 ([#2062](https://github.com/googleapis/java-spanner-jdbc/issues/2062)) ([d82de6f](https://github.com/googleapis/java-spanner-jdbc/commit/d82de6f6e2d662877d2985e8fe6f49f27126e094)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.0 ([#2063](https://github.com/googleapis/java-spanner-jdbc/issues/2063)) ([dcae562](https://github.com/googleapis/java-spanner-jdbc/commit/dcae5626e4e0721045864f29abf97571b8c1fa6c)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.0 ([#2067](https://github.com/googleapis/java-spanner-jdbc/issues/2067)) ([668f7f6](https://github.com/googleapis/java-spanner-jdbc/commit/668f7f6d42ff252f46a19452ffdf922eb4f163c0)) +* Update dependency org.testcontainers:testcontainers to v1.21.1 ([#2075](https://github.com/googleapis/java-spanner-jdbc/issues/2075)) ([82520a9](https://github.com/googleapis/java-spanner-jdbc/commit/82520a92ce3b798ead16d356befc46d2a6abf288)) +* Update dependency org.testcontainers:testcontainers-bom to v1.21.1 ([#2076](https://github.com/googleapis/java-spanner-jdbc/issues/2076)) ([ace1375](https://github.com/googleapis/java-spanner-jdbc/commit/ace13756d0280f2380e10c8bfc75636ac93c66c1)) + ## [2.30.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.1...v2.30.2) (2025-05-22) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 0409981be79b..7acc638acc56 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.2 + 2.30.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 80aa212f27c1..62a3f33f9726 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.3-SNAPSHOT + 2.30.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9c8297a6fcce..df85068a19b4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.3-SNAPSHOT + 2.30.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 065d238631cc..c2789bb4bcbc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.2:2.30.3-SNAPSHOT +google-cloud-spanner-jdbc:2.30.3:2.30.3 From 03c8dd11f1618be872626371598ba33e560b826c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 10:13:05 +0200 Subject: [PATCH 1689/1979] chore(main): release 2.30.4-SNAPSHOT (#2084) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 62a3f33f9726..f7b808f6f8b8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.3 + 2.30.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index df85068a19b4..6cd4bb5b58dc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.3 + 2.30.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c2789bb4bcbc..c9a0dd35e1a3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.3:2.30.3 +google-cloud-spanner-jdbc:2.30.3:2.30.4-SNAPSHOT From 9552c0aad7a3e4910576a1eb3942e9bba2db101f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 10 Jun 2025 10:13:25 +0200 Subject: [PATCH 1690/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.95.1 (#2086) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f7b808f6f8b8..e9112cacdd8f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.0 + 6.95.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 43a930fbbf93..fbc95e39131f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.0 + 6.95.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 7962d7306b88..a9558ba5621f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.0 + 6.95.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 4e8624351d2c..60f1613d6359 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.0 + 6.95.1 import pom From 14647162579b0c0ca70765bd65302aa7bb4ef00b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 10 Jun 2025 10:59:30 +0200 Subject: [PATCH 1691/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.95.1 (#2085) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 60f1613d6359..e79894384285 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.95.0 + 6.95.1 test-jar test From 517c65d2ed813aa8b95788a619eb4974778f9c9c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:10:52 +0200 Subject: [PATCH 1692/1979] chore(main): release 2.30.4 (#2087) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 8 ++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 432ea76f9e0a..596968055ee3 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [2.30.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.3...v2.30.4) (2025-06-10) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner to v6.95.1 ([#2085](https://github.com/googleapis/java-spanner-jdbc/issues/2085)) ([e255f89](https://github.com/googleapis/java-spanner-jdbc/commit/e255f897007e3651ca243efd0beae0926ab8d1b7)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.95.1 ([#2086](https://github.com/googleapis/java-spanner-jdbc/issues/2086)) ([fd03d31](https://github.com/googleapis/java-spanner-jdbc/commit/fd03d312891a06ed7465e596802f7141b2966c3b)) + ## [2.30.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.2...v2.30.3) (2025-06-09) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7acc638acc56..7a1e37212bf9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.3 + 2.30.4 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.4' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.4" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e9112cacdd8f..763796a7c0a9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.4-SNAPSHOT + 2.30.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6cd4bb5b58dc..728e2514d1b2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.4-SNAPSHOT + 2.30.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c9a0dd35e1a3..4b64df8c169c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.3:2.30.4-SNAPSHOT +google-cloud-spanner-jdbc:2.30.4:2.30.4 From 475f745e502d8cbfaa683e99c3546c1a564cf0b7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:46:05 +0200 Subject: [PATCH 1693/1979] chore(main): release 2.30.5-SNAPSHOT (#2088) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 763796a7c0a9..c50a25eef84f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.4 + 2.30.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 728e2514d1b2..5a336430e8a4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.4 + 2.30.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4b64df8c169c..7664cf536dee 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.4:2.30.4 +google-cloud-spanner-jdbc:2.30.4:2.30.5-SNAPSHOT From cc9e0f320d81efc3c0a7e6383809e00c91e4df63 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:37:21 +0200 Subject: [PATCH 1694/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.62.0 (#2090) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4ac5fff3fd87..05def68a3bc1 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 11e7fb312d5e..ea41057c6d76 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index fbc95e39131f..fbacf643e20d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a9558ba5621f..857cccc1abc2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index e79894384285..9f0aaa84b55d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index f808d9a3fb76..1eb65e65f452 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.61.0 + 26.62.0 import pom From f6d7de63988263fa800a106e54efb9d79bf8300e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:42:35 +0200 Subject: [PATCH 1695/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.30.4 (#2089) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ec9a9033f01d..246f6534dbb9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.2 + 2.30.4 From 8b1519a2742b413bb4708f7a08321cfc83d92933 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:43:19 +0200 Subject: [PATCH 1696/1979] deps: update dependency org.postgresql:postgresql to v42.7.7 [security] (#2093) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 857cccc1abc2..4ec4bb0e8182 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -72,7 +72,7 @@ org.postgresql postgresql - 42.7.6 + 42.7.7 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 1eb65e65f452..9e293a98d79a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.6 + 42.7.7 org.testcontainers From 4cb6edf20f86fa78652d8d83745154cb37283b88 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:43:44 +0200 Subject: [PATCH 1697/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.7 (#2094) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index fbacf643e20d..974a56e82b46 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.6 + 2024.1.7 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4ec4bb0e8182..540eee9115e2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.6 + 2024.1.7 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 9f0aaa84b55d..cc000d4d50a8 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.6 + 2024.1.7 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 9e293a98d79a..4ad94b006622 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.6 + 2024.1.7 import pom From c8f23fc0bc71072c2ac80885d983c9d7c8f5a496 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:44:03 +0200 Subject: [PATCH 1698/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.1 (#2095) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 05def68a3bc1..948f4fbb355f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.19.0 + 2.19.1 From 0379f81b692ef48a3a2820e95b07818f61697e0d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:44:30 +0200 Subject: [PATCH 1699/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.49.2 (#2096) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 57c18dcb73b2..dbf6fc04a711 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.49.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.49.2 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index b2565b8eaae9..daa00c898382 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 80881c2910e1..e1caa99808aa 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index cf82898b7954..38e0052a1786 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.2" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c50a25eef84f..cb4913d6b0ae 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.49.0 + 3.49.2 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 948f4fbb355f..f73fe682c483 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.49.0 + 3.49.2 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ea41057c6d76..76f27fcba736 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.49.0 + 3.49.2 From 5d29f66f3e247846161deadc287a133cf7a4bd04 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 08:44:49 +0200 Subject: [PATCH 1700/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.3 (#2099) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f73fe682c483..852a7ec6de45 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.0 + 3.5.3 test From 99d333e1d1dc53773a121a3c992514b193bad0b9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 09:23:58 +0200 Subject: [PATCH 1701/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.21.2 (#2098) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index cc000d4d50a8..d1f15dc8f2ae 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 1.21.1 + 1.21.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 4ad94b006622..db2ac0935f65 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.21.1 + 1.21.2 import pom From da39cf49a7e32096f72779406b26c08c679da31b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 09:25:40 +0200 Subject: [PATCH 1702/1979] deps: update dependency org.testcontainers:testcontainers to v1.21.2 (#2097) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cb4913d6b0ae..cdb00525759c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.21.1 + 1.21.2 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 852a7ec6de45..36f4d5a738a7 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.21.1 + 1.21.2 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 76f27fcba736..d168f2f7c332 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.21.1 + 1.21.2 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 974a56e82b46..3de8363245b4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 1.21.1 + 1.21.2 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 540eee9115e2..4f07c04b443b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.21.1 + 1.21.2 test From 65de11f11372b3d38270403d65977babe99f9779 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 09:26:13 +0200 Subject: [PATCH 1703/1979] build(deps): bump org.postgresql:postgresql (#2092) Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.6 to 42.7.7. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.6...REL42.7.7) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-version: 42.7.7 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 063fa87fb25d2b8b4297de4d740c3cd4e85be031 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 09:29:41 +0200 Subject: [PATCH 1704/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.3 (#2102) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d1f15dc8f2ae..a41316b9143c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.0 + 3.5.3 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index db2ac0935f65..7a9e1f6f95a0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.0 + 3.5.3 From 3a819a8e0d6a94b609a796a1e767d5165fbd0dcc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 20 Jun 2025 09:30:44 +0200 Subject: [PATCH 1705/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.3 (#2101) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 3de8363245b4..e088104b7fa3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.0 + 3.5.3 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4f07c04b443b..2d4d99ba1b74 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.0 + 3.5.3 From e4e14da18d1a987629e8c7fb8951587da67f8b05 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 10:19:31 +0200 Subject: [PATCH 1706/1979] chore(main): release 2.30.5 (#2100) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 596968055ee3..33caeaa34a40 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [2.30.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.4...v2.30.5) (2025-06-20) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.1 ([#2095](https://github.com/googleapis/java-spanner-jdbc/issues/2095)) ([4d662fe](https://github.com/googleapis/java-spanner-jdbc/commit/4d662fe71fc0d03fe0d648e202a508ff18f1f97b)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.49.2 ([#2096](https://github.com/googleapis/java-spanner-jdbc/issues/2096)) ([53871df](https://github.com/googleapis/java-spanner-jdbc/commit/53871df28b4a3a98d3193f1fb66418e7106e891b)) +* Update dependency org.postgresql:postgresql to v42.7.7 [security] ([#2093](https://github.com/googleapis/java-spanner-jdbc/issues/2093)) ([a7209c4](https://github.com/googleapis/java-spanner-jdbc/commit/a7209c496ef2895c469f19447e4cc90d4e4066bf)) +* Update dependency org.springframework.boot:spring-boot to v3.5.3 ([#2099](https://github.com/googleapis/java-spanner-jdbc/issues/2099)) ([fa1dde8](https://github.com/googleapis/java-spanner-jdbc/commit/fa1dde8e806df5fcd1477ce1388507a542a73ca0)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.3 ([#2101](https://github.com/googleapis/java-spanner-jdbc/issues/2101)) ([2381398](https://github.com/googleapis/java-spanner-jdbc/commit/2381398c3c89bf4a2edf3d3520c62e158487ae8a)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.3 ([#2102](https://github.com/googleapis/java-spanner-jdbc/issues/2102)) ([7d865e9](https://github.com/googleapis/java-spanner-jdbc/commit/7d865e917b2610f2cae6819698c1c03505e340d2)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.7 ([#2094](https://github.com/googleapis/java-spanner-jdbc/issues/2094)) ([e273887](https://github.com/googleapis/java-spanner-jdbc/commit/e273887d61da95930e32494d5abc9aab0906f237)) +* Update dependency org.testcontainers:testcontainers to v1.21.2 ([#2097](https://github.com/googleapis/java-spanner-jdbc/issues/2097)) ([ce9298e](https://github.com/googleapis/java-spanner-jdbc/commit/ce9298ec4583649d8187206345a2e3fe245e4d32)) +* Update dependency org.testcontainers:testcontainers-bom to v1.21.2 ([#2098](https://github.com/googleapis/java-spanner-jdbc/issues/2098)) ([cd9f8a0](https://github.com/googleapis/java-spanner-jdbc/commit/cd9f8a01db5b0364bf7188a9b7f2079fb37d494c)) + ## [2.30.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.3...v2.30.4) (2025-06-10) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 7a1e37212bf9..a6144c0be402 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.4 + 2.30.5 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.4' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.5' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.4" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.5" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cdb00525759c..20f523288522 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.5-SNAPSHOT + 2.30.5 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5a336430e8a4..2a138c037ece 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.5-SNAPSHOT + 2.30.5 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 7664cf536dee..897e9ba04c4d 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.4:2.30.5-SNAPSHOT +google-cloud-spanner-jdbc:2.30.5:2.30.5 From 7efb639d3cebd4445ddf95cbc22972f69c751464 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 08:50:23 +0000 Subject: [PATCH 1707/1979] chore(main): release 2.30.6-SNAPSHOT (#2103) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 20f523288522..ed1115754c53 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.5 + 2.30.6-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2a138c037ece..569f214688bd 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.5 + 2.30.6-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 897e9ba04c4d..85a63f3207b1 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.5:2.30.5 +google-cloud-spanner-jdbc:2.30.5:2.30.6-SNAPSHOT From b19e15fd999930b41ae9b5e7a277c63a11566744 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Jun 2025 19:13:59 +0200 Subject: [PATCH 1708/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.30.5 (#2104) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 246f6534dbb9..0ca4b1438d19 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.4 + 2.30.5 From 9293e42988ac2ecb78ca85556d3e394ff11e0c49 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 23 Jun 2025 19:29:25 +0200 Subject: [PATCH 1709/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.66.0 (#2106) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ed1115754c53..84fff6b70059 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.64.0 + 2.66.0 test From 33d818004aa56936a5aebdd215bf92ab5545418c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 24 Jun 2025 07:44:10 +0200 Subject: [PATCH 1710/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.66.0 (#2105) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 84fff6b70059..3f23f0a20fb6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.64.0 + 2.66.0 test From 959420e3c9f28b9345c5a451de19ed5aedee1652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 25 Jun 2025 15:42:25 +0200 Subject: [PATCH 1711/1979] test: remove some Emulator restrictions from tests (#2111) Remove some specific checks/restrictions from tests when running on the Emulator, as these issues have been fixed in the latest release of the Emulator. --- .../spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java index 6f514bed0966..25ade01e461b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcDatabaseMetaDataTest.java @@ -313,10 +313,6 @@ public void testGetColumns() throws SQLException { assertEquals(0, rs.getShort("SOURCE_DATA_TYPE")); assertTrue(rs.wasNull()); assertEquals(col.computed ? "YES" : "NO", rs.getString("IS_GENERATEDCOLUMN")); - // TODO: Remove check when the emulator correctly returns IS_IDENTITY - if (!EmulatorSpannerHelper.isUsingEmulator()) { - assertEquals(col.autoIncrement ? "YES" : "NO", rs.getString("IS_AUTOINCREMENT")); - } assertEquals(24, rs.getMetaData().getColumnCount()); } assertFalse(rs.next()); @@ -590,12 +586,6 @@ public void testGetIndexInfo() throws SQLException { connection.getMetaData().getIndexInfo(DEFAULT_CATALOG, schema, null, false, false)) { for (IndexInfo index : EXPECTED_INDICES) { - // The emulator does not generate indexes for foreign keys in a non-default schema. - if (EmulatorSpannerHelper.isUsingEmulator() - && "test".equals(schema) - && ("FOREIGN_KEY".equals(index.indexName) || "GENERATED".equals(index.indexName))) { - continue; - } assertTrue(rs.next()); assertEquals(DEFAULT_CATALOG, rs.getString("TABLE_CAT")); assertEquals(schema, rs.getString("TABLE_SCHEM")); From bc5ede8feb98b0d6d6a7c234bcf0d5eac75462bc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Jun 2025 16:20:19 +0200 Subject: [PATCH 1712/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.50.0 (#2108) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index dbf6fc04a711..ea62e6c39b27 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.49.2 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index daa00c898382..1d327c28dd86 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index e1caa99808aa..5b98727f2751 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 38e0052a1786..952a1c1b0322 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3f23f0a20fb6..45631b9608ad 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.49.2 + 3.50.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 36f4d5a738a7..4f5cb025f32f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.49.2 + 3.50.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d168f2f7c332..8cbc9c7d8e97 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.49.2 + 3.50.0 From 55c15f53772d9bb82406bb0164f9bf1004540fbf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Jun 2025 17:10:40 +0200 Subject: [PATCH 1713/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-trace to v0.36.0 (#2110) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 45631b9608ad..d1069e889796 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -204,7 +204,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.35.0 + 0.36.0 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index e088104b7fa3..2c0be20b1280 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -78,7 +78,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.35.0 + 0.36.0 com.google.cloud.opentelemetry diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 2d4d99ba1b74..105aececb940 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-trace - 0.35.0 + 0.36.0 com.google.cloud.opentelemetry From a07639c2469072f14a6b566782d4e45c81ce4260 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 25 Jun 2025 17:14:23 +0200 Subject: [PATCH 1714/1979] deps: update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.36.0 (#2109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud.opentelemetry:exporter-metrics](https://redirect.github.com/GoogleCloudPlatform/opentelemetry-operations-java) | `0.35.0` -> `0.36.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud.opentelemetry:exporter-metrics/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud.opentelemetry:exporter-metrics/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud.opentelemetry:exporter-metrics/0.35.0/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud.opentelemetry:exporter-metrics/0.35.0/0.36.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    GoogleCloudPlatform/opentelemetry-operations-java (com.google.cloud.opentelemetry:exporter-metrics) ### [`v0.36.0`](https://redirect.github.com/GoogleCloudPlatform/opentelemetry-operations-java/releases/tag/v0.36.0) [Compare Source](https://redirect.github.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.35.0...v0.36.0) ##### Release Highlights This release is primarily done to test the new release process for this repository. There are no new feature updates or fixes in this release compared to the previous version. ##### What's Changed - Publish by using Portal OSSRH Staging API by [@​psx95](https://redirect.github.com/psx95) in [https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/416](https://redirect.github.com/GoogleCloudPlatform/opentelemetry-operations-java/pull/416) **Full Changelog**: https://togithub.com/GoogleCloudPlatform/opentelemetry-operations-java/compare/v0.35.0...v0.36.0
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 2c0be20b1280..e906e5a73090 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -83,7 +83,7 @@ com.google.cloud.opentelemetry exporter-metrics - 0.35.0 + 0.36.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 105aececb940..73adf1563691 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -88,7 +88,7 @@ com.google.cloud.opentelemetry exporter-metrics - 0.35.0 + 0.36.0 From f20b7bdd1ce58ad48045ff0e7fff7f2450d746e5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Jun 2025 12:11:28 +0200 Subject: [PATCH 1715/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.67.0 (#2114) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d1069e889796..ee861c0afe31 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.66.0 + 2.67.0 test From 2ada30f06e87ee7409db70f844c9be66a658d8ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Jun 2025 12:42:43 +0200 Subject: [PATCH 1716/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.67.0 (#2112) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ee861c0afe31..d95ebd5dd2ef 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.66.0 + 2.67.0 test From b29ba6c2606a53c5e6bbbab7c94eb34ef844dbd5 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Fri, 27 Jun 2025 19:07:28 +0530 Subject: [PATCH 1717/1979] feat: Allow JDBC connection to configure direct access (#2116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Allow JDBC connection to configiue direct access * test: update SQL script tests to allow zero for timeouts --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/README.md | 1 + .../documentation/connection_properties.md | 1 + java-spanner-jdbc/pom.xml | 2 +- .../ConnectionImplGeneratedSqlScriptTest.sql | 386 ++++++------------ .../ConnectionImplGeneratedSqlScriptTest.sql | 386 ++++++------------ .../jdbc/PostgreSQL/TimeoutSqlScriptTest.sql | 5 +- .../spanner/jdbc/TimeoutSqlScriptTest.sql | 5 +- 7 files changed, 269 insertions(+), 517 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a6144c0be402..aa63aa36f93f 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -137,6 +137,7 @@ supported connection properties. into one batch. - oauthToken (string): A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. - lenient (boolean): Enable this to force the JDBC driver to ignore unknown properties in the connection URL. Some applications automatically add additional properties to the URL that are not recognized by the JDBC driver. Normally, the JDBC driver will reject this, unless `lenient` mode is enabled. +- enableDirectAccess (boolean): Sets whether the JDBC connection should establish connection using Directpath. Setting this property will enable client to establish connection directly to Spanner if client is running in GCP VM, Otherwise it will fall back standard network path. For a full list of supported connection properties, see [Supported Connection Properties](documentation/connection_properties.md). diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index cedb01d0482a..4110bcfe7cc4 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -28,6 +28,7 @@ The 'Context' value indicates whether the property can only be set when a connec | dialect | Sets the dialect to use for new databases that are created by this connection. | GOOGLE_STANDARD_SQL | GOOGLE_STANDARD_SQL, POSTGRESQL | STARTUP | | directed_read | The directed read options to apply to read-only transactions. | | | USER | | enableapitracing | Add OpenTelemetry traces for each individual RPC call. Enable this to get a detailed view of each RPC that is being executed by your application, or if you want to debug potential latency problems caused by RPCs that are being retried. | | true, false | STARTUP | +| enabledirectaccess | Configure the connection to try to connect to Spanner using DirectPath (true/false). The client will try to connect to Spanner using a direct Google network connection. DirectPath will work only if the client is trying to establish a connection from a Google Cloud VM. Otherwise it will automatically fallback to the standard network path. NOTE: The default for this property is currently false, but this could be changed in the future. | | true, false | STARTUP | | enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | true, false | STARTUP | | enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | true, false | STARTUP | | encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d95ebd5dd2ef..a01e211964d3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.1 + 6.96.0 pom import diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql index 84275c3d5c3e..d79dd8bf6f55 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/ConnectionImplGeneratedSqlScriptTest.sql @@ -160,15 +160,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:38.900000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:38.900000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:38.900000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -261,7 +261,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -271,7 +270,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -281,7 +279,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -291,7 +288,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -510,15 +506,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.005000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.005000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.005000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -611,7 +607,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -621,7 +616,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -631,7 +625,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -641,7 +634,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -950,8 +942,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.100000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.100000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -961,7 +953,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.100000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1096,7 +1088,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1106,7 +1097,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1116,7 +1106,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1126,7 +1115,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1462,8 +1450,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.195000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.195000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1473,7 +1461,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.195000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1608,7 +1596,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1618,7 +1605,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1628,7 +1614,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1638,7 +1623,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1876,15 +1860,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.290000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.290000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.290000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1977,7 +1961,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1987,7 +1970,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1997,7 +1979,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2007,7 +1988,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2243,14 +2223,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.365000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.365000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2355,7 +2335,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2365,7 +2344,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2375,7 +2353,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2385,7 +2362,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2600,13 +2576,13 @@ SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.444000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.444000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2697,7 +2673,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2707,7 +2682,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2717,7 +2691,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2727,7 +2700,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2910,14 +2882,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.539000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.539000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.539000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2996,7 +2968,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3006,7 +2977,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3016,7 +2986,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3026,7 +2995,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3245,15 +3213,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.630000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.630000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.630000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3346,7 +3314,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3356,7 +3323,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3366,7 +3332,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3376,7 +3341,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3662,8 +3626,8 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.702000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.702000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -3672,7 +3636,7 @@ START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.702000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3793,7 +3757,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3803,7 +3766,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3813,7 +3775,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3823,7 +3784,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4081,14 +4041,14 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.767000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.767000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4193,7 +4153,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4203,7 +4162,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4213,7 +4171,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4223,7 +4180,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4438,13 +4394,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.826000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.826000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4535,7 +4491,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4545,7 +4500,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4555,7 +4509,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4565,7 +4518,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4877,8 +4829,8 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.888000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.888000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -4888,7 +4840,7 @@ SET TRANSACTION READ ONLY; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.888000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5023,7 +4975,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5033,7 +4984,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5043,7 +4993,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5053,7 +5002,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5288,15 +5236,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.960000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.960000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.960000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5389,7 +5337,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5399,7 +5346,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5409,7 +5355,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5419,7 +5364,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5641,15 +5585,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.018000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.018000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.018000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5742,7 +5686,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5752,7 +5695,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5762,7 +5704,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5772,7 +5713,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6088,8 +6028,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.091000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.091000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -6099,7 +6039,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.091000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6234,7 +6174,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6244,7 +6183,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6254,7 +6192,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6264,7 +6201,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6607,8 +6543,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.166000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.166000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -6618,7 +6554,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.166000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6753,7 +6689,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6763,7 +6698,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6773,7 +6707,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6783,7 +6716,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7023,15 +6955,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.255000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.255000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.255000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7124,7 +7056,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7134,7 +7065,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7144,7 +7074,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7154,7 +7083,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7394,14 +7322,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.372000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.372000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7506,7 +7434,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7516,7 +7443,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7526,7 +7452,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7536,7 +7461,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7756,13 +7680,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.441000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.441000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7853,7 +7777,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7863,7 +7786,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7873,7 +7795,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7883,7 +7804,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8075,14 +7995,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.535000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.535000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.535000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8161,7 +8081,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8171,7 +8090,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8181,7 +8099,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8191,7 +8108,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8392,13 +8308,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.592000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.592000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8489,7 +8405,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8499,7 +8414,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8509,7 +8423,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8519,7 +8432,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8753,8 +8665,8 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.651000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.651000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -8762,7 +8674,7 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.651000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8869,7 +8781,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8879,7 +8790,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8889,7 +8799,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8899,7 +8808,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9064,6 +8972,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9197,8 +9108,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.713000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.713000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -9206,8 +9117,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.713000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.713000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -9330,7 +9241,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9340,7 +9250,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9350,7 +9259,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9360,7 +9268,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9593,15 +9500,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.781000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.781000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.781000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9694,7 +9601,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9704,7 +9610,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9714,7 +9619,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9724,7 +9628,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9851,6 +9754,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9952,15 +9858,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.843000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.843000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.843000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.843000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -10055,7 +9961,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10065,7 +9970,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10075,7 +9979,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10085,7 +9988,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10219,6 +10121,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -10320,15 +10225,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.905000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.905000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.905000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.905000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -10423,7 +10328,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10433,7 +10337,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10443,7 +10346,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10453,7 +10355,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10601,6 +10502,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -10718,16 +10622,16 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.964000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.964000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.964000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.964000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -10836,7 +10740,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10846,7 +10749,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10856,7 +10758,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10866,7 +10767,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11009,6 +10909,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -11110,15 +11013,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.022000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.022000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.022000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.022000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -11213,7 +11116,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11223,7 +11125,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11233,7 +11134,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11243,7 +11143,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11363,6 +11262,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -11448,14 +11350,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.080000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.080000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.080000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.080000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -11536,7 +11438,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11546,7 +11447,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11556,7 +11456,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11566,7 +11465,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11778,15 +11676,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.139000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.139000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.139000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.139000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -11881,7 +11779,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11891,7 +11788,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11901,7 +11797,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11911,7 +11806,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12193,8 +12087,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.195000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.195000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -12202,8 +12096,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.195000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.195000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -12326,7 +12220,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12336,7 +12229,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12346,7 +12238,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12356,7 +12247,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12586,15 +12476,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.253000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.253000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.253000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -12687,7 +12577,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12697,7 +12586,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12707,7 +12595,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12717,7 +12604,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12932,15 +12818,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.307000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.307000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.307000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.307000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -13035,7 +12921,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13045,7 +12930,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13055,7 +12939,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13065,7 +12948,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13287,15 +13169,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.364000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.364000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.364000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.364000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -13390,7 +13272,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13400,7 +13281,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13410,7 +13290,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13420,7 +13299,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13612,14 +13490,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.418000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.418000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.418000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.418000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -13700,7 +13578,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13710,7 +13587,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13720,7 +13596,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13730,7 +13605,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=null; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql index e35ae5f3c3c7..91c4ac3f394a 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/ConnectionImplGeneratedSqlScriptTest.sql @@ -160,15 +160,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:38.957000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:38.957000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:38.957000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -261,7 +261,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -271,7 +270,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -281,7 +279,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -291,7 +288,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -510,15 +506,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.052000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.052000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.052000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -611,7 +607,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -621,7 +616,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -631,7 +625,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -641,7 +634,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -950,8 +942,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.148000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.148000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -961,7 +953,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.148000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1096,7 +1088,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1106,7 +1097,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1116,7 +1106,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1126,7 +1115,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1462,8 +1450,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.239000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.239000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -1473,7 +1461,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.239000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1608,7 +1596,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1618,7 +1605,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1628,7 +1614,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1638,7 +1623,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1876,15 +1860,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.327000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.327000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.327000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1977,7 +1961,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1987,7 +1970,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1997,7 +1979,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2007,7 +1988,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2243,14 +2223,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.406000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.406000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2355,7 +2335,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2365,7 +2344,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2375,7 +2353,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2385,7 +2362,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2600,13 +2576,13 @@ SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.494000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.494000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2697,7 +2673,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2707,7 +2682,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2717,7 +2691,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2727,7 +2700,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2910,14 +2882,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.573000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.573000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.573000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2996,7 +2968,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3006,7 +2977,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3016,7 +2986,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3026,7 +2995,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3245,15 +3213,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.666000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.666000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.666000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3346,7 +3314,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3356,7 +3323,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3366,7 +3332,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3376,7 +3341,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3662,8 +3626,8 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.736000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.736000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -3672,7 +3636,7 @@ START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.736000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3793,7 +3757,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3803,7 +3766,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3813,7 +3775,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3823,7 +3784,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4081,14 +4041,14 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.798000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.798000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4193,7 +4153,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4203,7 +4162,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4213,7 +4171,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4223,7 +4180,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4438,13 +4394,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.854000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.854000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4535,7 +4491,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4545,7 +4500,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4555,7 +4509,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4565,7 +4518,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4877,8 +4829,8 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.926000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.926000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -4888,7 +4840,7 @@ SET TRANSACTION READ ONLY; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.926000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5023,7 +4975,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5033,7 +4984,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5043,7 +4993,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5053,7 +5002,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5288,15 +5236,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:39.987000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:39.987000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:39.987000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5389,7 +5337,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5399,7 +5346,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5409,7 +5355,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5419,7 +5364,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5641,15 +5585,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.054000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.054000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.054000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5742,7 +5686,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5752,7 +5695,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5762,7 +5704,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5772,7 +5713,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6088,8 +6028,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.126000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.126000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -6099,7 +6039,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.126000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6234,7 +6174,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6244,7 +6183,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6254,7 +6192,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6264,7 +6201,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6607,8 +6543,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.209000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.209000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -6618,7 +6554,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.209000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6753,7 +6689,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6763,7 +6698,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6773,7 +6707,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6783,7 +6716,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7023,15 +6955,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.323000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.323000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.323000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7124,7 +7056,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7134,7 +7065,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7144,7 +7074,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7154,7 +7083,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7394,14 +7322,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.407000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.407000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7506,7 +7434,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7516,7 +7443,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7526,7 +7452,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7536,7 +7461,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7756,13 +7680,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.473000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.473000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7853,7 +7777,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7863,7 +7786,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7873,7 +7795,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7883,7 +7804,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8075,14 +7995,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.565000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.565000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.565000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8161,7 +8081,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8171,7 +8090,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8181,7 +8099,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8191,7 +8108,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8392,13 +8308,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.621000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.621000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8489,7 +8405,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8499,7 +8414,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8509,7 +8423,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8519,7 +8432,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8753,8 +8665,8 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.678000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.678000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -8762,7 +8674,7 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.678000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8869,7 +8781,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8879,7 +8790,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8889,7 +8799,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8899,7 +8808,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9064,6 +8972,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9197,8 +9108,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.749000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.749000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -9206,8 +9117,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.749000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.749000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -9330,7 +9241,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9340,7 +9250,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9350,7 +9259,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9360,7 +9268,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9593,15 +9500,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.812000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.812000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.812000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9694,7 +9601,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9704,7 +9610,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9714,7 +9619,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9724,7 +9628,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9851,6 +9754,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9952,15 +9858,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.876000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.876000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.876000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.876000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -10055,7 +9961,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10065,7 +9970,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10075,7 +9979,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10085,7 +9988,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10219,6 +10121,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -10320,15 +10225,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.934000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.934000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.934000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.934000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -10423,7 +10328,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10433,7 +10337,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10443,7 +10346,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10453,7 +10355,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10601,6 +10502,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -10718,16 +10622,16 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:40.992000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:40.992000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:40.992000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:40.992000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -10836,7 +10740,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10846,7 +10749,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10856,7 +10758,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10866,7 +10767,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11009,6 +10909,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -11110,15 +11013,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.052000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.052000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.052000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.052000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -11213,7 +11116,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11223,7 +11125,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11233,7 +11134,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11243,7 +11143,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11363,6 +11262,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; @EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; +SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' +SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -11448,14 +11350,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.108000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.108000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.108000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.108000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -11536,7 +11438,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11546,7 +11447,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11556,7 +11456,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11566,7 +11465,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11778,15 +11676,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.166000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.166000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.166000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.166000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -11881,7 +11779,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11891,7 +11788,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11901,7 +11797,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11911,7 +11806,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12193,8 +12087,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.226000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.226000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -12202,8 +12096,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.226000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.226000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -12326,7 +12220,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12336,7 +12229,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12346,7 +12238,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12356,7 +12247,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12586,15 +12476,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.279000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.279000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.279000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -12687,7 +12577,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12697,7 +12586,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12707,7 +12595,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12717,7 +12604,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -12932,15 +12818,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.336000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.336000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.336000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.336000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -13035,7 +12921,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13045,7 +12930,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13055,7 +12939,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13065,7 +12948,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13287,15 +13169,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.392000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.392000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.392000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.392000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -13390,7 +13272,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13400,7 +13281,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13410,7 +13290,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13420,7 +13299,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13612,14 +13490,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-06-12T08:45:41.442000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-06-12T08:45:41.442000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-06-12T08:45:41.442000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-06-12T08:45:41.442000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -13700,7 +13578,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13710,7 +13587,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13720,7 +13596,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0us'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13730,7 +13605,6 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT=DEFAULT; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; -@EXPECT EXCEPTION INVALID_ARGUMENT SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' SHOW VARIABLE STATEMENT_TIMEOUT; diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql index 60a8f247698e..ec92c02b0be1 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/PostgreSQL/TimeoutSqlScriptTest.sql @@ -42,9 +42,10 @@ SHOW STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT='2999ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','2999ms' SHOW STATEMENT_TIMEOUT; --- Check that setting the value to 0 is not allowed -@EXPECT EXCEPTION INVALID_ARGUMENT +-- Check that setting the value to 0 is allowed SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT','0' +SHOW STATEMENT_TIMEOUT; -- Set a timeout value and then reset it to null SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' diff --git a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql index 06dc96fb8693..3c258a21f054 100644 --- a/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql +++ b/java-spanner-jdbc/src/test/resources/com/google/cloud/spanner/jdbc/TimeoutSqlScriptTest.sql @@ -42,9 +42,10 @@ SHOW VARIABLE STATEMENT_TIMEOUT; SET STATEMENT_TIMEOUT='2999ms'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','2999ms' SHOW VARIABLE STATEMENT_TIMEOUT; --- Check that setting the value to 0 is not allowed -@EXPECT EXCEPTION INVALID_ARGUMENT +-- Check that setting the value to 0 is allowed SET STATEMENT_TIMEOUT='0s'; +@EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null +SHOW VARIABLE STATEMENT_TIMEOUT; -- Set a timeout value and then reset it to null SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' From 455d8f83344f55c5596534a5cd705ad77712ebee Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:30:31 +0200 Subject: [PATCH 1718/1979] chore(main): release 2.31.0 (#2107) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 33caeaa34a40..ac2e332d8a4b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.31.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.5...v2.31.0) (2025-06-27) + + +### Features + +* Allow JDBC connection to configure direct access ([#2116](https://github.com/googleapis/java-spanner-jdbc/issues/2116)) ([d72242a](https://github.com/googleapis/java-spanner-jdbc/commit/d72242a9d73056394af9469ada7e6439d3678a59)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.66.0 ([#2105](https://github.com/googleapis/java-spanner-jdbc/issues/2105)) ([619bea7](https://github.com/googleapis/java-spanner-jdbc/commit/619bea764083e7b253de3b6e3a944235dab42109)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.67.0 ([#2114](https://github.com/googleapis/java-spanner-jdbc/issues/2114)) ([60d5aa7](https://github.com/googleapis/java-spanner-jdbc/commit/60d5aa7df330008085bce7fc1a70b8e8abb9f05d)) +* Update dependency com.google.cloud:google-cloud-trace to v2.66.0 ([#2106](https://github.com/googleapis/java-spanner-jdbc/issues/2106)) ([161683a](https://github.com/googleapis/java-spanner-jdbc/commit/161683aefe0c93446524c3733e9d3b8aa2e76f94)) +* Update dependency com.google.cloud:google-cloud-trace to v2.67.0 ([#2112](https://github.com/googleapis/java-spanner-jdbc/issues/2112)) ([70e21a6](https://github.com/googleapis/java-spanner-jdbc/commit/70e21a68677ac4adac436e1f4e67a1201c85d427)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.0 ([#2108](https://github.com/googleapis/java-spanner-jdbc/issues/2108)) ([816c2b6](https://github.com/googleapis/java-spanner-jdbc/commit/816c2b67098b622013e2c7fcfea0bc8855d427eb)) +* Update dependency com.google.cloud.opentelemetry:exporter-metrics to v0.36.0 ([#2109](https://github.com/googleapis/java-spanner-jdbc/issues/2109)) ([7a3fa70](https://github.com/googleapis/java-spanner-jdbc/commit/7a3fa7018dda8c4bda5a1fce2fb42c632058d66d)) +* Update dependency com.google.cloud.opentelemetry:exporter-trace to v0.36.0 ([#2110](https://github.com/googleapis/java-spanner-jdbc/issues/2110)) ([89ea86b](https://github.com/googleapis/java-spanner-jdbc/commit/89ea86b2608938f062ce7ac4fa61e591811f65e4)) + ## [2.30.5](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.4...v2.30.5) (2025-06-20) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index aa63aa36f93f..f701797a2309 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.30.5 + 2.31.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.30.5' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.30.5" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a01e211964d3..3488d39d92c6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.30.6-SNAPSHOT + 2.31.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 569f214688bd..898cd7da4b46 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.6-SNAPSHOT + 2.31.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 85a63f3207b1..d8c281bd9bf8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.30.5:2.30.6-SNAPSHOT +google-cloud-spanner-jdbc:2.31.0:2.31.0 From 8dc385ebbe8ed0bf25246c02183bc92516b34d57 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Jun 2025 16:30:47 +0200 Subject: [PATCH 1719/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.96.0 (#2117) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index a41316b9143c..da4211bb7d87 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.95.1 + 6.96.0 test-jar test From cf25aa59146439421ed55bdb50798f96b5785e4e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 27 Jun 2025 16:30:59 +0200 Subject: [PATCH 1720/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.96.0 (#2118) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index e906e5a73090..66c075494178 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.1 + 6.96.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 73adf1563691..3a0993ce3e70 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.1 + 6.96.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index da4211bb7d87..4b28c31d2056 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.95.1 + 6.96.0 import pom From 33e69bec4a3ff71fb2e9e567e729950cadefbb22 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 18:32:51 +0200 Subject: [PATCH 1721/1979] chore(main): release 2.31.1-SNAPSHOT (#2119) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3488d39d92c6..30c285d3ecfe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.0 + 2.31.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 898cd7da4b46..7094402449c4 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.0 + 2.31.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index d8c281bd9bf8..caf432fbecd8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.0:2.31.0 +google-cloud-spanner-jdbc:2.31.0:2.31.1-SNAPSHOT From 5307266104981d69b663d519165cab2911d069e8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Jul 2025 09:30:59 +0200 Subject: [PATCH 1722/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.96.1 (#2125) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 30c285d3ecfe..797d223b7b8d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.0 + 6.96.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 66c075494178..1537873c49e7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.0 + 6.96.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 3a0993ce3e70..0905fa450d8f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.0 + 6.96.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 4b28c31d2056..76b5a8dccdc9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.0 + 6.96.1 import pom From 6de150b2e99e71bc2877cb57b99eb59d3fc92545 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Jul 2025 10:17:38 +0200 Subject: [PATCH 1723/1979] deps: update dependency org.testcontainers:testcontainers to v1.21.3 (#2122) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 797d223b7b8d..b68842fc4eca 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.21.2 + 1.21.3 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4f5cb025f32f..a7f867c9c68a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.21.2 + 1.21.3 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 8cbc9c7d8e97..b8e76427b82b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.21.2 + 1.21.3 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 1537873c49e7..0b5079181e39 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 1.21.2 + 1.21.3 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 0905fa450d8f..290430724f7e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -119,7 +119,7 @@ org.testcontainers testcontainers - 1.21.2 + 1.21.3 test From e4e2e9906588a4759f1594005b32d79bbd2c29ce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Jul 2025 10:17:57 +0200 Subject: [PATCH 1724/1979] deps: update dependency org.testcontainers:testcontainers-bom to v1.21.3 (#2123) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 76b5a8dccdc9..af1c4052db83 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 1.21.2 + 1.21.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 7a9e1f6f95a0..ddd94106fc23 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.21.2 + 1.21.3 import pom From ad45931e9b084132aa89e43792b880f45e9c6f2c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Jul 2025 10:18:14 +0200 Subject: [PATCH 1725/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.96.1 (#2124) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index af1c4052db83..bfee8d77abfd 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.96.0 + 6.96.1 test-jar test From 79022970dbec4214c1120c03cd759657142b1ed4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 1 Jul 2025 10:19:35 +0200 Subject: [PATCH 1726/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.31.0 (#2121) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0ca4b1438d19..e545a922fdc6 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.30.5 + 2.31.0 From c378a6dfecb9a8d6248500406dabeae3e5b717df Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:49:46 +0200 Subject: [PATCH 1727/1979] chore(main): release 2.31.1 (#2120) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ac2e332d8a4b..cdb10a012453 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.31.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.0...v2.31.1) (2025-07-01) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner to v6.96.0 ([#2117](https://github.com/googleapis/java-spanner-jdbc/issues/2117)) ([e8eb64a](https://github.com/googleapis/java-spanner-jdbc/commit/e8eb64a668c7d95076a9940fe8fa38c293594598)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.96.1 ([#2124](https://github.com/googleapis/java-spanner-jdbc/issues/2124)) ([3d5be5e](https://github.com/googleapis/java-spanner-jdbc/commit/3d5be5ecf17f8618c30c815319b90fd3c53202cc)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.96.0 ([#2118](https://github.com/googleapis/java-spanner-jdbc/issues/2118)) ([f1ca551](https://github.com/googleapis/java-spanner-jdbc/commit/f1ca55144efabb37f872909fa97a6f33a1c3c0e9)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.96.1 ([#2125](https://github.com/googleapis/java-spanner-jdbc/issues/2125)) ([6b83bcd](https://github.com/googleapis/java-spanner-jdbc/commit/6b83bcdc090017d531839fa6da555a6e4c8d428a)) +* Update dependency org.testcontainers:testcontainers to v1.21.3 ([#2122](https://github.com/googleapis/java-spanner-jdbc/issues/2122)) ([241b19d](https://github.com/googleapis/java-spanner-jdbc/commit/241b19d89f221abe7eeee29bc1e605f1edb1a69f)) +* Update dependency org.testcontainers:testcontainers-bom to v1.21.3 ([#2123](https://github.com/googleapis/java-spanner-jdbc/issues/2123)) ([92dd5ea](https://github.com/googleapis/java-spanner-jdbc/commit/92dd5eaad584c680b62ca4f1f297f78188101ab5)) + ## [2.31.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.30.5...v2.31.0) (2025-06-27) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index f701797a2309..23a432fb2b3c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.31.0 + 2.31.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b68842fc4eca..b571b50ea54f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.1-SNAPSHOT + 2.31.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 7094402449c4..b590b65496cc 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.1-SNAPSHOT + 2.31.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index caf432fbecd8..987cc0cb3473 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.0:2.31.1-SNAPSHOT +google-cloud-spanner-jdbc:2.31.1:2.31.1 From 1b649510cfac444e69db5ad489e89075974e1d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 2 Jul 2025 07:22:29 +0200 Subject: [PATCH 1728/1979] test: check for credentials for traces (#2128) Add an explicit check to the test whether there are credentials available. --- java-spanner-jdbc/.kokoro/build.sh | 2 -- .../.kokoro/presubmit/integration.cfg | 15 +++++++++++-- .../spanner/jdbc/it/ITOpenTelemetryTest.java | 21 ++++++++++++------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/java-spanner-jdbc/.kokoro/build.sh b/java-spanner-jdbc/.kokoro/build.sh index d7dbf59de306..e1b04b4fdf98 100755 --- a/java-spanner-jdbc/.kokoro/build.sh +++ b/java-spanner-jdbc/.kokoro/build.sh @@ -76,8 +76,6 @@ integration) -DtrimStackTrace=false \ -Dclirr.skip=true \ -Denforcer.skip=true \ - -Dspanner.testenv.instance=projects/span-cloud-testing/instances/java-client-integration-test \ - -Dspanner.gce.config.project_id=span-cloud-testing \ -fae \ verify RETURN_CODE=$? diff --git a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg index 929a8b3467ca..5864c603e5ad 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/integration.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/integration.cfg @@ -11,13 +11,24 @@ env_vars: { value: "integration" } +# TODO: remove this after we've migrated all tests and scripts +env_vars: { + key: "GCLOUD_PROJECT" + value: "gcloud-devel" +} + +env_vars: { + key: "GOOGLE_CLOUD_PROJECT" + value: "gcloud-devel" +} + env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "secret_manager/java-client-testing" + value: "secret_manager/java-it-service-account" } env_vars: { key: "SECRET_MANAGER_KEYS" - value: "java-client-testing" + value: "java-it-service-account" } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java index 83cfab81c9ff..7c5654fd71b6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITOpenTelemetryTest.java @@ -23,6 +23,8 @@ import com.google.api.gax.core.FixedCredentialsProvider; import com.google.api.gax.rpc.ResourceExhaustedException; +import com.google.auth.Credentials; +import com.google.auth.oauth2.GoogleCredentials; import com.google.cloud.opentelemetry.trace.TraceConfiguration; import com.google.cloud.opentelemetry.trace.TraceExporter; import com.google.cloud.spanner.Database; @@ -282,14 +284,19 @@ private void assertUpdateResult(long updateCount, String sql) } private void assertTrace(String sql) throws IOException, InterruptedException { + Credentials credentials; + if (env.getTestHelper().getOptions().getCredentials() != null) { + credentials = env.getTestHelper().getOptions().getCredentials(); + } else { + credentials = GoogleCredentials.getApplicationDefault(); + } + if (credentials == null) { + throw new IllegalStateException("No credentials found"); + } TraceServiceSettings settings = - env.getTestHelper().getOptions().getCredentials() == null - ? TraceServiceSettings.newBuilder().build() - : TraceServiceSettings.newBuilder() - .setCredentialsProvider( - FixedCredentialsProvider.create( - env.getTestHelper().getOptions().getCredentials())) - .build(); + TraceServiceSettings.newBuilder() + .setCredentialsProvider(FixedCredentialsProvider.create(credentials)) + .build(); try (TraceServiceClient client = TraceServiceClient.create(settings)) { // It can take a few seconds before the trace is visible. Thread.sleep(5000L); From 2858a3ee70ad53c652de2882c61517f891023f0a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Jul 2025 09:32:42 +0200 Subject: [PATCH 1729/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.31.1 (#2129) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index e545a922fdc6..cd16789b206b 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.0 + 2.31.1 From 0b2ba4ae41ced56ac5133aba947f881bc2c27e15 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:58:23 +0200 Subject: [PATCH 1730/1979] chore(main): release 2.31.2-SNAPSHOT (#2127) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b571b50ea54f..65e930421314 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.1 + 2.31.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b590b65496cc..fae2007b43e7 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.1 + 2.31.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 987cc0cb3473..0936cb93e360 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.1:2.31.1 +google-cloud-spanner-jdbc:2.31.1:2.31.2-SNAPSHOT From 6fa7b27dafe10f7c0d08c8c2eebb26d04c26b884 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 2 Jul 2025 09:58:39 +0200 Subject: [PATCH 1731/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.63.0 (#2130) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index a7f867c9c68a..69ce8b42bb63 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index b8e76427b82b..93cd35a9f10c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 0b5079181e39..c812eb5fc7da 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 290430724f7e..a8949af7ff93 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index bfee8d77abfd..d591ef0d56db 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index ddd94106fc23..510e9a1c947c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.62.0 + 26.63.0 import pom From 3663775226d85381b64183baa699ad6551cea4d6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 9 Jul 2025 17:58:23 +0200 Subject: [PATCH 1732/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.50.1 (#2131) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index ea62e6c39b27..4c509c3d073d 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 1d327c28dd86..412e08757746 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 5b98727f2751..0aceb4447c55 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 952a1c1b0322..5a7f173f6243 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 65e930421314..e546fb9bea42 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.50.0 + 3.50.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 69ce8b42bb63..38262ef2083e 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.50.0 + 3.50.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 93cd35a9f10c..49544bf45057 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.50.0 + 3.50.1 From 76a7699fb4c3d7d529fa446da29712e4a11d82f2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 16 Jul 2025 05:24:22 +0200 Subject: [PATCH 1733/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.97.1 (#2134) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d591ef0d56db..532485d2af15 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.96.1 + 6.97.1 test-jar test From 4a717d59dbef271197e02e7380d487d4cba97451 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 16 Jul 2025 05:31:19 +0200 Subject: [PATCH 1734/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.97.1 (#2135) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e546fb9bea42..e92b78916d9a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.1 + 6.97.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index c812eb5fc7da..03f644282959 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.1 + 6.97.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a8949af7ff93..0b0a5ef8c4c2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.1 + 6.97.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 532485d2af15..11efaba17fdc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.96.1 + 6.97.1 import pom From 3a215687f4979a1ceb302907b8143f5cd6310217 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 09:34:00 +0530 Subject: [PATCH 1735/1979] chore(main): release 2.31.2 (#2132) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 9 +++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index cdb10a012453..633f81479e96 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [2.31.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.1...v2.31.2) (2025-07-16) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-spanner to v6.97.1 ([#2134](https://github.com/googleapis/java-spanner-jdbc/issues/2134)) ([90f11b5](https://github.com/googleapis/java-spanner-jdbc/commit/90f11b5f5fbfbcd418e114dfc66d3accbc1c08eb)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.97.1 ([#2135](https://github.com/googleapis/java-spanner-jdbc/issues/2135)) ([a47dbed](https://github.com/googleapis/java-spanner-jdbc/commit/a47dbedc89a9c7125f90c6c44401214fc4a9794f)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.1 ([#2131](https://github.com/googleapis/java-spanner-jdbc/issues/2131)) ([9e059c4](https://github.com/googleapis/java-spanner-jdbc/commit/9e059c404e821afff6e8ab05454308497edc7abc)) + ## [2.31.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.0...v2.31.1) (2025-07-01) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 23a432fb2b3c..1c30f55267d9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.31.1 + 2.31.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e92b78916d9a..6475787fa118 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.2-SNAPSHOT + 2.31.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fae2007b43e7..79a7a5ee39cb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.2-SNAPSHOT + 2.31.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0936cb93e360..684e8c157f9a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.1:2.31.2-SNAPSHOT +google-cloud-spanner-jdbc:2.31.2:2.31.2 From d59c95a08c774938fe37357907f0435dcbea717c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 26 Jul 2025 06:50:39 +0200 Subject: [PATCH 1736/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.52.0 (#2137) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 03f644282959..51aa3fa11e38 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.51.0 + 1.52.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 0b0a5ef8c4c2..a36f623f09c7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.51.0 + 1.52.0 pom import From 1ade4e2bd31bd27dd2593ec17b92cd1a90f62334 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:39:19 +0200 Subject: [PATCH 1737/1979] chore(main): release 2.31.3-SNAPSHOT (#2143) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6475787fa118..a206642f9fa6 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.2 + 2.31.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 79a7a5ee39cb..8cab143f1a00 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.2 + 2.31.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 684e8c157f9a..34bd384f289f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.2:2.31.2 +google-cloud-spanner-jdbc:2.31.2:2.31.3-SNAPSHOT From 05e429cb10869eca2425fa8d57939fd7df61c103 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 10:44:55 +0200 Subject: [PATCH 1738/1979] deps: update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.5 (#2136) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 11efaba17fdc..14b63da8a236 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -60,7 +60,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - 3.0.4 + 3.0.5 org.mybatis.dynamic-sql diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 510e9a1c947c..071954df2c9d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -53,7 +53,7 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - 3.0.4 + 3.0.5 org.mybatis.dynamic-sql From 614048075a2abd331594feafc3a9db89d12d9141 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:00:41 +0200 Subject: [PATCH 1739/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.68.0 (#2140) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a206642f9fa6..b030a1355ba1 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.67.0 + 2.68.0 test From da906a500460649457db001aec11bb8e878c1d80 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:00:54 +0200 Subject: [PATCH 1740/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.31.2 (#2144) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index cd16789b206b..7eb50bba30d4 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.1 + 2.31.2 From 256903640ec4bdc382adc98ac8d3072ae2db1707 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:01:10 +0200 Subject: [PATCH 1741/1979] deps: update dependency org.apache.commons:commons-lang3 to v3.18.0 [security] (#2139) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 38262ef2083e..d7098cf78c2f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -62,7 +62,7 @@ org.apache.commons commons-lang3 - 3.17.0 + 3.18.0 com.fasterxml.jackson.core From ce2c1af2c7dabdc8ab432b82454c4dc21d742ae8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:01:24 +0200 Subject: [PATCH 1742/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.68.0 (#2141) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b030a1355ba1..b00b8f4cc628 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.67.0 + 2.68.0 test From e41c6692a87fe9fb3f14be66c3329d25c2614170 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:01:50 +0200 Subject: [PATCH 1743/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.64.0 (#2146) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d7098cf78c2f..8a894e2caee9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 49544bf45057..0b3d40088ce4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 51aa3fa11e38..25e75d84d9b5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a36f623f09c7..8bf7532474b2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 14b63da8a236..f529ccf9e499 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 071954df2c9d..ce075824d4f6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 import pom From c5ec3c441208f0c7fd5f3b133d996b33b62a7ce3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:02:03 +0200 Subject: [PATCH 1744/1979] deps: update dependency org.springframework.data:spring-data-bom to v2024.1.8 (#2147) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 25e75d84d9b5..8fbb3d0be9a0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.7 + 2024.1.8 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 8bf7532474b2..dfd46bd69c62 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.7 + 2024.1.8 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index f529ccf9e499..443afe7a6013 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.7 + 2024.1.8 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index ce075824d4f6..c1c24bf95578 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.7 + 2024.1.8 import pom From 38d059b417a78b82e44dff5841c04356aa044620 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:02:17 +0200 Subject: [PATCH 1745/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.2 (#2148) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 8a894e2caee9..0ec967ae6347 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.19.1 + 2.19.2 From 621a36a8db5823a7273955fce80d122177ae92d9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 11:02:33 +0200 Subject: [PATCH 1746/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.50.2 (#2149) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 4c509c3d073d..39f5accd7e97 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.2 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 412e08757746..3107bfda907c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 0aceb4447c55..6a20fa806b9c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 5a7f173f6243..b59f2dfc73d6 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.2" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b00b8f4cc628..8f8fd4e5f1ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.50.1 + 3.50.2 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 0ec967ae6347..1d67e277f8eb 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.50.1 + 3.50.2 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0b3d40088ce4..fd7ddb6b72a6 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.50.1 + 3.50.2 From 7a7997f0138a88a71cbf794d757c5ad825366a91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 14:09:28 +0200 Subject: [PATCH 1747/1979] build(deps): bump org.apache.commons:commons-lang3 in /samples/quickperf (#2138) Bumps org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From b7f72bdffdb7f48f9fc9c3a4523ceccb97b1397b Mon Sep 17 00:00:00 2001 From: "rayudu.alp" Date: Mon, 28 Jul 2025 17:40:13 +0530 Subject: [PATCH 1748/1979] chore: spring data jdbc version 2025.0.1 upgrade fix (#2142) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- .../java/com/google/cloud/spanner/sample/JdbcConfiguration.java | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 8fbb3d0be9a0..1976e415c0cd 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.8 + 2025.0.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java index 2537ed7d7d7d..9d45fef5bed7 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/src/main/java/com/google/cloud/spanner/sample/JdbcConfiguration.java @@ -24,11 +24,11 @@ import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Lazy; import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; -import org.springframework.data.jdbc.core.convert.JdbcArrayColumns; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; import org.springframework.data.jdbc.core.convert.RelationResolver; +import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns; import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration; diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index dfd46bd69c62..b39128167db8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2024.1.8 + 2025.0.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 443afe7a6013..fd888cc01007 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.8 + 2025.0.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index c1c24bf95578..f386b5e4fa52 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2024.1.8 + 2025.0.1 import pom From da13bad3a141d508ee364c8f1a140f21a4b02cd8 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 14:10:48 +0200 Subject: [PATCH 1749/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.4 (#2151) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 1d67e277f8eb..a27f46103c62 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.3 + 3.5.4 test From 7b96178e1635f14fbbd44709563086642b9932a0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 15:30:40 +0200 Subject: [PATCH 1750/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.4 (#2153) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index fd888cc01007..dd2bb48eb275 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.3 + 3.5.4 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index f386b5e4fa52..1ba6da59621b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.3 + 3.5.4 From 2f6be6de8f313245c1139791d1fd074b031f7c0a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 16:00:23 +0200 Subject: [PATCH 1751/1979] deps: update dependency org.springframework.data:spring-data-bom to v2025.0.2 (#2061) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 1976e415c0cd..5b35ec51d0d3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.1 + 2025.0.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b39128167db8..b5050c9bbe53 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.1 + 2025.0.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index dd2bb48eb275..68641aef0016 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.1 + 2025.0.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 1ba6da59621b..c8ee4906aac0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.1 + 2025.0.2 import pom From cf9fd4d18bada6b436c73d941c2dda386ae4e13d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 28 Jul 2025 16:30:17 +0200 Subject: [PATCH 1752/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.4 (#2152) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 5b35ec51d0d3..aabd49f4e911 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.3 + 3.5.4 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b5050c9bbe53..e3f847410afb 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.3 + 3.5.4 From 909cb8c788b4d8ef89cdcc8756937ff94a61ad84 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 14:58:46 +0200 Subject: [PATCH 1753/1979] chore(main): release 2.31.3 (#2150) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 633f81479e96..8d0f0d7fdcd6 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.31.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.2...v2.31.3) (2025-07-28) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.19.2 ([#2148](https://github.com/googleapis/java-spanner-jdbc/issues/2148)) ([0ef3b4f](https://github.com/googleapis/java-spanner-jdbc/commit/0ef3b4f9c19a19731d90195a192d6d466c3eacb8)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.68.0 ([#2140](https://github.com/googleapis/java-spanner-jdbc/issues/2140)) ([62f92c0](https://github.com/googleapis/java-spanner-jdbc/commit/62f92c04bbecfd98000710843339743d2c838d7a)) +* Update dependency com.google.cloud:google-cloud-trace to v2.68.0 ([#2141](https://github.com/googleapis/java-spanner-jdbc/issues/2141)) ([1036353](https://github.com/googleapis/java-spanner-jdbc/commit/1036353c9388610325c5c83b7544ee5e9198bfa0)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.2 ([#2149](https://github.com/googleapis/java-spanner-jdbc/issues/2149)) ([81f9307](https://github.com/googleapis/java-spanner-jdbc/commit/81f930740c714d696779656d9ac658ebe93312ac)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.52.0 ([#2137](https://github.com/googleapis/java-spanner-jdbc/issues/2137)) ([f1978b5](https://github.com/googleapis/java-spanner-jdbc/commit/f1978b500e96e8d7212bb2a0ac8a354467dd6638)) +* Update dependency org.apache.commons:commons-lang3 to v3.18.0 [security] ([#2139](https://github.com/googleapis/java-spanner-jdbc/issues/2139)) ([a12e520](https://github.com/googleapis/java-spanner-jdbc/commit/a12e520092c8613d90998a3151c850bc892ba90b)) +* Update dependency org.mybatis.spring.boot:mybatis-spring-boot-starter to v3.0.5 ([#2136](https://github.com/googleapis/java-spanner-jdbc/issues/2136)) ([6fcfa9d](https://github.com/googleapis/java-spanner-jdbc/commit/6fcfa9d749e35d5ee4b67bed6f8850202cee3b5a)) +* Update dependency org.springframework.boot:spring-boot to v3.5.4 ([#2151](https://github.com/googleapis/java-spanner-jdbc/issues/2151)) ([d121993](https://github.com/googleapis/java-spanner-jdbc/commit/d1219934e7cc6c12cef0a76b2ebffa8457c90614)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.4 ([#2152](https://github.com/googleapis/java-spanner-jdbc/issues/2152)) ([1f3b330](https://github.com/googleapis/java-spanner-jdbc/commit/1f3b33017724a2c9c227318dee422208b077d20e)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.4 ([#2153](https://github.com/googleapis/java-spanner-jdbc/issues/2153)) ([294fb97](https://github.com/googleapis/java-spanner-jdbc/commit/294fb97de0a583af25dbfccca2eff18a8e10bcfa)) +* Update dependency org.springframework.data:spring-data-bom to v2024.1.8 ([#2147](https://github.com/googleapis/java-spanner-jdbc/issues/2147)) ([925600d](https://github.com/googleapis/java-spanner-jdbc/commit/925600d1c15cfd5c950c08ef4a56492809801008)) +* Update dependency org.springframework.data:spring-data-bom to v2025.0.2 ([#2061](https://github.com/googleapis/java-spanner-jdbc/issues/2061)) ([81382ae](https://github.com/googleapis/java-spanner-jdbc/commit/81382aeb0e50f7655c52524a41e8325f638b0f48)) + ## [2.31.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.1...v2.31.2) (2025-07-16) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 1c30f55267d9..ad95234cab5c 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.31.2 + 2.31.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8f8fd4e5f1ab..a0f3a8ed2e93 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.3-SNAPSHOT + 2.31.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 8cab143f1a00..aea1e8b6371e 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.3-SNAPSHOT + 2.31.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 34bd384f289f..c173a5c2dd37 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.2:2.31.3-SNAPSHOT +google-cloud-spanner-jdbc:2.31.3:2.31.3 From de34e78da7b920f5dcc700185902a14a1e64a235 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 14:08:24 +0000 Subject: [PATCH 1754/1979] chore(main): release 2.31.4-SNAPSHOT (#2154) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a0f3a8ed2e93..c41d9f1f5810 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.3 + 2.31.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index aea1e8b6371e..6c9f65418321 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.3 + 2.31.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c173a5c2dd37..4a4e2772ba6c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.3:2.31.3 +google-cloud-spanner-jdbc:2.31.3:2.31.4-SNAPSHOT From d0c25e4d9bd96ad1ffa1c74d9ca52e7f06806a72 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 30 Jul 2025 15:30:50 +0200 Subject: [PATCH 1755/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.31.3 (#2155) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 7eb50bba30d4..1839425deddf 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.2 + 2.31.3 From 01708289104b1c85ef47ca00e22a1995b094e010 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 31 Jul 2025 13:52:32 +0200 Subject: [PATCH 1756/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.70.0 (#2157) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c41d9f1f5810..a224577dbc73 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.68.0 + 2.70.0 test From 1e599bf824cc152caee2aef31339f0d0b92578a9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 31 Jul 2025 14:57:23 +0200 Subject: [PATCH 1757/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.0 (#2161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.0 * test: update test cases as mux sessions are default --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 2 +- .../spring-data-jdbc/googlesql/pom.xml | 2 +- .../spring-data-jdbc/postgresql/pom.xml | 2 +- .../spring-data-mybatis/googlesql/pom.xml | 2 +- .../spanner/jdbc/JdbcConnectionUrlTest.java | 112 ------------------ .../cloud/spanner/jdbc/JdbcGrpcErrorTest.java | 84 ++++++------- .../MultiplexedSessionsMockServerTest.java | 8 +- 7 files changed, 52 insertions(+), 160 deletions(-) delete mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a224577dbc73..2b484f5250d9 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index aabd49f4e911..0574cd98df50 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index e3f847410afb..a13e1d3a6879 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 68641aef0016..aed7d10cab9d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java deleted file mode 100644 index 756007190c42..000000000000 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2021 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.assertTrue; - -import com.google.cloud.spanner.connection.AbstractMockServerTest; -import com.google.spanner.v1.BatchCreateSessionsRequest; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -@RunWith(Enclosed.class) -public class JdbcConnectionUrlTest { - - public static class ConnectionMinSessionsTest extends AbstractMockServerTest { - @AfterClass - public static void reset() { - mockSpanner.reset(); - } - - protected String getBaseUrl() { - return super.getBaseUrl() + ";minSessions=1"; - } - - @Test - public void testMinSessions() throws InterruptedException, TimeoutException, SQLException { - try (Connection connection = createJdbcConnection()) { - mockSpanner.waitForRequestsToContain( - input -> - input instanceof BatchCreateSessionsRequest - && ((BatchCreateSessionsRequest) input).getSessionCount() == 1, - 5000L); - } - } - } - - public static class ConnectionMaxSessionsTest extends AbstractMockServerTest { - - @AfterClass - public static void reset() { - mockSpanner.reset(); - } - - protected String getBaseUrl() { - return super.getBaseUrl() + ";minSessions=0;maxSessions=1"; - } - - @Test - public void testMaxSessions() - throws InterruptedException, TimeoutException, ExecutionException, SQLException { - ExecutorService executor1 = Executors.newSingleThreadExecutor(); - ExecutorService executor2 = Executors.newSingleThreadExecutor(); - - try (Connection connection1 = createJdbcConnection(); - Connection connection2 = createJdbcConnection()) { - final CountDownLatch latch = new CountDownLatch(1); - Future fut1 = - executor1.submit( - () -> { - assertTrue(latch.await(5L, TimeUnit.SECONDS)); - connection1.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection1.commit(); - return null; - }); - Future fut2 = - executor2.submit( - () -> { - latch.countDown(); - connection2.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection2.commit(); - return null; - }); - // Wait until both finishes. - fut1.get(5L, TimeUnit.SECONDS); - fut2.get(5L, TimeUnit.SECONDS); - } finally { - executor1.shutdown(); - executor2.shutdown(); - } - assertEquals(1, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); - BatchCreateSessionsRequest request = - mockSpanner.getRequestsOfType(BatchCreateSessionsRequest.class).get(0); - assertEquals(1, request.getSessionCount()); - } - } -} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index c337f64cf15c..147d76b31206 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -85,9 +85,10 @@ public class JdbcGrpcErrorTest { private static MockSpannerServiceImpl mockSpanner; private static Server server; - // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. + // INVALID_ARGUMENT is chosen as the test error code as it should never be retryable, and it does + // not overlap with the 'are multiplexed sessions supported?' check. private final Exception serverException = - Status.FAILED_PRECONDITION.withDescription("test exception").asRuntimeException(); + Status.INVALID_ARGUMENT.withDescription("test exception").asRuntimeException(); @BeforeClass public static void startStaticServer() throws IOException { @@ -152,7 +153,7 @@ private Connection createConnection() throws SQLException { @Test public void autocommitBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { // This triggers a retry with an explicit BeginTransaction RPC. mockSpanner.abortNextStatement(); @@ -160,7 +161,7 @@ public void autocommitBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -168,14 +169,14 @@ public void autocommitBeginTransaction() throws SQLException { @Test public void autocommitBeginPDMLTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -183,7 +184,7 @@ public void autocommitBeginPDMLTransaction() throws SQLException { @Test public void transactionalBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); // This triggers a retry with an explicit BeginTransaction RPC. @@ -192,7 +193,7 @@ public void transactionalBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -200,7 +201,7 @@ public void transactionalBeginTransaction() throws SQLException { @Test public void readOnlyBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -208,20 +209,21 @@ public void readOnlyBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void autocommitExecuteSql() throws SQLException { - mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -235,28 +237,29 @@ public void autocommitPDMLExecuteSql() throws SQLException { } mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalExecuteSql() throws SQLException { - mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -264,14 +267,14 @@ public void transactionalExecuteSql() throws SQLException { @Test public void autocommitExecuteBatchDml() throws SQLException { mockSpanner.setExecuteBatchDmlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -280,7 +283,7 @@ public void autocommitExecuteBatchDml() throws SQLException { @Test public void transactionalExecuteBatchDml() throws SQLException { mockSpanner.setExecuteBatchDmlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); try (java.sql.Statement statement = connection.createStatement()) { @@ -288,7 +291,7 @@ public void transactionalExecuteBatchDml() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -296,26 +299,26 @@ public void transactionalExecuteBatchDml() throws SQLException { @Test public void autocommitCommit() throws SQLException { - mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalCommit() throws SQLException { - mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, connection::commit); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -324,7 +327,7 @@ public void transactionalCommit() throws SQLException { public void autocommitRollback() throws SQLException { // The JDBC driver should throw the exception of the SQL statement and ignore any errors from // the rollback() method. - mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( @@ -340,7 +343,7 @@ public void autocommitRollback() throws SQLException { public void transactionalRollback() throws SQLException { // Rollback exceptions are ignored by the client library and not propagated to the JDBC driver. // This method will therefore not throw any errors. - mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); @@ -357,13 +360,13 @@ public void autocommitExecuteStreamingSql() throws SQLException { } mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -371,14 +374,14 @@ public void autocommitExecuteStreamingSql() throws SQLException { @Test public void transactionalExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -386,7 +389,7 @@ public void transactionalExecuteStreamingSql() throws SQLException { @Test public void readOnlyExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -394,43 +397,44 @@ public void readOnlyExecuteStreamingSql() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void autocommitCreateSession() throws SQLException { - mockSpanner.setBatchCreateSessionsExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalCreateSession() throws SQLException { - mockSpanner.setBatchCreateSessionsExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void readOnlyCreateSession() throws SQLException { - mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -438,7 +442,7 @@ public void readOnlyCreateSession() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java index 9fc6a89ddf9c..57b79a026e96 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -137,7 +137,7 @@ public void testUsesMultiplexedSessionForQueryInReadOnlyTransaction() throws SQL } @Test - public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { + public void testUsesMultiplexedSessionForDmlInAutoCommit() throws SQLException { try (Connection connection = createJdbcConnection()) { assertTrue(connection.getAutoCommit()); assertEquals(1, connection.createStatement().executeUpdate(INSERT_SQL)); @@ -154,11 +154,11 @@ public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); Session session = MockServerHelper.getSession(mockSpanner, sessionId); assertNotNull(session); - assertFalse(session.getMultiplexed()); + assertTrue(session.getMultiplexed()); } @Test - public void testUsesRegularSessionForQueryInTransaction() throws SQLException { + public void testUsesMultiplexedSessionForQueryInTransaction() throws SQLException { try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(false); assertFalse(connection.getAutoCommit()); @@ -183,7 +183,7 @@ public void testUsesRegularSessionForQueryInTransaction() throws SQLException { String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); Session session = MockServerHelper.getSession(mockSpanner, sessionId); assertNotNull(session); - assertFalse(session.getMultiplexed()); + assertTrue(session.getMultiplexed()); } @Test From 27a956065f5e51b4cfba2496385adb7dcb79ce3d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 31 Jul 2025 15:31:09 +0200 Subject: [PATCH 1758/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.70.0 (#2158) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 2b484f5250d9..f5452ee5678f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.68.0 + 2.70.0 test From 52ecf9ab956973a72e1314e61457bf15c645a9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 31 Jul 2025 16:02:24 +0200 Subject: [PATCH 1759/1979] feat: a single multiplexed session is used for all operations (#2162) The JDBC driver now uses a single multiplexed session for all operations. This applies to all operations in auto-commit mode, in read-only transactions, and in read/write transactions. One multiplexed session can execute an unlimited number of operations concurrently. Configuring minSessions and maxSessions in the connection URL is therefore no longer needed for workloads that execute a large number of concurrent transactions. --- java-spanner-jdbc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index ad95234cab5c..a0626b3dd6da 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -117,8 +117,8 @@ supported connection properties. - optimizerVersion (String): Sets the default query optimizer version to use for this connection. See also https://cloud.google.com/spanner/docs/query-optimizer/query-optimizer-versions. #### Advanced Properties -- minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. -- maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. +- DEPRECATED minSessions (int): Sets the minimum number of sessions in the backing session pool. Defaults to 100. This configuration option is no longer needed, as the JDBC driver by default uses a [single multiplexed session for all operations](https://cloud.google.com/spanner/docs/sessions#multiplexed_sessions). +- DEPRECATED maxSessions (int): Sets the maximum number of sessions in the backing session pool. Defaults to 400. This configuration option is no longer needed, as the JDBC driver by default uses a [single multiplexed session for all operations](https://cloud.google.com/spanner/docs/sessions#multiplexed_sessions). - numChannels (int): Sets the number of gRPC channels to use. Defaults to 4. - retryAbortsInternally (boolean): The JDBC driver will by default automatically retry aborted transactions internally. This is done by keeping track of all statements and the results of these during a transaction, and if the transaction is aborted by Cloud Spanner, it will replay the statements on a new transaction and compare the results with the initial attempt. Disable this option if you want to handle aborted transactions in your own application. - autocommit_dml_mode (string): Determines the transaction type that is used to execute From 529b5ba80ddceb6fb40d2d64e99b9590c3729375 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 31 Jul 2025 16:46:06 +0200 Subject: [PATCH 1760/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.98.0 (#2160) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index aed7d10cab9d..deaf7e5cb746 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.97.1 + 6.98.0 test-jar test From 734718b530a1609b00930e935eff34f378cfe883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 31 Jul 2025 17:16:23 +0200 Subject: [PATCH 1761/1979] chore: support simple statement param metadata (#2163) Add an option to use simple PreparedStatement ParameterMetadata that only uses client-side information. This prevents round-trips to Spanner when calling the method PreparedStatement#getParameterMetaData(), for example when these are triggered by frameworks like Spring Data. This option is experimental and could be removed in future releases. The option can be enabled by setting the system property `spanner.jdbc.use_simple_parameter_metadata=true` --- .../spanner/jdbc/JdbcPreparedStatement.java | 11 +- .../jdbc/JdbcSimpleParameterMetaData.java | 102 ++++++++++++++++++ .../jdbc/JdbcPreparedStatementTest.java | 8 +- ...reparedStatementParameterMetadataTest.java | 32 ++++++ 4 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSimpleParameterMetaData.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java index 9ebbc98f5452..ad74234221c4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatement.java @@ -29,6 +29,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.rpc.Code; +import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; @@ -117,8 +118,16 @@ public void addBatch() throws SQLException { } @Override - public JdbcParameterMetaData getParameterMetaData() throws SQLException { + public ParameterMetaData getParameterMetaData() throws SQLException { checkClosed(); + + // NOTE: JdbcSimpleParameterMetaData is an experimental feature that can be removed without + // warning in a future version. Your application should not assume that this feature will + // continue to be supported. + if (JdbcSimpleParameterMetaData.useSimpleParameterMetadata()) { + return new JdbcSimpleParameterMetaData(this.parameters); + } + if (cachedParameterMetadata == null) { if (getConnection().getParser().isUpdateStatement(sql) && !getConnection().getParser().checkReturningClause(sql)) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSimpleParameterMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSimpleParameterMetaData.java new file mode 100644 index 000000000000..b458573d0d39 --- /dev/null +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcSimpleParameterMetaData.java @@ -0,0 +1,102 @@ +/* + * Copyright 2025 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.api.core.BetaApi; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; +import java.sql.ParameterMetaData; +import java.sql.SQLException; +import java.sql.Types; + +/** + * {@link JdbcSimpleParameterMetaData} implements {@link ParameterMetaData} without a round-trip to + * Spanner. This is an experimental feature that can be removed in a future version without prior + * warning. + */ +@BetaApi +class JdbcSimpleParameterMetaData implements ParameterMetaData { + static final String USE_SIMPLE_PARAMETER_METADATA_KEY = + "spanner.jdbc.use_simple_parameter_metadata"; + private final ParametersInfo parametersInfo; + + /** + * This is an experimental feature that can be removed in a future version without prior warning. + */ + @BetaApi + static boolean useSimpleParameterMetadata() { + return Boolean.parseBoolean(System.getProperty(USE_SIMPLE_PARAMETER_METADATA_KEY, "false")); + } + + JdbcSimpleParameterMetaData(ParametersInfo parametersInfo) { + this.parametersInfo = parametersInfo; + } + + @Override + public int getParameterCount() throws SQLException { + return this.parametersInfo.numberOfParameters; + } + + @Override + public int isNullable(int param) throws SQLException { + return ParameterMetaData.parameterNullableUnknown; + } + + @Override + public boolean isSigned(int param) throws SQLException { + return false; + } + + @Override + public int getPrecision(int param) throws SQLException { + return 0; + } + + @Override + public int getScale(int param) throws SQLException { + return 0; + } + + @Override + public int getParameterType(int param) throws SQLException { + return Types.OTHER; + } + + @Override + public String getParameterTypeName(int param) throws SQLException { + return "unknown"; + } + + @Override + public String getParameterClassName(int param) throws SQLException { + return Object.class.getName(); + } + + @Override + public int getParameterMode(int param) throws SQLException { + return ParameterMetaData.parameterModeIn; + } + + @Override + public T unwrap(Class iface) throws SQLException { + throw new SQLException("This is not a wrapper for " + iface.getName()); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java index c5748d1c71e6..c95c38b7a127 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcPreparedStatementTest.java @@ -221,7 +221,7 @@ public void testParameters() throws SQLException, MalformedURLException { ps.setObject(52, "{}", JsonType.VENDOR_TYPE_NUMBER); ps.setObject(53, "{}", PgJsonbType.VENDOR_TYPE_NUMBER); - JdbcParameterMetaData pmd = ps.getParameterMetaData(); + JdbcParameterMetaData pmd = (JdbcParameterMetaData) ps.getParameterMetaData(); assertEquals(numberOfParams, pmd.getParameterCount()); assertEquals(JdbcArray.class.getName(), pmd.getParameterClassName(1)); assertEquals(ByteArrayInputStream.class.getName(), pmd.getParameterClassName(2)); @@ -281,7 +281,7 @@ public void testParameters() throws SQLException, MalformedURLException { assertEquals(String.class.getName(), pmd.getParameterClassName(51)); ps.clearParameters(); - pmd = ps.getParameterMetaData(); + pmd = (JdbcParameterMetaData) ps.getParameterMetaData(); assertEquals(numberOfParams, pmd.getParameterCount()); } } @@ -329,12 +329,12 @@ public void testSetNullValues() throws SQLException { ps.setNull(++index, Types.NULL); assertEquals(numberOfParameters, index); - JdbcParameterMetaData pmd = ps.getParameterMetaData(); + JdbcParameterMetaData pmd = (JdbcParameterMetaData) ps.getParameterMetaData(); assertEquals(numberOfParameters, pmd.getParameterCount()); assertEquals(Timestamp.class.getName(), pmd.getParameterClassName(15)); ps.clearParameters(); - pmd = ps.getParameterMetaData(); + pmd = (JdbcParameterMetaData) ps.getParameterMetaData(); assertEquals(numberOfParameters, pmd.getParameterCount()); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java index a6d7c35420ba..55c93cca19b5 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/PreparedStatementParameterMetadataTest.java @@ -24,6 +24,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.SpannerPool; +import com.google.spanner.v1.ExecuteSqlRequest; import com.google.spanner.v1.ResultSet; import com.google.spanner.v1.ResultSetMetadata; import com.google.spanner.v1.ResultSetStats; @@ -133,6 +134,7 @@ public void testAllTypesParameterMetadata_GoogleSql() throws SQLException { assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("ARRAY", metadata.getParameterTypeName(index)); } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); } } @@ -214,6 +216,36 @@ public void testAllTypesParameterMetadata_PostgreSQL() throws SQLException { assertEquals(Types.ARRAY, metadata.getParameterType(++index)); assertEquals("timestamp with time zone[]", metadata.getParameterTypeName(index)); } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + } + + @Test + public void testSimpleJdbcParameterMetadata() throws SQLException { + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); + String baseSql = + "insert into all_types (col_bool, col_bytes, col_date, col_float32, col_float64, col_int64, " + + "col_json, col_numeric, col_string, col_timestamp, col_bool_array, col_bytes_array, " + + "col_date_array, col_float32_array, col_float64_array, col_int64_array, col_json_array," + + "col_numeric_array, col_string_array, col_timestamp_array) values (%s)"; + String jdbcSql = + String.format( + baseSql, + IntStream.range(0, 20).mapToObj(ignored -> "?").collect(Collectors.joining(", "))); + + System.setProperty(JdbcSimpleParameterMetaData.USE_SIMPLE_PARAMETER_METADATA_KEY, "true"); + try (Connection connection = createJdbcConnection()) { + try (PreparedStatement statement = connection.prepareStatement(jdbcSql)) { + ParameterMetaData metadata = statement.getParameterMetaData(); + assertEquals(20, metadata.getParameterCount()); + for (int i = 0; i < metadata.getParameterCount(); i++) { + assertEquals(Types.OTHER, metadata.getParameterType(i)); + } + } + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } finally { + System.clearProperty(JdbcSimpleParameterMetaData.USE_SIMPLE_PARAMETER_METADATA_KEY); } } From f1843ec4f996fcc759aa1828c6baf322fcfc6d16 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:25:50 +0200 Subject: [PATCH 1762/1979] chore(main): release 2.32.0 (#2159) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 15 +++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8d0f0d7fdcd6..ddf82c66938e 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [2.32.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.3...v2.32.0) (2025-07-31) + + +### Features + +* A single multiplexed session is used for all operations ([#2162](https://github.com/googleapis/java-spanner-jdbc/issues/2162)) ([21438cc](https://github.com/googleapis/java-spanner-jdbc/commit/21438cc88b9b5f5cb196c2a0e1c233a7ecb07b62)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.70.0 ([#2157](https://github.com/googleapis/java-spanner-jdbc/issues/2157)) ([9679471](https://github.com/googleapis/java-spanner-jdbc/commit/9679471e9e97b1770fc41b39a0050b8f77542588)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.98.0 ([#2160](https://github.com/googleapis/java-spanner-jdbc/issues/2160)) ([5893055](https://github.com/googleapis/java-spanner-jdbc/commit/589305520aa5474f36954018a72b561a6e0d8189)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.0 ([#2161](https://github.com/googleapis/java-spanner-jdbc/issues/2161)) ([b5345b1](https://github.com/googleapis/java-spanner-jdbc/commit/b5345b18506c1437c3a23e4aa3b7eb54db519e74)) +* Update dependency com.google.cloud:google-cloud-trace to v2.70.0 ([#2158](https://github.com/googleapis/java-spanner-jdbc/issues/2158)) ([d0caeb9](https://github.com/googleapis/java-spanner-jdbc/commit/d0caeb9ddb586fc44405ec1c7c4790ad82cd20cb)) + ## [2.31.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.2...v2.31.3) (2025-07-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a0626b3dd6da..a77143046c89 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.31.3 + 2.32.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.31.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.31.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f5452ee5678f..a4c092193210 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.31.4-SNAPSHOT + 2.32.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6c9f65418321..33a51ca43e43 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.4-SNAPSHOT + 2.32.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4a4e2772ba6c..b516d7af0d4b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.31.3:2.31.4-SNAPSHOT +google-cloud-spanner-jdbc:2.32.0:2.32.0 From 20e9338ff4d00e302503a4d977bf9638058033f1 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 16:54:23 +0000 Subject: [PATCH 1763/1979] chore(main): release 2.32.1-SNAPSHOT (#2164) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a4c092193210..dbd1401dc835 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.0 + 2.32.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 33a51ca43e43..2114b626361d 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.0 + 2.32.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index b516d7af0d4b..092510650b62 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.0:2.32.0 +google-cloud-spanner-jdbc:2.32.0:2.32.1-SNAPSHOT From ddc9c986bfe3b543304f47fce0e7426b9471ca78 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 1 Aug 2025 13:34:37 +0200 Subject: [PATCH 1764/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.0 (#2165) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1839425deddf..430c4fb373ac 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.31.3 + 2.32.0 From 3f2dcb5524c27d671f71dbd99ce62e2bc595d183 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 4 Aug 2025 17:00:37 +0200 Subject: [PATCH 1765/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.65.0 (#2166) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index a27f46103c62..9711cc2316db 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fd7ddb6b72a6..fe329443b4db 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 0574cd98df50..cd67913afdab 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a13e1d3a6879..2bea4c2c5362 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index deaf7e5cb746..cbb6ab01e361 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index c8ee4906aac0..83e083552818 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.64.0 + 26.65.0 import pom From c73228d1b91506e87367675a8378b12cbe29ff76 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 8 Aug 2025 08:13:32 +0200 Subject: [PATCH 1766/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.51.0 (#2168) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 39f5accd7e97..02c7e6b37089 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.2 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.51.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 3107bfda907c..67910699e9b3 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.51.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 6a20fa806b9c..b93be6b53acd 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.51.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index b59f2dfc73d6..cbe595c94642 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.51.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dbd1401dc835..953136555173 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.50.2 + 3.51.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 9711cc2316db..f0172c6dfd7b 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.50.2 + 3.51.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fe329443b4db..4095f74370b3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.50.2 + 3.51.0 From 48ccd77fcc3a991fba34d9b1d200e3da6fcf7a1e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:24:40 +0200 Subject: [PATCH 1767/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.1 (#2176) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 953136555173..c8aef9d43432 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.0 + 6.98.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index cd67913afdab..ed939f4fe23f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.0 + 6.98.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 2bea4c2c5362..c3703b3c9d8a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.0 + 6.98.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index cbb6ab01e361..eac0470b45f5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.0 + 6.98.1 import pom From cfd018e3bfc023ac7ddc04d6e5e4e8dfe75cd6c3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:24:59 +0200 Subject: [PATCH 1768/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.98.1 (#2175) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index eac0470b45f5..bdd7fa727ee5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.98.0 + 6.98.1 test-jar test From b562db14c6b6d20c42b0f90b5ec2c0212f8753fb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:44:30 +0200 Subject: [PATCH 1769/1979] deps: update dependency commons-cli:commons-cli to v1.10.0 (#2167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [commons-cli:commons-cli](https://commons.apache.org/proper/commons-cli/) ([source](https://gitbox.apache.org/repos/asf?p=commons-cli.git)) | `1.9.0` -> `1.10.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/commons-cli:commons-cli/1.10.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/commons-cli:commons-cli/1.10.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/commons-cli:commons-cli/1.9.0/1.10.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/commons-cli:commons-cli/1.9.0/1.10.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index f0172c6dfd7b..688e7f5cc5d8 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -47,7 +47,7 @@ commons-cli commons-cli - 1.9.0 + 1.10.0 com.google.cloud From 62f3ca11c74299c3ebad07bc963bdd486bb40465 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:46:22 +0200 Subject: [PATCH 1770/1979] deps: update actions/checkout action to v5 (#2174) --- .../.github/workflows/integration-tests-against-emulator.yaml | 2 +- java-spanner-jdbc/.github/workflows/quickperf.yaml | 2 +- java-spanner-jdbc/.github/workflows/sample-tests.yml | 2 +- .../.github/workflows/spring-data-jdbc-sample.yaml | 2 +- .../.github/workflows/spring-data-mybatis-sample.yaml | 2 +- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index ccf1ebd1fd66..a8c0d9fa9004 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -16,7 +16,7 @@ jobs: - 9020:9020 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/quickperf.yaml b/java-spanner-jdbc/.github/workflows/quickperf.yaml index 03c242fefe92..694175c572cd 100644 --- a/java-spanner-jdbc/.github/workflows/quickperf.yaml +++ b/java-spanner-jdbc/.github/workflows/quickperf.yaml @@ -20,7 +20,7 @@ jobs: quickperf: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml index eae9314cf8f1..579904eb7d55 100644 --- a/java-spanner-jdbc/.github/workflows/sample-tests.yml +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -20,7 +20,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index 7d5b4ea41334..2331f232a197 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-jdbc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index e7dfbc7b36aa..439778717508 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-mybatis: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 02c7e6b37089..82800a5bbaf1 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -5,7 +5,7 @@ jobs: unmanaged_dependency_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-java@v4 with: distribution: temurin From e7a1e6a4fcbaec6885f5f71a8c0c0e47f394698b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:57:48 +0200 Subject: [PATCH 1771/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.53.0 (#2173) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index ed939f4fe23f..19502db703e9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.52.0 + 1.53.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index c3703b3c9d8a..a3a9991eb9a2 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.52.0 + 1.53.0 pom import From 310598af780dc351b21d293876879d00f9cf1b95 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 18:58:00 +0200 Subject: [PATCH 1772/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.71.0 (#2172) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c8aef9d43432..4b6e2ad25e35 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.70.0 + 2.71.0 test From 3e070c6e4fb796d1f2a591f7b7c08e5625fc8053 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 12 Aug 2025 19:06:29 +0200 Subject: [PATCH 1773/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.71.0 (#2171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.70.0` -> `2.71.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.70.0/2.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.70.0/2.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4b6e2ad25e35..4d05e73b1341 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.70.0 + 2.71.0 test From 51bd36c7f7c3e40771629b2e72a4760280840d52 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:52:30 +0000 Subject: [PATCH 1774/1979] chore(main): release 2.32.1 (#2170) :robot: I have created a release *beep* *boop* --- ## [2.32.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.32.0...v2.32.1) (2025-08-12) ### Dependencies * Update actions/checkout action to v5 ([#2174](https://togithub.com/googleapis/java-spanner-jdbc/issues/2174)) ([62f3ca1](https://togithub.com/googleapis/java-spanner-jdbc/commit/62f3ca11c74299c3ebad07bc963bdd486bb40465)) * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.71.0 ([#2171](https://togithub.com/googleapis/java-spanner-jdbc/issues/2171)) ([3e070c6](https://togithub.com/googleapis/java-spanner-jdbc/commit/3e070c6e4fb796d1f2a591f7b7c08e5625fc8053)) * Update dependency com.google.cloud:google-cloud-spanner to v6.98.1 ([#2175](https://togithub.com/googleapis/java-spanner-jdbc/issues/2175)) ([cfd018e](https://togithub.com/googleapis/java-spanner-jdbc/commit/cfd018e3bfc023ac7ddc04d6e5e4e8dfe75cd6c3)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.1 ([#2176](https://togithub.com/googleapis/java-spanner-jdbc/issues/2176)) ([48ccd77](https://togithub.com/googleapis/java-spanner-jdbc/commit/48ccd77fcc3a991fba34d9b1d200e3da6fcf7a1e)) * Update dependency com.google.cloud:google-cloud-trace to v2.71.0 ([#2172](https://togithub.com/googleapis/java-spanner-jdbc/issues/2172)) ([310598a](https://togithub.com/googleapis/java-spanner-jdbc/commit/310598af780dc351b21d293876879d00f9cf1b95)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.51.0 ([#2168](https://togithub.com/googleapis/java-spanner-jdbc/issues/2168)) ([c73228d](https://togithub.com/googleapis/java-spanner-jdbc/commit/c73228d1b91506e87367675a8378b12cbe29ff76)) * Update dependency commons-cli:commons-cli to v1.10.0 ([#2167](https://togithub.com/googleapis/java-spanner-jdbc/issues/2167)) ([b562db1](https://togithub.com/googleapis/java-spanner-jdbc/commit/b562db14c6b6d20c42b0f90b5ec2c0212f8753fb)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.53.0 ([#2173](https://togithub.com/googleapis/java-spanner-jdbc/issues/2173)) ([e7a1e6a](https://togithub.com/googleapis/java-spanner-jdbc/commit/e7a1e6a4fcbaec6885f5f71a8c0c0e47f394698b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 14 ++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ddf82c66938e..8c5d3f805435 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.32.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.0...v2.32.1) (2025-08-12) + + +### Dependencies + +* Update actions/checkout action to v5 ([#2174](https://github.com/googleapis/java-spanner-jdbc/issues/2174)) ([46378ca](https://github.com/googleapis/java-spanner-jdbc/commit/46378caa33c6d78223d65cb0ea11e39784d75a9e)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.71.0 ([#2171](https://github.com/googleapis/java-spanner-jdbc/issues/2171)) ([6713d5c](https://github.com/googleapis/java-spanner-jdbc/commit/6713d5c2ef7af8fb68e3a1ada8b1f71f4137a209)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.98.1 ([#2175](https://github.com/googleapis/java-spanner-jdbc/issues/2175)) ([3a4d7ec](https://github.com/googleapis/java-spanner-jdbc/commit/3a4d7ecc907eb7c5da1bd19ce50d86cf677deaa8)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.1 ([#2176](https://github.com/googleapis/java-spanner-jdbc/issues/2176)) ([f44a15e](https://github.com/googleapis/java-spanner-jdbc/commit/f44a15e25b3c7b4163ae1075f6932e6e3c5cb5f1)) +* Update dependency com.google.cloud:google-cloud-trace to v2.71.0 ([#2172](https://github.com/googleapis/java-spanner-jdbc/issues/2172)) ([3159c4f](https://github.com/googleapis/java-spanner-jdbc/commit/3159c4f1c6c81db4e1095f0a52c7e7d51e51c6a2)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.51.0 ([#2168](https://github.com/googleapis/java-spanner-jdbc/issues/2168)) ([ecf1a07](https://github.com/googleapis/java-spanner-jdbc/commit/ecf1a0782defc37af9ccffe7488506e904950809)) +* Update dependency commons-cli:commons-cli to v1.10.0 ([#2167](https://github.com/googleapis/java-spanner-jdbc/issues/2167)) ([1ef709d](https://github.com/googleapis/java-spanner-jdbc/commit/1ef709d22e9131f2e84dc657cd8a2a56d682d29a)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.53.0 ([#2173](https://github.com/googleapis/java-spanner-jdbc/issues/2173)) ([a61de5c](https://github.com/googleapis/java-spanner-jdbc/commit/a61de5c62d90d16e0ad6207e24424aa57442e349)) + ## [2.32.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.31.3...v2.32.0) (2025-07-31) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index a77143046c89..71800b3bcb4b 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.32.0 + 2.32.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4d05e73b1341..0544af870738 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.1-SNAPSHOT + 2.32.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 2114b626361d..ba9da5c73000 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.1-SNAPSHOT + 2.32.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 092510650b62..0ee7f9ab82a8 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.0:2.32.1-SNAPSHOT +google-cloud-spanner-jdbc:2.32.1:2.32.1 From 7b6940a9e4e21e0a1e062d34e9ad9f4f6db316c7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 04:58:22 +0000 Subject: [PATCH 1775/1979] chore(main): release 2.32.2-SNAPSHOT (#2177) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0544af870738..3266d9ffa138 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.1 + 2.32.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ba9da5c73000..436b203584b5 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.1 + 2.32.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0ee7f9ab82a8..82cbdc6ed147 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.1:2.32.1 +google-cloud-spanner-jdbc:2.32.1:2.32.2-SNAPSHOT From 0df9fee2ef22c3223995c7b79a023efa96c7a125 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Aug 2025 17:06:26 +0200 Subject: [PATCH 1776/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.1 (#2178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.32.0` -> `2.32.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.32.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.32.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.32.0/2.32.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.32.0/2.32.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.32.1`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2321-2025-08-12) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.32.0...v2.32.1) ##### Dependencies - Update actions/checkout action to v5 ([#​2174](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2174)) ([62f3ca1](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/62f3ca11c74299c3ebad07bc963bdd486bb40465)) - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.71.0 ([#​2171](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2171)) ([3e070c6](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/3e070c6e4fb796d1f2a591f7b7c08e5625fc8053)) - Update dependency com.google.cloud:google-cloud-spanner to v6.98.1 ([#​2175](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2175)) ([cfd018e](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/cfd018e3bfc023ac7ddc04d6e5e4e8dfe75cd6c3)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.1 ([#​2176](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2176)) ([48ccd77](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/48ccd77fcc3a991fba34d9b1d200e3da6fcf7a1e)) - Update dependency com.google.cloud:google-cloud-trace to v2.71.0 ([#​2172](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2172)) ([310598a](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/310598af780dc351b21d293876879d00f9cf1b95)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.51.0 ([#​2168](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2168)) ([c73228d](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/c73228d1b91506e87367675a8378b12cbe29ff76)) - Update dependency commons-cli:commons-cli to v1.10.0 ([#​2167](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2167)) ([b562db1](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/b562db14c6b6d20c42b0f90b5ec2c0212f8753fb)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.53.0 ([#​2173](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2173)) ([e7a1e6a](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/e7a1e6a4fcbaec6885f5f71a8c0c0e47f394698b))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 430c4fb373ac..24da0bdc90db 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.0 + 2.32.1 From c6dd47b5a4bbe8fcbbc73bfc34e2077e3911deff Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Aug 2025 17:09:50 +0200 Subject: [PATCH 1777/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.72.0 (#2179) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 3266d9ffa138..f0dc922ea02f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.71.0 + 2.72.0 test From 031f7c6843a45a19d4b847d3e80ca883f192a690 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Aug 2025 17:10:18 +0200 Subject: [PATCH 1778/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.72.0 (#2180) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f0dc922ea02f..85b95e148bd8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.71.0 + 2.72.0 test From f38819b126d2c3d8c08d205e804fd2dca0131c14 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Aug 2025 17:10:50 +0200 Subject: [PATCH 1779/1979] deps: update dependency org.springframework.data:spring-data-bom to v2025.0.3 (#2181) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 19502db703e9..cd8c4c141d40 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.2 + 2025.0.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a3a9991eb9a2..407a8b89e79d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.2 + 2025.0.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index bdd7fa727ee5..492321eaeae1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.2 + 2025.0.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 83e083552818..152991af8ca9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.2 + 2025.0.3 import pom From d54621f347e913b9f92b6b3313d914d8c26362c3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 17 Aug 2025 18:18:22 +0200 Subject: [PATCH 1780/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.66.0 (#2182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.65.0` -> `26.66.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.66.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.66.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.65.0/26.66.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.65.0/26.66.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.66.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26660-2025-08-15) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.65.0...v26.66.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.51.0 ([#​7146](https://redirect.github.com/googleapis/java-cloud-bom/issues/7146)) ([0064be3](https://redirect.github.com/googleapis/java-cloud-bom/commit/0064be3b306a1714525bac9453df7df2fceaa0b1)) - update dependency com.google.cloud:gapic-libraries-bom to v1.66.0 ([#​7155](https://redirect.github.com/googleapis/java-cloud-bom/issues/7155)) ([2848092](https://redirect.github.com/googleapis/java-cloud-bom/commit/28480920a34e5fb661ba12070d394d6b0ce740d7)) - update dependency com.google.cloud:google-cloud-bigquery to v2.54.1 ([#​7158](https://redirect.github.com/googleapis/java-cloud-bom/issues/7158)) ([e42b23d](https://redirect.github.com/googleapis/java-cloud-bom/commit/e42b23d8ae5ef9c314c3206582f55632fa6fc13d)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.16.2 ([#​7147](https://redirect.github.com/googleapis/java-cloud-bom/issues/7147)) ([822732e](https://redirect.github.com/googleapis/java-cloud-bom/commit/822732e09e2ef7fea4adbb90191572169c4ca888)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.65.0 ([#​7156](https://redirect.github.com/googleapis/java-cloud-bom/issues/7156)) ([9329cc4](https://redirect.github.com/googleapis/java-cloud-bom/commit/9329cc44ea98b4cb941b4def4955712578be6316)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.31.2 ([#​7148](https://redirect.github.com/googleapis/java-cloud-bom/issues/7148)) ([b5acc9c](https://redirect.github.com/googleapis/java-cloud-bom/commit/b5acc9ccbec013d26a19a7d49408d47a616a06de)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.32.1 ([#​7159](https://redirect.github.com/googleapis/java-cloud-bom/issues/7159)) ([430c212](https://redirect.github.com/googleapis/java-cloud-bom/commit/430c2120ba13438879b7eb5acb13eb40ebf6d62a)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.23.2 ([#​7149](https://redirect.github.com/googleapis/java-cloud-bom/issues/7149)) ([0a32fa1](https://redirect.github.com/googleapis/java-cloud-bom/commit/0a32fa1a03265264e732a8f3aae3fd27c062888e)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.132.13-alpha ([#​7150](https://redirect.github.com/googleapis/java-cloud-bom/issues/7150)) ([d3fb9c5](https://redirect.github.com/googleapis/java-cloud-bom/commit/d3fb9c54143c0ffd4172d005f518f05f0b15114b)) - update dependency com.google.cloud:google-cloud-nio to v0.128.2 ([#​7151](https://redirect.github.com/googleapis/java-cloud-bom/issues/7151)) ([c1475ca](https://redirect.github.com/googleapis/java-cloud-bom/commit/c1475ca5f9119b63c4542fb51f28a23558abb27f)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.141.2 ([#​7152](https://redirect.github.com/googleapis/java-cloud-bom/issues/7152)) ([45a2d3f](https://redirect.github.com/googleapis/java-cloud-bom/commit/45a2d3f78efcda2d7b84b2411eafa2fd9dcde34b)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.15.13 ([#​7153](https://redirect.github.com/googleapis/java-cloud-bom/issues/7153)) ([6ee2ee6](https://redirect.github.com/googleapis/java-cloud-bom/commit/6ee2ee606c63763d244ce147d9d5831b347a113f)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.98.1 ([#​7154](https://redirect.github.com/googleapis/java-cloud-bom/issues/7154)) ([58c4bf6](https://redirect.github.com/googleapis/java-cloud-bom/commit/58c4bf6ab85cac71e818f5c54f361370650cc1da)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.1 ([#​7160](https://redirect.github.com/googleapis/java-cloud-bom/issues/7160)) ([3b64c48](https://redirect.github.com/googleapis/java-cloud-bom/commit/3b64c4843501ad023d045ac1b3e0c70a86f2dfea)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.55.0 ([#​7157](https://redirect.github.com/googleapis/java-cloud-bom/issues/7157)) ([47da2af](https://redirect.github.com/googleapis/java-cloud-bom/commit/47da2af69a62eef497a9a651b2406d09a1a23caa))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 688e7f5cc5d8..82c183484b54 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 4095f74370b3..a098f9d77074 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index cd8c4c141d40..e2b0b0aaee8c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 407a8b89e79d..8f903aa9beb8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 492321eaeae1..f88e38ffa4cf 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 152991af8ca9..2ae6fc9e22c6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.65.0 + 26.66.0 import pom From 28e711730dece3c1271cf3d639f75695ac459290 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 20 Aug 2025 18:24:27 +0200 Subject: [PATCH 1781/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.52.0 (#2184) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 82800a5bbaf1..d35a71f28fd3 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.51.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 67910699e9b3..15e20c8995ca 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.51.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index b93be6b53acd..97ef9db6a096 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.51.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index cbe595c94642..53bb1a1cf035 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.51.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 85b95e148bd8..ef814c0f60fe 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.51.0 + 3.52.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 82c183484b54..55a1c6ff1643 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.51.0 + 3.52.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a098f9d77074..8a851d30bf81 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.51.0 + 3.52.0 From e406d1be9b6f1d53d4ad78adad235c37671eb0ed Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Aug 2025 09:29:35 +0200 Subject: [PATCH 1782/1979] deps: update actions/setup-java action to v5 (#2185) --- .../.github/workflows/integration-tests-against-emulator.yaml | 2 +- java-spanner-jdbc/.github/workflows/quickperf.yaml | 2 +- java-spanner-jdbc/.github/workflows/sample-tests.yml | 2 +- .../.github/workflows/spring-data-jdbc-sample.yaml | 2 +- .../.github/workflows/spring-data-mybatis-sample.yaml | 2 +- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index a8c0d9fa9004..7669c2806927 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/quickperf.yaml b/java-spanner-jdbc/.github/workflows/quickperf.yaml index 694175c572cd..aa0bf2b547d4 100644 --- a/java-spanner-jdbc/.github/workflows/quickperf.yaml +++ b/java-spanner-jdbc/.github/workflows/quickperf.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 17 diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml index 579904eb7d55..056ef15cc20c 100644 --- a/java-spanner-jdbc/.github/workflows/sample-tests.yml +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 8 diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index 2331f232a197..07b41e4ec7fb 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 17 diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index 439778717508..84dc6e521e4d 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 17 diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index d35a71f28fd3..bc6305810d33 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 11 From 26df5359c981a3a28511f415e4c98824754fd1a2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Aug 2025 09:29:53 +0200 Subject: [PATCH 1783/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.5 (#2186) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 55a1c6ff1643..5be697300feb 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.4 + 3.5.5 test From 1e002fda770174e18dc99a0ae3924d9e9e10fac1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Aug 2025 09:30:15 +0200 Subject: [PATCH 1784/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.5 (#2188) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index f88e38ffa4cf..04c16d2fdf08 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.4 + 3.5.5 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 2ae6fc9e22c6..3ba3f4f728e5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.4 + 3.5.5 From e62e03e7db9608b87f71c10913e04adf6170b688 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 22 Aug 2025 10:36:25 +0200 Subject: [PATCH 1785/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.5 (#2187) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index e2b0b0aaee8c..f44e614932fc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.4 + 3.5.5 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 8f903aa9beb8..d5226731b3a4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.4 + 3.5.5 From efc993e16957f0a6c3e34dbe0fc0cd8c89bc2584 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Aug 2025 18:48:24 +0200 Subject: [PATCH 1786/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.73.0 (#2189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.72.0` -> `2.73.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.72.0/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.72.0/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ef814c0f60fe..0a10e91a745d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.72.0 + 2.73.0 test From 461838293248bf79a7273ba9134a14646abb5624 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 26 Aug 2025 18:50:28 +0200 Subject: [PATCH 1787/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.73.0 (#2190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.72.0` -> `2.73.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.72.0/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.72.0/2.73.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0a10e91a745d..868846070d85 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.72.0 + 2.73.0 test From c5b3c1c5c5f19b76e35cfcfa87f777e2c3a0f296 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 28 Aug 2025 08:00:36 +0200 Subject: [PATCH 1788/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.99.0 (#2192) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 04c16d2fdf08..b6de4af6c596 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.98.1 + 6.99.0 test-jar test From bf73609b025859fba4f68bb693700bfbc05004bd Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 28 Aug 2025 08:01:00 +0200 Subject: [PATCH 1789/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.99.0 (#2193) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 868846070d85..639f2ae35b28 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.1 + 6.99.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index f44e614932fc..ddbd95f20d18 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.1 + 6.99.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index d5226731b3a4..a77f87bf6d6f 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.1 + 6.99.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index b6de4af6c596..5d1dfd366e24 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.98.1 + 6.99.0 import pom From d7162658c13e690f2e923f04679b7703107835aa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 08:31:00 +0200 Subject: [PATCH 1790/1979] chore(main): release 2.32.2 (#2183) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 18 ++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 8c5d3f805435..e2da1c267aab 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [2.32.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.1...v2.32.2) (2025-08-28) + + +### Dependencies + +* Update actions/setup-java action to v5 ([#2185](https://github.com/googleapis/java-spanner-jdbc/issues/2185)) ([a0e1cec](https://github.com/googleapis/java-spanner-jdbc/commit/a0e1cec3789d12282b3a5d3b0e2353f3dfa0b68c)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.72.0 ([#2179](https://github.com/googleapis/java-spanner-jdbc/issues/2179)) ([3df3cf7](https://github.com/googleapis/java-spanner-jdbc/commit/3df3cf7c836b032968c78ed4ffefc4c0c6545494)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.73.0 ([#2189](https://github.com/googleapis/java-spanner-jdbc/issues/2189)) ([bc45d56](https://github.com/googleapis/java-spanner-jdbc/commit/bc45d567b462967a4cfbe8068027dbf14344c5a0)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.99.0 ([#2192](https://github.com/googleapis/java-spanner-jdbc/issues/2192)) ([db9732e](https://github.com/googleapis/java-spanner-jdbc/commit/db9732e11c5f83f3b2c53bb9c2b6b2a16d0579de)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.99.0 ([#2193](https://github.com/googleapis/java-spanner-jdbc/issues/2193)) ([54d482f](https://github.com/googleapis/java-spanner-jdbc/commit/54d482fc7723d63a0f1d98317c62fc798385b33a)) +* Update dependency com.google.cloud:google-cloud-trace to v2.72.0 ([#2180](https://github.com/googleapis/java-spanner-jdbc/issues/2180)) ([2ce3c39](https://github.com/googleapis/java-spanner-jdbc/commit/2ce3c39b4c5a2a42afca48de6ea065c6c6e85949)) +* Update dependency com.google.cloud:google-cloud-trace to v2.73.0 ([#2190](https://github.com/googleapis/java-spanner-jdbc/issues/2190)) ([a116a8f](https://github.com/googleapis/java-spanner-jdbc/commit/a116a8fac1773aeaf9543d92d6facbfd60a75461)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.0 ([#2184](https://github.com/googleapis/java-spanner-jdbc/issues/2184)) ([79ce6bc](https://github.com/googleapis/java-spanner-jdbc/commit/79ce6bcc3b4c46a46a09a5261019dc55ae2992b8)) +* Update dependency org.springframework.boot:spring-boot to v3.5.5 ([#2186](https://github.com/googleapis/java-spanner-jdbc/issues/2186)) ([75e71cc](https://github.com/googleapis/java-spanner-jdbc/commit/75e71ccd4f15016bf48d73f257f714cd676c19b4)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.5 ([#2187](https://github.com/googleapis/java-spanner-jdbc/issues/2187)) ([803f0dd](https://github.com/googleapis/java-spanner-jdbc/commit/803f0dd1c38abe2d6f78a1b3cf1676257e98ca9f)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.5 ([#2188](https://github.com/googleapis/java-spanner-jdbc/issues/2188)) ([fd383c7](https://github.com/googleapis/java-spanner-jdbc/commit/fd383c702b82b87e96cae6b77006ce6563c5a14b)) +* Update dependency org.springframework.data:spring-data-bom to v2025.0.3 ([#2181](https://github.com/googleapis/java-spanner-jdbc/issues/2181)) ([a1bab5a](https://github.com/googleapis/java-spanner-jdbc/commit/a1bab5a2d195c2974146c6d2e5756d4c265c4a21)) + ## [2.32.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.0...v2.32.1) (2025-08-12) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 71800b3bcb4b..b36d3cece54d 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.32.1 + 2.32.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 639f2ae35b28..98be6544275f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.2-SNAPSHOT + 2.32.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 436b203584b5..a8cc710d2829 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.2-SNAPSHOT + 2.32.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 82cbdc6ed147..062a338768f9 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.1:2.32.2-SNAPSHOT +google-cloud-spanner-jdbc:2.32.2:2.32.2 From b5eae52b69afac809075bec1f4af79c0840d9741 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Sep 2025 11:16:07 +0200 Subject: [PATCH 1791/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.2 (#2195) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 24da0bdc90db..05ff3bb12de7 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.1 + 2.32.2 From ac7bd8c06f7f58c8729191dcdd6052c492196988 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Sep 2025 11:16:20 +0200 Subject: [PATCH 1792/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.67.0 (#2196) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 5be697300feb..4700603ad8ae 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 8a851d30bf81..df31417e81c8 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index ddbd95f20d18..c8f4454b3355 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a77f87bf6d6f..2f6f7408b2ba 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 5d1dfd366e24..bd1605634f35 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 3ba3f4f728e5..59abf916c1ab 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.66.0 + 26.67.0 import pom From 10be366613e3795ac91c1eb5a5d5986faa9e58c2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Sep 2025 11:16:32 +0200 Subject: [PATCH 1793/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.0 (#2197) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4700603ad8ae..cbd0901b8bda 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.19.2 + 2.20.0 From c020cba5e056c12ae1589339d98ca5fa88c08a88 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Sep 2025 11:16:45 +0200 Subject: [PATCH 1794/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.52.1 (#2198) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index bc6305810d33..5b7dd21a160f 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 15e20c8995ca..f69120cbb2a0 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 97ef9db6a096..7f7797ccf2f6 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 53bb1a1cf035..0ed7b4e65b0b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 98be6544275f..813cb427796f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.52.0 + 3.52.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index cbd0901b8bda..da1c8551e540 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.52.0 + 3.52.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index df31417e81c8..fd661e4bc144 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.52.0 + 3.52.1 From 1776a1518932ae475d6559dff428fb3325f297c4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 8 Sep 2025 11:23:18 +0200 Subject: [PATCH 1795/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.54.0 (#2199) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index c8f4454b3355..db14e9cd0f76 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.53.0 + 1.54.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 2f6f7408b2ba..503fc542f3a4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.53.0 + 1.54.0 pom import From 1fb2387b48db7f2466e17fe6b24b82fa8138e60d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 11:48:09 +0200 Subject: [PATCH 1796/1979] chore(main): release 2.32.3-SNAPSHOT (#2194) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 813cb427796f..8c762be73c4c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.2 + 2.32.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a8cc710d2829..1507082a9976 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.2 + 2.32.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 062a338768f9..e21aefaed00a 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.2:2.32.2 +google-cloud-spanner-jdbc:2.32.2:2.32.3-SNAPSHOT From ad03ce14b1dde38c4c25768d9ef20a980fe126bc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Sep 2025 16:08:25 +0200 Subject: [PATCH 1797/1979] test(deps): update dependency com.google.truth:truth to v1.4.5 (#2202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.truth:truth](https://redirect.github.com/google/truth) | `1.4.4` -> `1.4.5` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.truth:truth/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.truth:truth/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.truth:truth/1.4.4/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.truth:truth/1.4.4/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    google/truth (com.google.truth:truth) ### [`v1.4.5`](https://redirect.github.com/google/truth/releases/tag/v1.4.5): 1.4.5 - Changed assertions like `assertThat(nullMap).isEmpty()` to fail with a useful failure message instead of throwing `NullPointerException` (and similarly for other "bogus" values, such as negative sizes). ([`da5d6e9`](https://redirect.github.com/google/truth/commit/da5d6e96f)) - Made Kotlin's `isInstanceOf(Int::class.java)` (and Java's `isInstanceOf(int.class)`) a valid way to check for `Int`/`Integer` instances. ([`974ef19`](https://redirect.github.com/google/truth/commit/974ef195b)) - Improved `isWithin` to pretty-print numbers in its failure messages. ([`de78553`](https://redirect.github.com/google/truth/commit/de785536d), [`07318c2`](https://redirect.github.com/google/truth/commit/07318c23e)) - Improved some assertions that print class names to print simpler names (e.g., `Integer` instead of `java.lang.Integer`). ([`0ba72d6`](https://redirect.github.com/google/truth/commit/0ba72d60fdb384aa97da03e2403a6757f63bf129)) - Changed `ExpectFailure` to never generate "value of" lines based on bytecode. This slightly simplifies writing new tests with `ExpectFailure` and prevents future behavior changes in some `ExpectFailure` tests that already exist. However, it may also require changes to other existing `ExpectFailure` tests to remove or change any assertions about the "value of" line. ([`3caa0e8`](https://redirect.github.com/google/truth/commit/3caa0e845)) - Our Android `minSdkVersion` is now 23 (Marshmallow). This follows the minimum of Google's foundational Android libraries, and we expect it to have no practical impact on users. ([`c85c75c`](https://redirect.github.com/google/truth/commit/c85c75cf4)) - Changed our GWT/J2CL artifact to omit usages of `@NullMarked`. This was making all our types non-null in those environments, since we don't yet use `@Nullable` in the GWT/J2CL artifact. ([`6392d37`](https://redirect.github.com/google/truth/commit/6392d37e7))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 05ff3bb12de7..ddb461ec2266 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.4 + 1.4.5 test diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 1507082a9976..b844615c498f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -42,7 +42,7 @@ com.google.truth truth - 1.4.4 + 1.4.5 test From ed590f4734108513ec7f4746c8a30043bbaa3b5d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Sep 2025 16:10:28 +0200 Subject: [PATCH 1798/1979] test(deps): update dependency com.google.truth:truth to v1.4.5 (#2201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.truth:truth](https://redirect.github.com/google/truth) | `1.4.4` -> `1.4.5` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.truth:truth/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.truth:truth/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.truth:truth/1.4.4/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.truth:truth/1.4.4/1.4.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    google/truth (com.google.truth:truth) ### [`v1.4.5`](https://redirect.github.com/google/truth/releases/tag/v1.4.5): 1.4.5 - Changed assertions like `assertThat(nullMap).isEmpty()` to fail with a useful failure message instead of throwing `NullPointerException` (and similarly for other "bogus" values, such as negative sizes). ([`da5d6e9`](https://redirect.github.com/google/truth/commit/da5d6e96f)) - Made Kotlin's `isInstanceOf(Int::class.java)` (and Java's `isInstanceOf(int.class)`) a valid way to check for `Int`/`Integer` instances. ([`974ef19`](https://redirect.github.com/google/truth/commit/974ef195b)) - Improved `isWithin` to pretty-print numbers in its failure messages. ([`de78553`](https://redirect.github.com/google/truth/commit/de785536d), [`07318c2`](https://redirect.github.com/google/truth/commit/07318c23e)) - Improved some assertions that print class names to print simpler names (e.g., `Integer` instead of `java.lang.Integer`). ([`0ba72d6`](https://redirect.github.com/google/truth/commit/0ba72d60fdb384aa97da03e2403a6757f63bf129)) - Changed `ExpectFailure` to never generate "value of" lines based on bytecode. This slightly simplifies writing new tests with `ExpectFailure` and prevents future behavior changes in some `ExpectFailure` tests that already exist. However, it may also require changes to other existing `ExpectFailure` tests to remove or change any assertions about the "value of" line. ([`3caa0e8`](https://redirect.github.com/google/truth/commit/3caa0e845)) - Our Android `minSdkVersion` is now 23 (Marshmallow). This follows the minimum of Google's foundational Android libraries, and we expect it to have no practical impact on users. ([`c85c75c`](https://redirect.github.com/google/truth/commit/c85c75cf4)) - Changed our GWT/J2CL artifact to omit usages of `@NullMarked`. This was making all our types non-null in those environments, since we don't yet use `@Nullable` in the GWT/J2CL artifact. ([`6392d37`](https://redirect.github.com/google/truth/commit/6392d37e7))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8c762be73c4c..99584fe91a9a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -51,7 +51,7 @@ google-cloud-spanner-jdbc 4.13.2 3.0.2 - 1.4.4 + 1.4.5 4.11.0 0.31.1
    From b0c190c150a3839c55e9d78a9ae50b1536d0f04d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Sep 2025 17:38:43 +0200 Subject: [PATCH 1799/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.28 (#2203) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index db14e9cd0f76..4551311c104c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -124,7 +124,7 @@ com.spotify.fmt fmt-maven-plugin - 2.27 + 2.28 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 503fc542f3a4..97cda34257ea 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -129,7 +129,7 @@ com.spotify.fmt fmt-maven-plugin - 2.27 + 2.28 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index bd1605634f35..bdc890856db0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -116,7 +116,7 @@ com.spotify.fmt fmt-maven-plugin - 2.27 + 2.28 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 59abf916c1ab..3a3c30b22bc0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -113,7 +113,7 @@ com.spotify.fmt fmt-maven-plugin - 2.27 + 2.28 From 75a1329d8a291cb2754479f7267811bd0069530e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 13 Sep 2025 05:14:07 +0200 Subject: [PATCH 1800/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.100.0 (#2206) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index bdc890856db0..3d8808c476b3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.99.0 + 6.100.0 test-jar test From 979e37fa633da02d081a0e91e9c1e2a22e373bfe Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sat, 13 Sep 2025 05:14:51 +0200 Subject: [PATCH 1801/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.100.0 (#2207) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 99584fe91a9a..4f9959998e3c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.99.0 + 6.100.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 4551311c104c..28939aefefe4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.99.0 + 6.100.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 97cda34257ea..494c576ec98c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.99.0 + 6.100.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 3d8808c476b3..46bfcdad11ed 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.99.0 + 6.100.0 import pom From bae00c3a0fce2257d8558a35d313cc6a487331a3 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 03:36:22 +0000 Subject: [PATCH 1802/1979] chore(main): release 2.32.3 (#2200) :robot: I have created a release *beep* *boop* --- ## [2.32.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.32.2...v2.32.3) (2025-09-13) ### Dependencies * Update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.0 ([#2197](https://togithub.com/googleapis/java-spanner-jdbc/issues/2197)) ([10be366](https://togithub.com/googleapis/java-spanner-jdbc/commit/10be366613e3795ac91c1eb5a5d5986faa9e58c2)) * Update dependency com.google.cloud:google-cloud-spanner to v6.100.0 ([#2206](https://togithub.com/googleapis/java-spanner-jdbc/issues/2206)) ([75a1329](https://togithub.com/googleapis/java-spanner-jdbc/commit/75a1329d8a291cb2754479f7267811bd0069530e)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.100.0 ([#2207](https://togithub.com/googleapis/java-spanner-jdbc/issues/2207)) ([979e37f](https://togithub.com/googleapis/java-spanner-jdbc/commit/979e37fa633da02d081a0e91e9c1e2a22e373bfe)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.52.1 ([#2198](https://togithub.com/googleapis/java-spanner-jdbc/issues/2198)) ([c020cba](https://togithub.com/googleapis/java-spanner-jdbc/commit/c020cba5e056c12ae1589339d98ca5fa88c08a88)) * Update dependency com.spotify.fmt:fmt-maven-plugin to v2.28 ([#2203](https://togithub.com/googleapis/java-spanner-jdbc/issues/2203)) ([b0c190c](https://togithub.com/googleapis/java-spanner-jdbc/commit/b0c190c150a3839c55e9d78a9ae50b1536d0f04d)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.54.0 ([#2199](https://togithub.com/googleapis/java-spanner-jdbc/issues/2199)) ([1776a15](https://togithub.com/googleapis/java-spanner-jdbc/commit/1776a1518932ae475d6559dff428fb3325f297c4)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index e2da1c267aab..9077df99a0d5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.32.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.2...v2.32.3) (2025-09-13) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.0 ([#2197](https://github.com/googleapis/java-spanner-jdbc/issues/2197)) ([70726b6](https://github.com/googleapis/java-spanner-jdbc/commit/70726b66b71fe1801dff6d43c321f9917f4d3e10)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.100.0 ([#2206](https://github.com/googleapis/java-spanner-jdbc/issues/2206)) ([ce63133](https://github.com/googleapis/java-spanner-jdbc/commit/ce63133c3d90873703096d7ffe62814646982d98)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.100.0 ([#2207](https://github.com/googleapis/java-spanner-jdbc/issues/2207)) ([8f3f00b](https://github.com/googleapis/java-spanner-jdbc/commit/8f3f00bceca948e8337e795d6801c27128b810c5)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.1 ([#2198](https://github.com/googleapis/java-spanner-jdbc/issues/2198)) ([6f6f80b](https://github.com/googleapis/java-spanner-jdbc/commit/6f6f80b369a2a4af23aea6ec163122692f03fa8f)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.28 ([#2203](https://github.com/googleapis/java-spanner-jdbc/issues/2203)) ([23545de](https://github.com/googleapis/java-spanner-jdbc/commit/23545deb10bc718040f56063a09ae65f906a828f)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.54.0 ([#2199](https://github.com/googleapis/java-spanner-jdbc/issues/2199)) ([b5e02dd](https://github.com/googleapis/java-spanner-jdbc/commit/b5e02dd7dd2a520b4a91a10b72dba777c5c6990d)) + ## [2.32.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.1...v2.32.2) (2025-08-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index b36d3cece54d..4e95b5a01307 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.32.2 + 2.32.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4f9959998e3c..cde8f1989469 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.3-SNAPSHOT + 2.32.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index b844615c498f..981ae4f52e70 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.3-SNAPSHOT + 2.32.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e21aefaed00a..862e4e8ee3b3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.2:2.32.3-SNAPSHOT +google-cloud-spanner-jdbc:2.32.3:2.32.3 From a88a8941c16d72fa5bc4fe51cf0a5c0f985259de Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 06:26:00 +0200 Subject: [PATCH 1803/1979] chore(main): release 2.32.4-SNAPSHOT (#2208) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index cde8f1989469..692ae78f2153 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.3 + 2.32.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 981ae4f52e70..9fae37b494f3 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.3 + 2.32.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 862e4e8ee3b3..e32dec015dec 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.3:2.32.3 +google-cloud-spanner-jdbc:2.32.3:2.32.4-SNAPSHOT From f2c90f5cf2d1350cd9946519e7bd31f190eac633 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:04:13 +0200 Subject: [PATCH 1804/1979] deps: update dependency org.springframework.data:spring-data-bom to v2025.0.4 (#2204) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 28939aefefe4..4915be1fd03c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.3 + 2025.0.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 494c576ec98c..da591d089f98 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.3 + 2025.0.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 46bfcdad11ed..24bfdef95792 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.3 + 2025.0.4 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 3a3c30b22bc0..61818ab4a2a2 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.3 + 2025.0.4 import pom From 5a82a9027b243a854f4cc25c609cee38572db4e4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:06:25 +0200 Subject: [PATCH 1805/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.3 (#2210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.32.2` -> `2.32.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.32.3?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.32.3?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.32.2/2.32.3?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.32.2/2.32.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.32.3`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2323-2025-09-13) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.32.2...v2.32.3) ##### Dependencies - Update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.0 ([#​2197](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2197)) ([10be366](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/10be366613e3795ac91c1eb5a5d5986faa9e58c2)) - Update dependency com.google.cloud:google-cloud-spanner to v6.100.0 ([#​2206](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2206)) ([75a1329](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/75a1329d8a291cb2754479f7267811bd0069530e)) - Update dependency com.google.cloud:google-cloud-spanner-bom to v6.100.0 ([#​2207](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2207)) ([979e37f](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/979e37fa633da02d081a0e91e9c1e2a22e373bfe)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.52.1 ([#​2198](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2198)) ([c020cba](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/c020cba5e056c12ae1589339d98ca5fa88c08a88)) - Update dependency com.spotify.fmt:fmt-maven-plugin to v2.28 ([#​2203](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2203)) ([b0c190c](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/b0c190c150a3839c55e9d78a9ae50b1536d0f04d)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.54.0 ([#​2199](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2199)) ([1776a15](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/1776a1518932ae475d6559dff428fb3325f297c4))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index ddb461ec2266..06eab9662bb7 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.2 + 2.32.3 From 2309b90517053848577f7acedc058e006410c7d7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:08:27 +0200 Subject: [PATCH 1806/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.68.0 (#2212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.67.0` -> `26.68.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.68.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.68.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.67.0/26.68.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.67.0/26.68.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.68.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26680-2025-09-14) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.67.0...v26.68.0) ##### Dependencies - update actions/github-script action to v8 ([#​7192](https://redirect.github.com/googleapis/java-cloud-bom/issues/7192)) ([cc7a174](https://redirect.github.com/googleapis/java-cloud-bom/commit/cc7a174d57a08f439d534090f67addf095007fd5)) - update actions/setup-java action to v5 ([#​7173](https://redirect.github.com/googleapis/java-cloud-bom/issues/7173)) ([6401ecd](https://redirect.github.com/googleapis/java-cloud-bom/commit/6401ecdcb04eca826a4360abd289cc59aed9fb3c)) - update actions/setup-node action to v5 ([#​7193](https://redirect.github.com/googleapis/java-cloud-bom/issues/7193)) ([0439194](https://redirect.github.com/googleapis/java-cloud-bom/commit/0439194e018faed23e1d7e93fa03d0303a8d7a7d)) - update actions/setup-python action to v6 ([#​7194](https://redirect.github.com/googleapis/java-cloud-bom/issues/7194)) ([65a777a](https://redirect.github.com/googleapis/java-cloud-bom/commit/65a777aec77d7d3e2ed9dbb0bae67707d337c9a9)) - update dependency com.google.cloud:first-party-dependencies to v3.52.1 ([#​7185](https://redirect.github.com/googleapis/java-cloud-bom/issues/7185)) ([b63a143](https://redirect.github.com/googleapis/java-cloud-bom/commit/b63a143662cb70a2645a739f13527906c7c81e90)) - update dependency com.google.cloud:gapic-libraries-bom to v1.68.0 ([#​7197](https://redirect.github.com/googleapis/java-cloud-bom/issues/7197)) ([d57bbc4](https://redirect.github.com/googleapis/java-cloud-bom/commit/d57bbc443faf9f61ebbf2868eacf5c2d560b2a3f)) - update dependency com.google.cloud:google-cloud-bigquery to v2.55.0. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.17.0. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.66.0 ([#​7190](https://redirect.github.com/googleapis/java-cloud-bom/issues/7190)) ([a216187](https://redirect.github.com/googleapis/java-cloud-bom/commit/a216187f3ebd1b3c1b3b235789dc6cb1f6a5dc43)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.66.0 ([#​7190](https://redirect.github.com/googleapis/java-cloud-bom/issues/7190)) ([3d3a307](https://redirect.github.com/googleapis/java-cloud-bom/commit/3d3a307c34ddd2eb7e046a8cc0fda099488ce4ad)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.32.0 ([#​7198](https://redirect.github.com/googleapis/java-cloud-bom/issues/7198)) ([5adf761](https://redirect.github.com/googleapis/java-cloud-bom/commit/5adf7619f322f56a9f6ec16888abe5ca0f18400e)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.33.0. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.23.4 ([#​7186](https://redirect.github.com/googleapis/java-cloud-bom/issues/7186)) ([cf2c1c4](https://redirect.github.com/googleapis/java-cloud-bom/commit/cf2c1c4d381bae3dc7ef1861b4f2d81cbc8bf37a)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.132.15-alpha. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-nio to v0.128.4 ([#​7187](https://redirect.github.com/googleapis/java-cloud-bom/issues/7187)) ([434d296](https://redirect.github.com/googleapis/java-cloud-bom/commit/434d296fa1e7ce28df76e689c8b0671a95138086)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.141.4. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.15.15 ([#​7188](https://redirect.github.com/googleapis/java-cloud-bom/issues/7188)) ([a979a18](https://redirect.github.com/googleapis/java-cloud-bom/commit/a979a186918a5ae21505c1a95dc9551d1a39dcce)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.100.0. ([1333590](https://redirect.github.com/googleapis/java-cloud-bom/commit/1333590444970a42feba96a23ba15d60492b9420)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.32.3 ([#​7200](https://redirect.github.com/googleapis/java-cloud-bom/issues/7200)) ([b692048](https://redirect.github.com/googleapis/java-cloud-bom/commit/b69204861820c59427928f96e916077a9522d5cd)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.57.0 ([#​7191](https://redirect.github.com/googleapis/java-cloud-bom/issues/7191)) ([ac15f20](https://redirect.github.com/googleapis/java-cloud-bom/commit/ac15f20f9df505d7db71db0329b93c3423ee35c7))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index da1c8551e540..e44bc804b693 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index fd661e4bc144..5532a54c4999 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 4915be1fd03c..afbf4e03de7c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index da591d089f98..763b27a115f0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 24bfdef95792..c3b4c76b81eb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 61818ab4a2a2..0caa6632a8df 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.67.0 + 26.68.0 import pom From 1db8b4a0a499fe46ee2f3877fc39c29c0cd2b1ba Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:08:31 +0200 Subject: [PATCH 1807/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.1 (#2209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-shade-plugin](https://maven.apache.org/plugins/) ([source](https://redirect.github.com/apache/maven-shade-plugin)) | `3.6.0` -> `3.6.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    apache/maven-shade-plugin (org.apache.maven.plugins:maven-shade-plugin) ### [`v3.6.1`](https://redirect.github.com/apache/maven-shade-plugin/releases/tag/v3.6.1): 3.6.1 #### 📝 Documentation updates - [\[MNGSITE-529\]](https://issues.apache.org/jira/browse/MNGSITE-529) - Rename "Goals" to "Plugin Documentation" ([#​250](https://redirect.github.com/apache/maven-shade-plugin/pull/250)) [@​Bukama](https://redirect.github.com/Bukama) #### 👻 Maintenance - Enable prevent branch protection rules ([#​746](https://redirect.github.com/apache/maven-shade-plugin/pull/746)) [@​sparsick](https://redirect.github.com/sparsick) - Enable GH issues ([#​253](https://redirect.github.com/apache/maven-shade-plugin/pull/253)) [@​Bukama](https://redirect.github.com/Bukama) - Add missing [@​Override](https://redirect.github.com/Override) annotations ([#​246](https://redirect.github.com/apache/maven-shade-plugin/pull/246)) [@​elharo](https://redirect.github.com/elharo) - Merge `ApacheLicenseResourceTransformer` tests ([#​245](https://redirect.github.com/apache/maven-shade-plugin/pull/245)) [@​Goooler](https://redirect.github.com/Goooler) - Add test cases for .md supports in the Apache License and Notice transformers ([#​243](https://redirect.github.com/apache/maven-shade-plugin/pull/243)) [@​Goooler](https://redirect.github.com/Goooler) - [\[MSHADE-479\]](https://issues.apache.org/jira/browse/MSHADE-479) - Make the mojo much less noisy ([#​233](https://redirect.github.com/apache/maven-shade-plugin/pull/233)) [@​elharo](https://redirect.github.com/elharo) #### 📦 Dependency updates - Bump org.codehaus.mojo:mrm-maven-plugin from 1.6.0 to 1.7.0 ([#​748](https://redirect.github.com/apache/maven-shade-plugin/pull/748)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.hamcrest:hamcrest-core from 2.2 to 3.0 ([#​235](https://redirect.github.com/apache/maven-shade-plugin/pull/235)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.apache.maven.plugins:maven-plugins from 42 to 45 ([#​738](https://redirect.github.com/apache/maven-shade-plugin/pull/738)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.apache.commons:commons-compress from 1.26.2 to 1.28.0 ([#​743](https://redirect.github.com/apache/maven-shade-plugin/pull/743)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.xmlunit:xmlunit-legacy from 2.10.0 to 2.10.3 ([#​745](https://redirect.github.com/apache/maven-shade-plugin/pull/745)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump ASM 9.8 to support JDK 25 bytecode ([#​744](https://redirect.github.com/apache/maven-shade-plugin/pull/744)) [@​pan3793](https://redirect.github.com/pan3793) - Bump commons-io:commons-io from 2.13.0 to 2.14.0 in /src/it/projects/MSHADE-105/shaded-jar ([#​241](https://redirect.github.com/apache/maven-shade-plugin/pull/241)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 692ae78f2153..30319bc16401 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -279,7 +279,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.6.0 + 3.6.1 @@ -449,7 +449,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.6.0 + 3.6.1 From 5b403622de4fadbcc0aeb7125ccc227218988e68 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:10:22 +0200 Subject: [PATCH 1808/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.74.0 (#2211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.73.0` -> `2.74.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.73.0/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.73.0/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 30319bc16401..5bb96be94990 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.73.0 + 2.74.0 test From 8081bc6ffd0a6ec470d284195549a0df1a1a772f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:10:26 +0200 Subject: [PATCH 1809/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.74.0 (#2205) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.73.0` -> `2.74.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.73.0/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.73.0/2.74.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 5bb96be94990..fb43fd2f6234 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.73.0 + 2.74.0 test From 2b996c60c205c2cb6ee02690bdb80557b9873784 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 15 Sep 2025 10:12:27 +0200 Subject: [PATCH 1810/1979] build(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.1 (#2209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-shade-plugin](https://maven.apache.org/plugins/) ([source](https://redirect.github.com/apache/maven-shade-plugin)) | `3.6.0` -> `3.6.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.maven.plugins:maven-shade-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    apache/maven-shade-plugin (org.apache.maven.plugins:maven-shade-plugin) ### [`v3.6.1`](https://redirect.github.com/apache/maven-shade-plugin/releases/tag/v3.6.1): 3.6.1 #### 📝 Documentation updates - [\[MNGSITE-529\]](https://issues.apache.org/jira/browse/MNGSITE-529) - Rename "Goals" to "Plugin Documentation" ([#​250](https://redirect.github.com/apache/maven-shade-plugin/pull/250)) [@​Bukama](https://redirect.github.com/Bukama) #### 👻 Maintenance - Enable prevent branch protection rules ([#​746](https://redirect.github.com/apache/maven-shade-plugin/pull/746)) [@​sparsick](https://redirect.github.com/sparsick) - Enable GH issues ([#​253](https://redirect.github.com/apache/maven-shade-plugin/pull/253)) [@​Bukama](https://redirect.github.com/Bukama) - Add missing [@​Override](https://redirect.github.com/Override) annotations ([#​246](https://redirect.github.com/apache/maven-shade-plugin/pull/246)) [@​elharo](https://redirect.github.com/elharo) - Merge `ApacheLicenseResourceTransformer` tests ([#​245](https://redirect.github.com/apache/maven-shade-plugin/pull/245)) [@​Goooler](https://redirect.github.com/Goooler) - Add test cases for .md supports in the Apache License and Notice transformers ([#​243](https://redirect.github.com/apache/maven-shade-plugin/pull/243)) [@​Goooler](https://redirect.github.com/Goooler) - [\[MSHADE-479\]](https://issues.apache.org/jira/browse/MSHADE-479) - Make the mojo much less noisy ([#​233](https://redirect.github.com/apache/maven-shade-plugin/pull/233)) [@​elharo](https://redirect.github.com/elharo) #### 📦 Dependency updates - Bump org.codehaus.mojo:mrm-maven-plugin from 1.6.0 to 1.7.0 ([#​748](https://redirect.github.com/apache/maven-shade-plugin/pull/748)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.hamcrest:hamcrest-core from 2.2 to 3.0 ([#​235](https://redirect.github.com/apache/maven-shade-plugin/pull/235)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.apache.maven.plugins:maven-plugins from 42 to 45 ([#​738](https://redirect.github.com/apache/maven-shade-plugin/pull/738)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.apache.commons:commons-compress from 1.26.2 to 1.28.0 ([#​743](https://redirect.github.com/apache/maven-shade-plugin/pull/743)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.xmlunit:xmlunit-legacy from 2.10.0 to 2.10.3 ([#​745](https://redirect.github.com/apache/maven-shade-plugin/pull/745)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump ASM 9.8 to support JDK 25 bytecode ([#​744](https://redirect.github.com/apache/maven-shade-plugin/pull/744)) [@​pan3793](https://redirect.github.com/pan3793) - Bump commons-io:commons-io from 2.13.0 to 2.14.0 in /src/it/projects/MSHADE-105/shaded-jar ([#​241](https://redirect.github.com/apache/maven-shade-plugin/pull/241)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). From 423bf8872c43616673f362a2f179502a5bdb3061 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 17 Sep 2025 17:14:25 +0200 Subject: [PATCH 1811/1979] deps: update dependency com.spotify.fmt:fmt-maven-plugin to v2.29 (#2214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.spotify.fmt:fmt-maven-plugin](https://redirect.github.com/spotify/fmt-maven-plugin) | `2.28` -> `2.29` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.spotify.fmt:fmt-maven-plugin/2.29?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.29?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.28/2.29?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.28/2.29?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spotify/fmt-maven-plugin (com.spotify.fmt:fmt-maven-plugin) ### [`v2.29`](https://redirect.github.com/spotify/fmt-maven-plugin/compare/2.28.0...2.29.0) [Compare Source](https://redirect.github.com/spotify/fmt-maven-plugin/compare/2.28.0...2.29.0)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index afbf4e03de7c..fdcb6a549f30 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -124,7 +124,7 @@ com.spotify.fmt fmt-maven-plugin - 2.28 + 2.29 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 763b27a115f0..079036be4a60 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -129,7 +129,7 @@ com.spotify.fmt fmt-maven-plugin - 2.28 + 2.29 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index c3b4c76b81eb..0dc1842ae880 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -116,7 +116,7 @@ com.spotify.fmt fmt-maven-plugin - 2.28 + 2.29 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 0caa6632a8df..1e7c23616599 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -113,7 +113,7 @@ com.spotify.fmt fmt-maven-plugin - 2.28 + 2.29 From 4baca662c88874cf22cf84d648375f22c5a7af12 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:22:32 +0200 Subject: [PATCH 1812/1979] deps: update dependency org.apache.commons:commons-lang3 to v3.19.0 (#2225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.commons:commons-lang3](https://commons.apache.org/proper/commons-lang/) ([source](https://gitbox.apache.org/repos/asf/commons-lang.git)) | `3.18.0` -> `3.19.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.apache.commons:commons-lang3/3.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.apache.commons:commons-lang3/3.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.apache.commons:commons-lang3/3.18.0/3.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.apache.commons:commons-lang3/3.18.0/3.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index e44bc804b693..2b82c74b0dc5 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -62,7 +62,7 @@ org.apache.commons commons-lang3 - 3.18.0 + 3.19.0 com.fasterxml.jackson.core From e036d15f6927bd41988b5cbe2e0bbd4995002c14 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:22:36 +0200 Subject: [PATCH 1813/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.6 (#2217) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-data-jdbc](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `3.5.5` -> `3.5.6` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.5.5/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-data-jdbc/3.5.5/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-data-jdbc) ### [`v3.5.6`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index fdcb6a549f30..e02ccddabdfc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.5 + 3.5.6 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 079036be4a60..008546b0769c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.5 + 3.5.6 From 4fe193f3d8ce76e7f49d0de464d3d72f6efbe58f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:22:40 +0200 Subject: [PATCH 1814/1979] deps: update dependency org.postgresql:postgresql to v42.7.8 (#2221) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.postgresql:postgresql](https://jdbc.postgresql.org) ([source](https://redirect.github.com/pgjdbc/pgjdbc)) | `42.7.7` -> `42.7.8` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.postgresql:postgresql/42.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.postgresql:postgresql/42.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.postgresql:postgresql/42.7.7/42.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.postgresql:postgresql/42.7.7/42.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    pgjdbc/pgjdbc (org.postgresql:postgresql) ### [`v42.7.8`](https://redirect.github.com/pgjdbc/pgjdbc/blob/HEAD/CHANGELOG.md#4278-2025-09-18) ##### Added - feat: Add configurable boolean-to-numeric conversion for ResultSet getters [PR #​3796](https://redirect.github.com/pgjdbc/pgjdbc/pull/3796) ##### Changed - perf: remove QUERY\_ONESHOT flag when calling getMetaData [PR #​3783](https://redirect.github.com/pgjdbc/pgjdbc/pull/3783) - perf: use `BufferedInputStream` with `FileInputStream` [PR #​3750](https://redirect.github.com/pgjdbc/pgjdbc/pull/3750) - perf: enable server-prepared statements for DatabaseMetaData ##### Fixed - fix: avoid NullPointerException when cancelling a query if cancel key is not known yet - fix: Change "PST" timezone in TimestampTest to "Pacific Standard Time" [PR #​3774](https://redirect.github.com/pgjdbc/pgjdbc/pull/3774) - fix: traverse the current dimension to get the correct pos in PgArray#calcRemainingDataLength [PR #​3746](https://redirect.github.com/pgjdbc/pgjdbc/pull/3746) - fix: make sure getImportedExportedKeys returns columns in consistent order - fix: Add "SELF\_REFERENCING\_COL\_NAME" field to getTables' ResultSetMetaData to fix NullPointerException [PR #​3660](https://redirect.github.com/pgjdbc/pgjdbc/pull/3660) - fix: unable to open replication connection to servers < 12 - fix: avoid closing statement caused by driver's internal ResultSet#close() - fix: return empty metadata for empty catalog names as it was before - fix: Incorrect class comparison in PGXmlFactoryFactory validation
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 008546b0769c..246c280a9dd9 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -72,7 +72,7 @@ org.postgresql postgresql - 42.7.7 + 42.7.8 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 1e7c23616599..8e03093fce42 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.7 + 42.7.8 org.testcontainers From f756a797c89b6ed818624032dbe5a38b0723b3c7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:24:33 +0200 Subject: [PATCH 1815/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.6 (#2216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `3.5.5` -> `3.5.6` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/3.5.5/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/3.5.5/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v3.5.6`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2b82c74b0dc5..fc146288326c 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.5 + 3.5.6 test From 5b4cc7120fbc4f98aa98f603167ab1fd0796adfc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:24:37 +0200 Subject: [PATCH 1816/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.54.1 (#2220) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://redirect.github.com/open-telemetry/opentelemetry-java) | `1.54.0` -> `1.54.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.54.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.54.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.54.0/1.54.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.54.0/1.54.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.54.1`](https://redirect.github.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1541-2025-09-18) [Compare Source](https://redirect.github.com/open-telemetry/opentelemetry-java/compare/v1.54.0...v1.54.1) ##### SDK ##### Exporters - Prometheus: Fix regression in protobuf format export ([#​7664](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7664))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index e02ccddabdfc..31db916baa50 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.54.0 + 1.54.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 246c280a9dd9..aa78ad2eb776 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.54.0 + 1.54.1 pom import From fd9c348aa3f1a93fc0c7138d993be30fcc614c33 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:26:33 +0200 Subject: [PATCH 1817/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.75.0 (#2223) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.74.0` -> `2.75.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.74.0/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.74.0/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fb43fd2f6234..07e034ab1d05 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.74.0 + 2.75.0 test From c5ec47e7c0856048a3d63422a36c1f2da8fecc63 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:28:28 +0200 Subject: [PATCH 1818/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.75.0 (#2224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.74.0` -> `2.75.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.74.0/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.74.0/2.75.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 07e034ab1d05..64023e28c9eb 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.74.0 + 2.75.0 test From 80097a72cdda9bf8e6b3442a1d54cedace86d851 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:32:11 +0200 Subject: [PATCH 1819/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.52.2 (#2218) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 5b7dd21a160f..7394b52affbd 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.2 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index f69120cbb2a0..631631deb091 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 7f7797ccf2f6..16cf471b0ba3 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 0ed7b4e65b0b..5d26971228c8 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.2" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 64023e28c9eb..0fa1a289fa74 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.52.1 + 3.52.2 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index fc146288326c..1a79d88258fc 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.52.1 + 3.52.2 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5532a54c4999..e82086db7c8c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.52.1 + 3.52.2 From e46bdfc2cf5b8fe3e7f04f42b3ec0c60e258067f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 26 Sep 2025 09:56:28 +0200 Subject: [PATCH 1820/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.6 (#2219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/spring-projects/spring-boot)) | `3.5.5` -> `3.5.6` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.5.6?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.5.6?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.5.5/3.5.6?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.5.5/3.5.6?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.5.6`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 0dc1842ae880..b4aa07c1d26c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.5 + 3.5.6 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 8e03093fce42..5f2b06f5510a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.5 + 3.5.6 From 8a2a0922410747f1630ee8e8d9541e6e42b8635a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 27 Sep 2025 05:06:24 +0200 Subject: [PATCH 1821/1979] feat: add transaction_timeout connection property (#2226) Adds a transaction_timeout connection property. This property can be set either in the JDBC connection URL or by executing a statement like `SET transaction_timeout = '5s';` The transaction timeout is the total time that a read/write transaction may take from start to end. If the transaction is not able to finish within the given timeout, then it will fail with a DEADLINE_EXCEEDED error. --- java-spanner-jdbc/documentation/connection_properties.md | 3 +++ java-spanner-jdbc/pom.xml | 2 +- .../cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index 4110bcfe7cc4..c0cd13861cf2 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -45,6 +45,7 @@ The 'Context' value indicates whether the property can only be set when a connec | oauthtoken | A valid pre-existing OAuth token to use for authentication for this connection. Setting this property will take precedence over any value set for a credentials file. | | | STARTUP | | optimizerstatisticspackage | Sets the query optimizer statistics package to use for this connection. | | | USER | | optimizerversion | Sets the default query optimizer version to use for this connection. | | | USER | +| read_lock_mode | This option controls the locking behavior for read operations and queries within a read/write transaction. It works in conjunction with the transaction's isolation level. PESSIMISTIC: Read locks are acquired immediately on read. This mode only applies to SERIALIZABLE isolation. This mode prevents concurrent modifications by locking data throughout the transaction. This reduces commit-time aborts due to conflicts, but can increase how long transactions wait for locks and the overall contention. OPTIMISTIC: Locks for reads within the transaction are not acquired on read. Instead, the locks are acquired on commit to validate that read/queried data has not changed since the transaction started. If a conflict is detected, the transaction will fail. This mode only applies to SERIALIZABLE isolation. This mode defers locking until commit, which can reduce contention and improve throughput. However, be aware that this increases the risk of transaction aborts if there's significant write competition on the same data. READ_LOCK_MODE_UNSPECIFIED: This is the default if no mode is set. The locking behavior depends on the isolation level: REPEATABLE_READ: Locking semantics default to OPTIMISTIC. However, validation checks at commit are only performed for queries using SELECT FOR UPDATE, statements with {@code LOCK_SCANNED_RANGES} hints, and DML statements. For all other isolation levels: If the read lock mode is not set, it defaults to PESSIMISTIC locking. | READ_LOCK_MODE_UNSPECIFIED | READ_LOCK_MODE_UNSPECIFIED, PESSIMISTIC, OPTIMISTIC | USER | | read_only_staleness | The read-only staleness to use for read-only transactions and single-use queries. | strong | | USER | | readonly | Should the connection start in read-only mode (true/false) | false | true, false | USER | | retryabortsinternally | Should the connection automatically retry Aborted errors (true/false) | true | true, false | USER | @@ -55,6 +56,8 @@ The 'Context' value indicates whether the property can only be set when a connec | tracing_prefix | The prefix that will be prepended to all OpenTelemetry traces that are generated by a Connection. | CloudSpanner | | STARTUP | | trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | true, false | STARTUP | | tracksessionleaks | Capture the call stack of the thread that checked out a session of the session pool. This will pre-create a LeakedSessionException already when a session is checked out. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedSessionException will only be created when an actual session leak is detected. The stack trace of the exception will in that case not contain the call stack of when the session was checked out. | true | true, false | STARTUP | +| transaction_timeout | Timeout for read/write transactions. | | | USER | +| universedomain | Configure the connection to try to connect to Spanner using a different partner Google Universe than GDU (googleapis.com). | googleapis.com | | STARTUP | | useautosavepointsforemulator | Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. This is no longer needed when using Emulator version 1.5.23 or higher. | false | true, false | STARTUP | | useplaintext | Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator. | false | true, false | STARTUP | | useragent | The custom user-agent property name to use when communicating with Cloud Spanner. This property is intended for internal library usage, and should not be set by applications. | | | STARTUP | diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0fa1a289fa74..dc5c4a93ac4d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.100.0 + 6.101.1 pom import diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java index 9efc63b9ed4e..052e4dce4c46 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java @@ -45,7 +45,7 @@ public static void main(String[] args) throws IOException { .append("| ") .append(connectionProperty.getName()) .append(" | ") - .append(connectionProperty.getDescription()) + .append(connectionProperty.getDescription().replace("\n", " ")) .append(" | ") .append( connectionProperty.getDefaultValue() == null From 115c69cd61d7dca47a05ee9062089db42787242a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 07:03:40 +0200 Subject: [PATCH 1822/1979] chore(main): release 2.33.0 (#2213) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 24 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 9077df99a0d5..38f6d8d3f07b 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [2.33.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.3...v2.33.0) (2025-09-27) + + +### Features + +* Add transaction_timeout connection property ([#2226](https://github.com/googleapis/java-spanner-jdbc/issues/2226)) ([092df54](https://github.com/googleapis/java-spanner-jdbc/commit/092df54f1bd823ce721c29732a51f8ef5065a6f2)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.74.0 ([#2205](https://github.com/googleapis/java-spanner-jdbc/issues/2205)) ([84dd68c](https://github.com/googleapis/java-spanner-jdbc/commit/84dd68cd661623132c007ac1bed9e69950aa3cac)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.75.0 ([#2223](https://github.com/googleapis/java-spanner-jdbc/issues/2223)) ([4aaa4a1](https://github.com/googleapis/java-spanner-jdbc/commit/4aaa4a132473935746d91363cf4e8b80e08bd017)) +* Update dependency com.google.cloud:google-cloud-trace to v2.74.0 ([#2211](https://github.com/googleapis/java-spanner-jdbc/issues/2211)) ([ac95834](https://github.com/googleapis/java-spanner-jdbc/commit/ac958346f19faad5eaf8dd53ce88b995261e9897)) +* Update dependency com.google.cloud:google-cloud-trace to v2.75.0 ([#2224](https://github.com/googleapis/java-spanner-jdbc/issues/2224)) ([99392d4](https://github.com/googleapis/java-spanner-jdbc/commit/99392d4aa010331815759c45b34372f6766ec9c8)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.2 ([#2218](https://github.com/googleapis/java-spanner-jdbc/issues/2218)) ([5718b16](https://github.com/googleapis/java-spanner-jdbc/commit/5718b161ce326fac7e85fed0bda960e00f035cde)) +* Update dependency com.spotify.fmt:fmt-maven-plugin to v2.29 ([#2214](https://github.com/googleapis/java-spanner-jdbc/issues/2214)) ([a73a772](https://github.com/googleapis/java-spanner-jdbc/commit/a73a77245f4827afb8580912d437543b5cc59317)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.54.1 ([#2220](https://github.com/googleapis/java-spanner-jdbc/issues/2220)) ([b386483](https://github.com/googleapis/java-spanner-jdbc/commit/b38648370a09631d5f6514aad2960dd3c76af99c)) +* Update dependency org.apache.commons:commons-lang3 to v3.19.0 ([#2225](https://github.com/googleapis/java-spanner-jdbc/issues/2225)) ([1ea3eca](https://github.com/googleapis/java-spanner-jdbc/commit/1ea3eca4c7711775d5d1b89534e490a989ad4630)) +* Update dependency org.postgresql:postgresql to v42.7.8 ([#2221](https://github.com/googleapis/java-spanner-jdbc/issues/2221)) ([bcc3f3d](https://github.com/googleapis/java-spanner-jdbc/commit/bcc3f3d59c02d2d7ff70e6a65a86f0750587c52e)) +* Update dependency org.springframework.boot:spring-boot to v3.5.6 ([#2216](https://github.com/googleapis/java-spanner-jdbc/issues/2216)) ([84396e0](https://github.com/googleapis/java-spanner-jdbc/commit/84396e042d3ac2d7da35bb7900f25f59d36f83d9)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.6 ([#2217](https://github.com/googleapis/java-spanner-jdbc/issues/2217)) ([1805daa](https://github.com/googleapis/java-spanner-jdbc/commit/1805daa587fe5f589213b0ef23fe773137446f9a)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.6 ([#2219](https://github.com/googleapis/java-spanner-jdbc/issues/2219)) ([63525af](https://github.com/googleapis/java-spanner-jdbc/commit/63525af099a80b0ae89bd3336244a3aa4e8b71e0)) +* Update dependency org.springframework.data:spring-data-bom to v2025.0.4 ([#2204](https://github.com/googleapis/java-spanner-jdbc/issues/2204)) ([f6327c7](https://github.com/googleapis/java-spanner-jdbc/commit/f6327c79ce4d3dd30994b0c2419ae5b6b058d156)) + ## [2.32.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.2...v2.32.3) (2025-09-13) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 4e95b5a01307..61b3d5cb2ba5 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.32.3 + 2.33.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.32.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.32.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dc5c4a93ac4d..b457a23565b3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.32.4-SNAPSHOT + 2.33.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9fae37b494f3..59afa6f0d0ca 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.4-SNAPSHOT + 2.33.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e32dec015dec..4edb3f7a6cbc 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.32.3:2.32.4-SNAPSHOT +google-cloud-spanner-jdbc:2.33.0:2.33.0 From 400408f59ccdd076eac7f1d2a1d376ec20ce2c5d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 05:30:26 +0000 Subject: [PATCH 1823/1979] chore(main): release 2.33.1-SNAPSHOT (#2229) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b457a23565b3..17518a75088c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.0 + 2.33.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 59afa6f0d0ca..e23e32c1aed1 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.0 + 2.33.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 4edb3f7a6cbc..53ba1a2db99e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.0:2.33.0 +google-cloud-spanner-jdbc:2.33.0:2.33.1-SNAPSHOT From 7d080314f620f5abe5698588e5f6293e5c03c14b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 28 Sep 2025 07:20:24 +0100 Subject: [PATCH 1824/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.0 (#2230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.32.3` -> `2.33.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.33.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.33.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.32.3/2.33.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.32.3/2.33.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.33.0`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2330-2025-09-27) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.32.3...v2.33.0) ##### Features - Add transaction\_timeout connection property ([#​2226](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2226)) ([8a2a092](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/8a2a0922410747f1630ee8e8d9541e6e42b8635a)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.74.0 ([#​2205](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2205)) ([8081bc6](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/8081bc6ffd0a6ec470d284195549a0df1a1a772f)) - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.75.0 ([#​2223](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2223)) ([fd9c348](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/fd9c348aa3f1a93fc0c7138d993be30fcc614c33)) - Update dependency com.google.cloud:google-cloud-trace to v2.74.0 ([#​2211](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2211)) ([5b40362](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/5b403622de4fadbcc0aeb7125ccc227218988e68)) - Update dependency com.google.cloud:google-cloud-trace to v2.75.0 ([#​2224](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2224)) ([c5ec47e](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/c5ec47e7c0856048a3d63422a36c1f2da8fecc63)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.52.2 ([#​2218](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2218)) ([80097a7](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/80097a72cdda9bf8e6b3442a1d54cedace86d851)) - Update dependency com.spotify.fmt:fmt-maven-plugin to v2.29 ([#​2214](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2214)) ([423bf88](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/423bf8872c43616673f362a2f179502a5bdb3061)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.54.1 ([#​2220](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2220)) ([5b4cc71](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/5b4cc7120fbc4f98aa98f603167ab1fd0796adfc)) - Update dependency org.apache.commons:commons-lang3 to v3.19.0 ([#​2225](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2225)) ([4baca66](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/4baca662c88874cf22cf84d648375f22c5a7af12)) - Update dependency org.postgresql:postgresql to v42.7.8 ([#​2221](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2221)) ([4fe193f](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/4fe193f3d8ce76e7f49d0de464d3d72f6efbe58f)) - Update dependency org.springframework.boot:spring-boot to v3.5.6 ([#​2216](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2216)) ([f756a79](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/f756a797c89b6ed818624032dbe5a38b0723b3c7)) - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.6 ([#​2217](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2217)) ([e036d15](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/e036d15f6927bd41988b5cbe2e0bbd4995002c14)) - Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.6 ([#​2219](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2219)) ([e46bdfc](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/e46bdfc2cf5b8fe3e7f04f42b3ec0c60e258067f)) - Update dependency org.springframework.data:spring-data-bom to v2025.0.4 ([#​2204](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2204)) ([f2c90f5](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/f2c90f5cf2d1350cd9946519e7bd31f190eac633))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 06eab9662bb7..041fab8ac1c1 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.32.3 + 2.33.0 From c411dde91ab89bd3b55a558fa0272525d331ec34 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 29 Sep 2025 07:16:51 +0100 Subject: [PATCH 1825/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.101.1 (#2228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.101.1 * chore: add bytebuddy for test workaround --------- Co-authored-by: Knut Olav Løite --- .../samples/spring-data-jdbc/googlesql/pom.xml | 2 +- .../samples/spring-data-jdbc/postgresql/pom.xml | 15 ++++++++++++++- .../samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 31db916baa50..a1c00cc200a3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.100.0 + 6.101.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index aa78ad2eb776..6771b551dec3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.100.0 + 6.101.1 import pom @@ -110,6 +110,19 @@ testlib test
    + + + net.bytebuddy + byte-buddy + 1.17.7 + test + + + net.bytebuddy + byte-buddy-agent + 1.17.7 + test + junit junit diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index b4aa07c1d26c..72002687db4a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.100.0 + 6.101.1 import pom From 8504b0d1d8e110a171e8b2dd20b7e2d66c389018 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 29 Sep 2025 07:18:28 +0100 Subject: [PATCH 1826/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.101.1 (#2227) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner](https://redirect.github.com/googleapis/java-spanner) | `6.100.0` -> `6.101.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner/6.101.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/6.101.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/6.100.0/6.101.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/6.100.0/6.101.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner) ### [`v6.101.1`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61011-2025-09-26) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.101.0...v6.101.1) ##### Bug Fixes - Potential NullPointerException in LocalConnectionChecker ([#​4092](https://redirect.github.com/googleapis/java-spanner/issues/4092)) ([3b9f597](https://redirect.github.com/googleapis/java-spanner/commit/3b9f597ba60199a16556824568b24908ce938a69)) ### [`v6.101.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61010-2025-09-26) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.100.0...v6.101.0) ##### Features - Add transaction\_timeout connection property ([#​4056](https://redirect.github.com/googleapis/java-spanner/issues/4056)) ([cdc52d4](https://redirect.github.com/googleapis/java-spanner/commit/cdc52d49b39c57e7255f4e09fb33a41f4810397d)) - TPC support ([#​4055](https://redirect.github.com/googleapis/java-spanner/issues/4055)) ([7625cce](https://redirect.github.com/googleapis/java-spanner/commit/7625cce9ad48b14a1cff9c2ede86a066ea292bef)) ##### Bug Fixes - **deps:** Update the Java code generator (gapic-generator-java) to 2.62.2 ([8d6cbf6](https://redirect.github.com/googleapis/java-spanner/commit/8d6cbf6bea9cbd823b8f0070516e34b4d8428e87)) - Potential NullPointerException in Value#hashCode ([#​4046](https://redirect.github.com/googleapis/java-spanner/issues/4046)) ([74abb34](https://redirect.github.com/googleapis/java-spanner/commit/74abb341e2ea42bbf0a2de4ec3e3555335b5fd9f)) - Recalculate remaining statement timeout after retry ([#​4053](https://redirect.github.com/googleapis/java-spanner/issues/4053)) ([5e26596](https://redirect.github.com/googleapis/java-spanner/commit/5e26596f4f9c924260da0908920854d8ddfc626b)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.52.2 ([#​4057](https://redirect.github.com/googleapis/java-spanner/issues/4057)) ([d782aff](https://redirect.github.com/googleapis/java-spanner/commit/d782aff63ff81e1b760690d4dee3e566028d522e))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 72002687db4a..e14577e30177 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.100.0 + 6.101.1 test-jar test From a4a85f69b397c7557378ca9d4b57a98caa998b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 29 Sep 2025 08:42:28 +0200 Subject: [PATCH 1827/1979] chore: add ByteBuddy for tests for MyBatis sample (#2232) Adds the ByteBuddy dependency that is needed for some test workarounds for mTLS. --- .../samples/spring-data-mybatis/googlesql/pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index e14577e30177..d55124ddc7c1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -104,6 +104,19 @@ testlib test
    + + + net.bytebuddy + byte-buddy + 1.17.7 + test + + + net.bytebuddy + byte-buddy-agent + 1.17.7 + test + junit junit From 96738200c3cc459ed257bc9f24040802091a7fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 1 Oct 2025 17:28:53 +0200 Subject: [PATCH 1828/1979] test: add bytebuddy for mybatis pg tests (#2235) --- .../samples/spring-data-mybatis/postgresql/pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 5f2b06f5510a..be4efa846a0e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -101,6 +101,19 @@ testlib test + + + net.bytebuddy + byte-buddy + 1.17.7 + test + + + net.bytebuddy + byte-buddy-agent + 1.17.7 + test + junit junit From 9eb42bcfc56c4708c6ccd2779ff8f1bc4b05fee3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Oct 2025 16:40:28 +0100 Subject: [PATCH 1829/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.6.0 (#2234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.codehaus.mojo:exec-maven-plugin](https://www.mojohaus.org/exec-maven-plugin) ([source](https://redirect.github.com/mojohaus/exec-maven-plugin)) | `3.5.1` -> `3.6.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.codehaus.mojo:exec-maven-plugin/3.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.codehaus.mojo:exec-maven-plugin/3.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.codehaus.mojo:exec-maven-plugin/3.5.1/3.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.codehaus.mojo:exec-maven-plugin/3.5.1/3.6.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mojohaus/exec-maven-plugin (org.codehaus.mojo:exec-maven-plugin) ### [`v3.6.0`](https://redirect.github.com/mojohaus/exec-maven-plugin/releases/tag/3.6.0) [Compare Source](https://redirect.github.com/mojohaus/exec-maven-plugin/compare/3.5.1...3.6.0) #### 🚀 New features and improvements - \[ExecMojo]Add `getShebang` method to correctly set the command line executable name ([#​487](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/487)) [@​uchenily](https://redirect.github.com/uchenily) - JEP 512 Support ([#​484](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/484)) [@​cayhorstmann](https://redirect.github.com/cayhorstmann) #### 🐛 Bug Fixes - fix inheritIo option ([#​488](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/488)) [@​dernasherbrezon](https://redirect.github.com/dernasherbrezon) - Fix for [#​479](https://redirect.github.com/mojohaus/exec-maven-plugin/issues/479) - Wrong repositories used to collect deps ([#​480](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/480)) [@​cstamas](https://redirect.github.com/cstamas) #### 👻 Maintenance - Use JSR-330 for component injection ([#​493](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/493)) [@​slawekjaranowski](https://redirect.github.com/slawekjaranowski) - Re-run failed tests ([#​491](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/491)) [@​slawekjaranowski](https://redirect.github.com/slawekjaranowski) - Restore default matrix build ([#​486](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/486)) [@​slawekjaranowski](https://redirect.github.com/slawekjaranowski) #### 📦 Dependency updates - Use Maven 3.9.11 in dependencies, still requires 3.6.3 as minimum ([#​492](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/492)) [@​slawekjaranowski](https://redirect.github.com/slawekjaranowski) - Bump org.codehaus.mojo:mojo-parent from 92 to 93 ([#​483](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/483)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.codehaus.mojo:mojo-parent from 91 to 92 ([#​478](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/478)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.codehaus.mojo:mojo-parent from 90 to 91 ([#​477](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/477)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot) - Bump org.codehaus.mojo:mojo-parent from 89 to 90 ([#​476](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/476)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 1a79d88258fc..616f21a4ec03 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.5.1 + 3.6.0 com.google.cloud.jdbc.quickperf.QuickPerf From eac6a26870f1583f8535cc9dc2aa5007cab5f30c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 1 Oct 2025 17:40:29 +0100 Subject: [PATCH 1830/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.69.0 (#2233) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.68.0` -> `26.69.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.69.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.69.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.68.0/26.69.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.68.0/26.69.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.69.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26690-2025-09-29) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.68.0...v26.69.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.52.2 ([#​7203](https://redirect.github.com/googleapis/java-cloud-bom/issues/7203)) ([69d0348](https://redirect.github.com/googleapis/java-cloud-bom/commit/69d0348b464ad29da8a674eed6f864bb6094a404)) - update dependency com.google.cloud:gapic-libraries-bom to v1.69.0 ([#​7206](https://redirect.github.com/googleapis/java-cloud-bom/issues/7206)) ([9c8625b](https://redirect.github.com/googleapis/java-cloud-bom/commit/9c8625b0510b85a242be08976b2a572b3745a0be)) - update dependency com.google.cloud:google-cloud-bigquery to v2.55.1 ([#​7215](https://redirect.github.com/googleapis/java-cloud-bom/issues/7215)) ([4fac3db](https://redirect.github.com/googleapis/java-cloud-bom/commit/4fac3db38d5630a0916347b2d27432e20e139637)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.17.1 ([#​7211](https://redirect.github.com/googleapis/java-cloud-bom/issues/7211)) ([b544459](https://redirect.github.com/googleapis/java-cloud-bom/commit/b544459063342c9cb11c3ec52be065d93741f2cf)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.67.0 ([#​7210](https://redirect.github.com/googleapis/java-cloud-bom/issues/7210)) ([bdbf6d0](https://redirect.github.com/googleapis/java-cloud-bom/commit/bdbf6d0e6f69f3018a4a63a5f29e9d0d1b990b08)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.32.1 ([#​7218](https://redirect.github.com/googleapis/java-cloud-bom/issues/7218)) ([1e9b8c7](https://redirect.github.com/googleapis/java-cloud-bom/commit/1e9b8c774809659b8223b9d9f45b5b66d833ced3)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.33.1 ([#​7208](https://redirect.github.com/googleapis/java-cloud-bom/issues/7208)) ([78cd5bc](https://redirect.github.com/googleapis/java-cloud-bom/commit/78cd5bcf49af7bd2ab9f138806e62efbb4f4f8b8)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.23.5 ([#​7209](https://redirect.github.com/googleapis/java-cloud-bom/issues/7209)) ([ee2a334](https://redirect.github.com/googleapis/java-cloud-bom/commit/ee2a334e273abd2eeb3918f153438f59e641abb4)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.132.16-alpha ([#​7212](https://redirect.github.com/googleapis/java-cloud-bom/issues/7212)) ([bce4761](https://redirect.github.com/googleapis/java-cloud-bom/commit/bce476175272b5e8d6e518387f3bc87cee8be38b)) - update dependency com.google.cloud:google-cloud-nio to v0.128.5 ([#​7204](https://redirect.github.com/googleapis/java-cloud-bom/issues/7204)) ([38ec3ff](https://redirect.github.com/googleapis/java-cloud-bom/commit/38ec3ff81ee4cb633db0e15b2bfc83edbb43548f)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.141.5 ([#​7207](https://redirect.github.com/googleapis/java-cloud-bom/issues/7207)) ([e104b9c](https://redirect.github.com/googleapis/java-cloud-bom/commit/e104b9cc991c99a442cc2eeec23dfed1ada68238)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.15.16 ([#​7214](https://redirect.github.com/googleapis/java-cloud-bom/issues/7214)) ([a59bacc](https://redirect.github.com/googleapis/java-cloud-bom/commit/a59bacc8efaca290d161139fbc2576e2a7eb3d4e)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.101.1 ([#​7216](https://redirect.github.com/googleapis/java-cloud-bom/issues/7216)) ([a516b51](https://redirect.github.com/googleapis/java-cloud-bom/commit/a516b51ed648950fb42c50f7014662432b4696de)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.0 ([#​7217](https://redirect.github.com/googleapis/java-cloud-bom/issues/7217)) ([e3debca](https://redirect.github.com/googleapis/java-cloud-bom/commit/e3debca6846a209842cd691530f2558984c5358d)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.58.0 ([#​7205](https://redirect.github.com/googleapis/java-cloud-bom/issues/7205)) ([98443be](https://redirect.github.com/googleapis/java-cloud-bom/commit/98443be61de9ffc94d8567255c9685dd60e1be46))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 616f21a4ec03..6a5185fda00f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e82086db7c8c..499dac6f907a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a1c00cc200a3..4cdb94895b2d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 6771b551dec3..2e0d47db4d38 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d55124ddc7c1..0d1ff90f6a1d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index be4efa846a0e..b821d947e2b1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.68.0 + 26.69.0 import pom From c5b796eca052de6607121d042d06d2308f8ea640 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 7 Oct 2025 05:33:35 +0100 Subject: [PATCH 1831/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.52.3 (#2236) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 7394b52affbd..2cf303dc3847 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.2 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.3 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 631631deb091..85695810d8a1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.3" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 16cf471b0ba3..c2efdcebf531 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.3" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 5d26971228c8..20946e7b08ae 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.3" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 17518a75088c..932e92a0dd73 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.52.2 + 3.52.3 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6a5185fda00f..9a2e83c31a32 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.52.2 + 3.52.3 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 499dac6f907a..07c7ab457aeb 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.52.2 + 3.52.3 From 28363febb80772a0c91e099d4efd2bb5f5c23a70 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 7 Oct 2025 05:36:28 +0100 Subject: [PATCH 1832/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.6.1 (#2237) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.codehaus.mojo:exec-maven-plugin](https://www.mojohaus.org/exec-maven-plugin) ([source](https://redirect.github.com/mojohaus/exec-maven-plugin)) | `3.6.0` -> `3.6.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.codehaus.mojo:exec-maven-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.codehaus.mojo:exec-maven-plugin/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.codehaus.mojo:exec-maven-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.codehaus.mojo:exec-maven-plugin/3.6.0/3.6.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    mojohaus/exec-maven-plugin (org.codehaus.mojo:exec-maven-plugin) ### [`v3.6.1`](https://redirect.github.com/mojohaus/exec-maven-plugin/releases/tag/3.6.1) [Compare Source](https://redirect.github.com/mojohaus/exec-maven-plugin/compare/3.6.0...3.6.1) ##### 🐛 Bug Fixes - Revert change from [#​480](https://redirect.github.com/mojohaus/exec-maven-plugin/issues/480) - plugin dependencies must be resolved from plugin repositories ([#​496](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/496)) [@​slawekjaranowski](https://redirect.github.com/slawekjaranowski) ##### 📦 Dependency updates - Bump org.codehaus.mojo:mojo-parent from 93 to 94 ([#​495](https://redirect.github.com/mojohaus/exec-maven-plugin/pull/495)) @​[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 9a2e83c31a32..ca7335c4fb33 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.6.0 + 3.6.1 com.google.cloud.jdbc.quickperf.QuickPerf From a0788ad299d0c6e02a0fecdca36c7e3c4741acd5 Mon Sep 17 00:00:00 2001 From: Mridula <66699525+mpeddada1@users.noreply.github.com> Date: Tue, 7 Oct 2025 01:47:46 -0400 Subject: [PATCH 1833/1979] chore: add JDK 25 to the CI build (#2239) --- java-spanner-jdbc/.github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/.github/workflows/ci.yaml b/java-spanner-jdbc/.github/workflows/ci.yaml index 4dd9974f263f..b9b8be0c36db 100644 --- a/java-spanner-jdbc/.github/workflows/ci.yaml +++ b/java-spanner-jdbc/.github/workflows/ci.yaml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - java: [11, 17, 21] + java: [11, 17, 21, 25] steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 From c08c01c28841cca50ee4db5031f69fbe274f64aa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Oct 2025 15:38:12 +0100 Subject: [PATCH 1834/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.76.0 (#2241) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 932e92a0dd73..0f5f21c77598 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.75.0 + 2.76.0 test From 74309b362b4571cbbace8c6fa2939c84a5ae6006 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 8 Oct 2025 15:42:27 +0100 Subject: [PATCH 1835/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.76.0 (#2240) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.75.0` -> `2.76.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.76.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.76.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.75.0/2.76.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.75.0/2.76.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0f5f21c77598..8bec03edf7b5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.75.0 + 2.76.0 test From a45eec0185450ef724b238dd572a29a194012e8f Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Wed, 8 Oct 2025 14:35:33 -0400 Subject: [PATCH 1836/1979] chore: use credential-specific fromStream method (#2242) --- .../google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java | 6 +++--- .../com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 7dc4667e4857..d5a429078ac6 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.connection.ConnectionOptionsTest; @@ -555,8 +555,8 @@ public void testGetVersionColumns() throws SQLException { @Test public void testGetUserName() throws SQLException, IOException { - GoogleCredentials credentials = - GoogleCredentials.fromStream( + ServiceAccountCredentials credentials = + ServiceAccountCredentials.fromStream( Objects.requireNonNull(ConnectionOptionsTest.class.getResource("test-key.json")) .openStream()); JdbcConnection connection = mock(JdbcConnection.class); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java index b42e81e5e593..92e590e162da 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcConnectTest.java @@ -20,6 +20,7 @@ import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; +import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ParallelIntegrationTest; @@ -230,7 +231,8 @@ public void testConnectWithDataSourceWithConflictingValues() throws SQLException public void testConnectWithOAuthToken() throws Exception { GoogleCredentials credentials; if (hasValidKeyFile()) { - credentials = GoogleCredentials.fromStream(Files.newInputStream(Paths.get(getKeyFile()))); + credentials = + ServiceAccountCredentials.fromStream(Files.newInputStream(Paths.get(getKeyFile()))); } else { try { credentials = GoogleCredentials.getApplicationDefault(); From ddf1f3c4e4ae72ce1dc8219dcfc01ea6b3c04264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 9 Oct 2025 07:13:37 +0200 Subject: [PATCH 1837/1979] docs: add samples for transaction isolation level (#2030) * docs: add samples for transaction isolation level * docs: update README and latency guide --- java-spanner-jdbc/README.md | 1 + .../documentation/latency-debugging-guide.md | 37 +++++++ .../example/spanner/jdbc/IsolationLevel.java | 73 ++++++++++++++ .../spanner/jdbc/IsolationLevelTest.java | 97 +++++++++++++++++++ .../jdbc/JdbcTransactionOptionsTest.java | 64 ++++++++++++ 5 files changed, 272 insertions(+) create mode 100644 java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/IsolationLevel.java create mode 100644 java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/IsolationLevelTest.java diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 61b3d5cb2ba5..bde34a69e875 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -109,6 +109,7 @@ See [Supported Connection Properties](documentation/connection_properties.md) fo supported connection properties. #### Commonly Used Properties +- default_isolation_level (String): Spanner supports isolation levels REPEATABLE_READ or SERIALIZABLE. SERIALIZABLE is the default. Using isolation level REPEATABLE_READ improves performance by reducing the amount of locks that are taken by transactions that execute a large number of queries in read/write transactions. See https://cloud.google.com/spanner/docs/isolation-levels for more information on the supported isolation levels in Spanner. - credentials (String): URL for the credentials file to use for the connection. If you do not specify any credentials at all, the default credentials of the environment as returned by `GoogleCredentials#getApplicationDefault()` is used. Example: `jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-db;credentials=/path/to/credentials.json` - autocommit (boolean): Sets the initial autocommit mode for the connection. Default is true. - readonly (boolean): Sets the initial readonly mode for the connection. Default is false. diff --git a/java-spanner-jdbc/documentation/latency-debugging-guide.md b/java-spanner-jdbc/documentation/latency-debugging-guide.md index cdcfec8265f7..0d2084c3f110 100644 --- a/java-spanner-jdbc/documentation/latency-debugging-guide.md +++ b/java-spanner-jdbc/documentation/latency-debugging-guide.md @@ -5,6 +5,43 @@ queries and transactions and to determine whether transactions or requests are b addition, all metrics described in [Latency points in a Spanner request](https://cloud.google.com/spanner/docs/latency-points) are also collected by the JDBC driver and can be used for debugging. +## Isolation Level + +A common reason for high latency in read/write transactions is lock contention. Spanner by default +uses isolation level `SERIALIZABLE`. This causes all queries in read/write transactions to take +locks for all rows that are scanned by a query. Using isolation level `REPEATABLE_READ` reduces the +number of locks that are taken during a read/write transaction, and can significantly improve +performance for applications that execute many and/or large queries in read/write transactions. + +Enable isolation level `REPEATABLE_READ` by default for all transactions that are executed by the +JDBC driver by setting the `default_isolation_level` connection property like this in the connection +URL: + +```java +String projectId = "my-project"; +String instanceId = "my-instance"; +String databaseId = "my-database"; +String isolationLevel = "REPEATABLE_READ"; + +try (Connection connection = + DriverManager.getConnection( + String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s?default_isolation_level=%s", + projectId, instanceId, databaseId, isolationLevel))) { + try (Statement statement = connection.createStatement()) { + try (ResultSet rs = statement.executeQuery("SELECT CURRENT_TIMESTAMP()")) { + while (rs.next()) { + System.out.printf( + "Connected to Cloud Spanner at [%s]%n", rs.getTimestamp(1).toString()); + } + } + } +} +``` + +See https://cloud.google.com/spanner/docs/isolation-levels for more information on the supported +isolation levels in Spanner. + ## Configuration You can configure the OpenTelemetry instance that should be used in two ways: diff --git a/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/IsolationLevel.java b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/IsolationLevel.java new file mode 100644 index 000000000000..7153b7c7aa2d --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/main/java/com/example/spanner/jdbc/IsolationLevel.java @@ -0,0 +1,73 @@ +/* + * Copyright 2025 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.example.spanner.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; + +final class IsolationLevel { + + static void isolationLevel( + final String project, + final String instance, + final String database, + final Properties properties) + throws SQLException { + String url = String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + project, instance, database); + try (Connection connection = DriverManager.getConnection(url, properties)) { + connection.setAutoCommit(false); + + // Spanner supports setting the isolation level to: + // 1. TRANSACTION_SERIALIZABLE (this is the default) + // 2. TRANSACTION_REPEATABLE_READ + + // The following line sets the default isolation level that will be used + // for all read/write transactions on this connection. + connection.setTransactionIsolation( + Connection.TRANSACTION_REPEATABLE_READ); + + // This query will not take any locks when using + // isolation level repeatable read. + try (ResultSet resultSet = connection + .createStatement() + .executeQuery("SELECT SingerId, Active " + + "FROM Singers " + + "ORDER BY LastName")) { + while (resultSet.next()) { + try (PreparedStatement statement = connection.prepareStatement( + "INSERT OR UPDATE INTO SingerHistory " + + "(SingerId, Active, CreatedAt) " + + "VALUES (?, ?, CURRENT_TIMESTAMP)")) { + statement.setLong(1, resultSet.getLong(1)); + statement.setBoolean(2, resultSet.getBoolean(2)); + statement.executeUpdate(); + } + } + } + connection.commit(); + } + } + + private IsolationLevel() { + } +} diff --git a/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/IsolationLevelTest.java b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/IsolationLevelTest.java new file mode 100644 index 000000000000..e1c7bfbe0155 --- /dev/null +++ b/java-spanner-jdbc/samples/snippets/src/test/java/com/example/spanner/jdbc/IsolationLevelTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2025 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.example.spanner.jdbc; + +import static com.example.spanner.jdbc.IsolationLevel.isolationLevel; +import static org.junit.Assume.assumeTrue; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; + +@RunWith(JUnit4.class) +public class IsolationLevelTest { + + private static GenericContainer emulator; + + private static final String PROJECT = "emulator-project"; + private static final String INSTANCE = "my-instance"; + private static final String DATABASE = "my-database"; + private static final Properties PROPERTIES = new Properties(); + + @BeforeClass + public static void setupEmulator() throws Exception { + assumeTrue("This test requires Docker", DockerClientFactory.instance().isDockerAvailable()); + + emulator = + new GenericContainer<>(DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator")); + emulator.withImagePullPolicy(PullPolicy.alwaysPull()); + emulator.addExposedPort(9010); + emulator.setWaitStrategy(Wait.forListeningPorts(9010)); + emulator.start(); + + PROPERTIES.setProperty("endpoint", + String.format("localhost:%d", emulator.getMappedPort(9010))); + PROPERTIES.setProperty("autoConfigEmulator", "true"); + + String url = String.format( + "jdbc:cloudspanner:/projects/%s/instances/%s/databases/%s", + PROJECT, INSTANCE, DATABASE); + try (Connection connection = DriverManager.getConnection(url, PROPERTIES)) { + try (Statement statement = connection.createStatement()) { + statement.addBatch( + "CREATE TABLE Singers (" + + "SingerId INT64 PRIMARY KEY, " + + "FirstName STRING(MAX), " + + "LastName STRING(MAX), " + + "Active BOOL)"); + statement.addBatch( + "CREATE TABLE SingerHistory (" + + "SingerId INT64, " + + "Active BOOL, " + + "CreatedAt TIMESTAMP) " + + "PRIMARY KEY (SingerId, CreatedAt)"); + statement.executeBatch(); + } + } + } + + @AfterClass + public static void stopEmulator() { + if (emulator != null) { + emulator.stop(); + } + } + + @Test + public void testIsolationLevel() throws SQLException { + isolationLevel("emulator-project", "my-instance", "my-database", PROPERTIES); + } + +} diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java index a34e449e76cf..8a5af27c0277 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTransactionOptionsTest.java @@ -27,10 +27,15 @@ import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.cloud.spanner.connection.SpannerPool; import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.TransactionOptions.IsolationLevel; +import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.time.Duration; +import java.util.Arrays; +import java.util.stream.Collectors; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -138,4 +143,63 @@ public void testMaxCommitDelay() throws SQLException { assertEquals(Duration.ofMillis(50).toNanos(), request.getMaxCommitDelay().getNanos()); } } + + @Test + public void testDefaultIsolationLevel() throws SQLException { + for (IsolationLevel isolationLevel : + Arrays.stream(IsolationLevel.values()) + .filter(level -> !level.equals(IsolationLevel.UNRECOGNIZED)) + .collect(Collectors.toList())) { + try (java.sql.Connection connection = + DriverManager.getConnection( + "jdbc:" + getBaseUrl() + ";default_isolation_level=" + isolationLevel.name())) { + connection.setAutoCommit(false); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT1_STATEMENT.getSql())) { + while (resultSet.next()) { + // ignore + } + } + connection.commit(); + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertEquals(isolationLevel, request.getTransaction().getBegin().getIsolationLevel()); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + + mockSpanner.clearRequests(); + } + } + } + + @Test + public void testSetIsolationLevel() throws SQLException { + try (java.sql.Connection connection = createJdbcConnection()) { + connection.setAutoCommit(false); + for (int isolationLevel : + new int[] {Connection.TRANSACTION_REPEATABLE_READ, Connection.TRANSACTION_SERIALIZABLE}) { + connection.setTransactionIsolation(isolationLevel); + try (ResultSet resultSet = + connection.createStatement().executeQuery(SELECT1_STATEMENT.getSql())) { + while (resultSet.next()) { + // ignore + } + } + connection.commit(); + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(request.hasTransaction()); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertEquals( + IsolationLevelConverter.convertToSpanner(isolationLevel), + request.getTransaction().getBegin().getIsolationLevel()); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + + mockSpanner.clearRequests(); + } + } + } } From 500be6aef8c409467ddb2be0e7bc33df56dbeee0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Oct 2025 07:47:06 +0100 Subject: [PATCH 1838/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.102.0 (#2246) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8bec03edf7b5..aa0088bff5fc 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.101.1 + 6.102.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 4cdb94895b2d..be86aa5080bd 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.101.1 + 6.102.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 2e0d47db4d38..ea86e1729bde 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.101.1 + 6.102.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 0d1ff90f6a1d..5549554e94ce 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.101.1 + 6.102.0 import pom From 884627f2ea66cb032a43f6d6f8e18b61fecd4a1b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Oct 2025 07:47:20 +0100 Subject: [PATCH 1839/1979] deps: update dependency net.bytebuddy:byte-buddy to v1.17.8 (#2245) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index ea86e1729bde..ddf8babe0f38 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy - 1.17.7 + 1.17.8 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 5549554e94ce..f38b1137761f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -108,7 +108,7 @@ net.bytebuddy byte-buddy - 1.17.7 + 1.17.8 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index b821d947e2b1..6828c16267dc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -105,7 +105,7 @@ net.bytebuddy byte-buddy - 1.17.7 + 1.17.8 test From e967d03424e5a324d95e4b1406072c6b8da2f197 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Oct 2025 09:05:34 +0100 Subject: [PATCH 1840/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.102.0 (#2244) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index f38b1137761f..de982023fbbe 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.101.1 + 6.102.0 test-jar test From 4a30c10bc21629c36a1ab11029e8c4bec0f5776f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 9 Oct 2025 09:05:54 +0100 Subject: [PATCH 1841/1979] deps: update dependency net.bytebuddy:byte-buddy-agent to v1.17.8 (#2243) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index ddf8babe0f38..b7305065b167 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -120,7 +120,7 @@ net.bytebuddy byte-buddy-agent - 1.17.7 + 1.17.8 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index de982023fbbe..0734042aecd1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy-agent - 1.17.7 + 1.17.8 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 6828c16267dc..449634a8a759 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -111,7 +111,7 @@ net.bytebuddy byte-buddy-agent - 1.17.7 + 1.17.8 test From 229134d29744b67e94e029400c821d1b7abad1b6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:06:03 +0200 Subject: [PATCH 1842/1979] chore(main): release 2.33.1 (#2231) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 20 ++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 38f6d8d3f07b..d5fe61cbd732 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [2.33.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.0...v2.33.1) (2025-10-09) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.76.0 ([#2240](https://github.com/googleapis/java-spanner-jdbc/issues/2240)) ([442565e](https://github.com/googleapis/java-spanner-jdbc/commit/442565ea8bf22ee926126fbd11a68a869b0772c7)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.101.1 ([#2227](https://github.com/googleapis/java-spanner-jdbc/issues/2227)) ([275c6bd](https://github.com/googleapis/java-spanner-jdbc/commit/275c6bd7f3f58b3f980e9ffaa576d1f910ecf08b)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.102.0 ([#2244](https://github.com/googleapis/java-spanner-jdbc/issues/2244)) ([383a392](https://github.com/googleapis/java-spanner-jdbc/commit/383a39222c7526163323575734c8473a34d4098d)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.101.1 ([#2228](https://github.com/googleapis/java-spanner-jdbc/issues/2228)) ([ded7944](https://github.com/googleapis/java-spanner-jdbc/commit/ded79447b8ecd294e56560b43cb02e45464706f1)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.102.0 ([#2246](https://github.com/googleapis/java-spanner-jdbc/issues/2246)) ([7162ac2](https://github.com/googleapis/java-spanner-jdbc/commit/7162ac236a77c24b4f0faccefa2cf3bdee6b96ab)) +* Update dependency com.google.cloud:google-cloud-trace to v2.76.0 ([#2241](https://github.com/googleapis/java-spanner-jdbc/issues/2241)) ([ff2432d](https://github.com/googleapis/java-spanner-jdbc/commit/ff2432d46cd23df2230671297f06c8e6fca8f1d7)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.52.3 ([#2236](https://github.com/googleapis/java-spanner-jdbc/issues/2236)) ([9a44975](https://github.com/googleapis/java-spanner-jdbc/commit/9a44975e0ab7ca49514be1d9ea03e8e760a0f3bc)) +* Update dependency net.bytebuddy:byte-buddy to v1.17.8 ([#2245](https://github.com/googleapis/java-spanner-jdbc/issues/2245)) ([60a3a8f](https://github.com/googleapis/java-spanner-jdbc/commit/60a3a8f0fcf86742128f8803ee3297670b713923)) +* Update dependency net.bytebuddy:byte-buddy-agent to v1.17.8 ([#2243](https://github.com/googleapis/java-spanner-jdbc/issues/2243)) ([952c08a](https://github.com/googleapis/java-spanner-jdbc/commit/952c08afbf2f7838ad864b8bb58423e8b566d325)) + + +### Documentation + +* Add samples for transaction isolation level ([#2030](https://github.com/googleapis/java-spanner-jdbc/issues/2030)) ([ca243d1](https://github.com/googleapis/java-spanner-jdbc/commit/ca243d194ef392d44cea561a148c0376b9af630d)) + ## [2.33.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.32.3...v2.33.0) (2025-09-27) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index bde34a69e875..8fb6a054d3f9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.33.0 + 2.33.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index aa0088bff5fc..fcd478ebb3f5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.1-SNAPSHOT + 2.33.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index e23e32c1aed1..46627619c81a 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.1-SNAPSHOT + 2.33.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 53ba1a2db99e..515f0d555783 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.0:2.33.1-SNAPSHOT +google-cloud-spanner-jdbc:2.33.1:2.33.1 From b07ca27a570fe8643472f84f7f5aca05f2d5cf1f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:12:04 +0200 Subject: [PATCH 1843/1979] chore(main): release 2.33.2-SNAPSHOT (#2247) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fcd478ebb3f5..d8064cda413d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.1 + 2.33.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 46627619c81a..6d76aca66938 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.1 + 2.33.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 515f0d555783..35e1d8efadad 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.1:2.33.1 +google-cloud-spanner-jdbc:2.33.1:2.33.2-SNAPSHOT From 8518e4e7760cb2f47f79c26ad9abc7523eafd02b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 22 Oct 2025 16:25:37 +0100 Subject: [PATCH 1844/1979] deps: update dependency org.springframework.data:spring-data-bom to v2025.0.5 (#2258) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index be86aa5080bd..b34c28985b43 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.4 + 2025.0.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b7305065b167..39d4be8a3359 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -23,7 +23,7 @@ org.springframework.data spring-data-bom - 2025.0.4 + 2025.0.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 0734042aecd1..992baacd7986 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.4 + 2025.0.5 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 449634a8a759..1b802c2ef71b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -28,7 +28,7 @@ org.springframework.data spring-data-bom - 2025.0.4 + 2025.0.5 import pom From 73889cc96ebc6422924bb5418d9feedf8b92403e Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:00:52 +0530 Subject: [PATCH 1845/1979] fix: findColumn is case-sensitive for unquoted identifier (#2261) * fix: findColumn is case-sensitive for unquoted identifier * Addressed comments --- .../google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 2 +- .../cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 67c6976c7a24..98d23a2261f5 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -187,7 +187,7 @@ public boolean storesUpperCaseIdentifiers() { @Override public boolean storesLowerCaseIdentifiers() { - return false; + return connection.getDialect() == Dialect.POSTGRESQL; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index d5a429078ac6..4545bb56ec21 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -61,6 +61,7 @@ public static Object[] data() { @Test public void testTrivialMethods() throws SQLException { JdbcConnection connection = mock(JdbcConnection.class); + when(connection.getDialect()).thenReturn(dialect); DatabaseMetaData meta = new JdbcDatabaseMetaData(connection); assertTrue(meta.allProceduresAreCallable()); assertTrue(meta.allTablesAreSelectable()); @@ -132,7 +133,11 @@ public void testTrivialMethods() throws SQLException { assertTrue(meta.nullPlusNonNullIsNull()); assertFalse(meta.isCatalogAtStart()); assertEquals(connection.isReadOnly(), meta.isReadOnly()); - assertFalse(meta.storesLowerCaseIdentifiers()); + if (dialect == Dialect.POSTGRESQL) { + assertTrue(meta.storesLowerCaseIdentifiers()); + } else { + assertFalse(meta.storesLowerCaseIdentifiers()); + } assertFalse(meta.storesLowerCaseQuotedIdentifiers()); assertTrue(meta.storesMixedCaseIdentifiers()); assertTrue(meta.storesMixedCaseQuotedIdentifiers()); From 7c277fdd95f3b106a49aaf7cdb8f2c0ad131ff39 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 22 Oct 2025 20:11:56 +0100 Subject: [PATCH 1846/1979] deps: update dependency org.testcontainers:testcontainers-bom to v2 (#2255) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 992baacd7986..a7923c7a4798 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 1.21.3 + 2.0.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 1b802c2ef71b..68f5d7dab043 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 1.21.3 + 2.0.1 import pom From ed7b14022776d315f6b104d1b86b9f2bcc48f29b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 22 Oct 2025 20:37:26 +0100 Subject: [PATCH 1847/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.78.0 (#2253) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d8064cda413d..7d2712055a91 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.76.0 + 2.78.0 test From 497bc2ddc5e84e3624d067e2c85ac78869226a0d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Oct 2025 06:50:52 +0100 Subject: [PATCH 1848/1979] deps: update dependency org.testcontainers:testcontainers to v2 (#2254) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7d2712055a91..0a9536e8e13c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 1.21.3 + 2.0.1 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ca7335c4fb33..72ca67a5b5bf 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 1.21.3 + 2.0.1 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 07c7ab457aeb..e21310cf53b4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 1.21.3 + 2.0.1 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index b34c28985b43..6f3d5b5c3a3b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 1.21.3 + 2.0.1 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 39d4be8a3359..124270942073 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -132,7 +132,7 @@ org.testcontainers testcontainers - 1.21.3 + 2.0.1 test From 36464a7bbea56cf33f2ecb30664ab3bd09a29a40 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Thu, 23 Oct 2025 13:00:53 +0530 Subject: [PATCH 1849/1979] chore: Support PG Dialect in Hibernate (#2238) * chore: Support text/varchar type in JDBC * Addressed comments --- .../google/cloud/spanner/jdbc/JdbcArray.java | 8 ++-- .../cloud/spanner/jdbc/JdbcDataType.java | 37 +++++++++++++++++++ .../DatabaseMetaData_GetColumns.sql | 10 ++++- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 80bea84ebd95..1dd83f8171a4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -60,9 +60,11 @@ class JdbcArray implements Array { * the elements array is not compatible with the base type of the array. */ static JdbcArray createArray(String typeName, Object[] elements) throws SQLException { - for (JdbcDataType type : JdbcDataType.values()) { - if (type.getTypeName().equalsIgnoreCase(typeName)) { - return new JdbcArray(type, elements); + if (typeName != null) { + for (JdbcDataType type : JdbcDataType.values()) { + if (type.matches(typeName)) { + return new JdbcArray(type, elements); + } } } throw JdbcSqlExceptionFactory.of( diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index 6a77cecc2ddc..c80db530226c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type; @@ -154,6 +155,7 @@ public Type getSpannerType() { }, FLOAT64 { private final Set> classes = new HashSet<>(Arrays.asList(Float.class, Double.class)); + private final Set aliases = new HashSet<>(Collections.singletonList("float8")); @Override public int getSqlType() { @@ -184,6 +186,11 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.float64(); } + + @Override + public Set getPostgreSQLAliases() { + return aliases; + } }, INT64 { private final Set> classes = @@ -220,6 +227,9 @@ public Type getSpannerType() { } }, NUMERIC { + + private final Set aliases = new HashSet<>(Collections.singletonList("decimal")); + @Override public int getSqlType() { return Types.NUMERIC; @@ -244,6 +254,11 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.numeric(); } + + @Override + public Set getPostgreSQLAliases() { + return aliases; + } }, PG_NUMERIC { @Override @@ -272,6 +287,8 @@ public Type getSpannerType() { } }, STRING { + private final Set aliases = new HashSet<>(Arrays.asList("varchar", "text")); + @Override public int getSqlType() { return Types.NVARCHAR; @@ -296,6 +313,11 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.string(); } + + @Override + public Set getPostgreSQLAliases() { + return aliases; + } }, JSON { @Override @@ -498,6 +520,21 @@ public Type getSpannerType() { public abstract Type getSpannerType(); + public Set getPostgreSQLAliases() { + return Collections.emptySet(); + } + + /*** + * @param typeName type of the column + * @return true if type name matches current type name or matches with one of postgres aliases + * or if it matches equivalent postgres type. + */ + boolean matches(String typeName) { + return getTypeName().equalsIgnoreCase(typeName) + || getPostgreSQLAliases().contains(typeName.toLowerCase()) + || getSpannerType().getSpannerTypeName(Dialect.POSTGRESQL).equalsIgnoreCase(typeName); + } + // TODO: Implement and use this method for all types. public int getPrecision() { throw new UnsupportedOperationException(); diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index a8260ff1383c..b0ca399442ee 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -28,7 +28,15 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE = 'jsonb' THEN -9 WHEN DATA_TYPE = 'timestamp with time zone' THEN 93 END AS "DATA_TYPE", - DATA_TYPE AS "TYPE_NAME", + CASE + WHEN DATA_TYPE LIKE 'ARRAY' THEN + CASE + WHEN spanner_type LIKE '%[]' THEN + CONCAT('_', REPLACE(spanner_type, '[]', '')) + ELSE spanner_type + END + ELSE DATA_TYPE + END AS "TYPE_NAME", CASE WHEN DATA_TYPE LIKE 'ARRAY' THEN 0 WHEN DATA_TYPE = 'boolean' THEN NULL From 4a62b798f86ec4627c796d0afa71920be0e0f335 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Oct 2025 08:34:15 +0100 Subject: [PATCH 1850/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.78.0 (#2252) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 0a9536e8e13c..95d3dcb694e8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.76.0 + 2.78.0 test From 5c1dc32a07d9f440cbd3c946645879e4f683dec5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Oct 2025 08:40:48 +0100 Subject: [PATCH 1851/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.55.0 (#2251) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 6f3d5b5c3a3b..15fbc5599ef0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.54.1 + 1.55.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 124270942073..54aa380bee55 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.54.1 + 1.55.0 pom import From 688670b72b8aca1f71648dc2c0009b3ae26f60d1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Oct 2025 08:48:31 +0100 Subject: [PATCH 1852/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.70.0 (#2249) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 72ca67a5b5bf..ddc9b6d2066e 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index e21310cf53b4..c44ac90ee1b0 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 15fbc5599ef0..294573cb4e24 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 54aa380bee55..52be4d54f2e8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index a7923c7a4798..ad39f30e4671 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 68f5d7dab043..bc3d4bcde949 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.69.0 + 26.70.0 import pom From 88a31851bd58ff59fc565c1ac63abf7fefccccd4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 23 Oct 2025 09:11:28 +0100 Subject: [PATCH 1853/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.1 (#2248) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 041fab8ac1c1..55f80e80a531 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.0 + 2.33.1 From ca999f8d7b526d507eaf10f71e65d8acce1ba195 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 Oct 2025 06:18:04 +0100 Subject: [PATCH 1854/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.53.0 (#2257) * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.53.0 * deps: update dependency com.google.cloud:google-cloud-spanner to v6.102.1 * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.102.1 --------- Co-authored-by: Lawrence Qiu --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 4 ++-- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/googlesql/pom.xml | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 2cf303dc3847..c4ee2b91a8a7 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.52.3 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.53.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 85695810d8a1..0cf782fcc73b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.52.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.53.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index c2efdcebf531..15deac1d1b14 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.52.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.53.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 20946e7b08ae..928626c44f6b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.52.3" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.53.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 95d3dcb694e8..c8cfa7d5376c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.52.3 + 3.53.0 @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.0 + 6.102.1 pom import diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index ddc9b6d2066e..68ac4ae35124 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.52.3 + 3.53.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c44ac90ee1b0..d936ece2e6e7 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.52.3 + 3.53.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 294573cb4e24..895e5735ab30 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.0 + 6.102.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 52be4d54f2e8..8d0216077f9a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.0 + 6.102.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index ad39f30e4671..9e36806ece19 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.0 + 6.102.1 import pom @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.102.0 + 6.102.1 test-jar test From db626a4f34315ae7fcf5eb097ed9dcb4ee765855 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 Oct 2025 07:07:51 +0100 Subject: [PATCH 1855/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.7 (#2267) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 9e36806ece19..1abc6dd0c3c2 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.6 + 3.5.7 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index bc3d4bcde949..83ea8608b1ea 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.6 + 3.5.7 From 5336cba4454a4ed6f689030c74c6f7429c22bebf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 Oct 2025 07:17:09 +0100 Subject: [PATCH 1856/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.7 (#2264) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 895e5735ab30..c9b0390a1cc8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.6 + 3.5.7 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 8d0216077f9a..581e89ec97e5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.6 + 3.5.7 From e88e1f6229f4d4eb1ad71886461e0f5d74c8976f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 Oct 2025 07:17:28 +0100 Subject: [PATCH 1857/1979] deps: update dependency org.springframework.boot:spring-boot to v3.5.7 (#2263) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 68ac4ae35124..09d9cd31dfab 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.6 + 3.5.7 test From ad6899be6ae02bdd33c0b4f735ae184f4d405287 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 24 Oct 2025 08:25:12 +0100 Subject: [PATCH 1858/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.6.2 (#2259) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 09d9cd31dfab..8450000d9824 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.6.1 + 3.6.2 com.google.cloud.jdbc.quickperf.QuickPerf From 41261033763a5a7cdbf1b51d4aaa8919294096ac Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:27:31 +0100 Subject: [PATCH 1859/1979] chore(main): release 2.33.2 (#2262) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 22 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d5fe61cbd732..4129da1b0692 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [2.33.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.1...v2.33.2) (2025-10-24) + + +### Bug Fixes + +* FindColumn is case-sensitive for unquoted identifier ([#2261](https://github.com/googleapis/java-spanner-jdbc/issues/2261)) ([71441f7](https://github.com/googleapis/java-spanner-jdbc/commit/71441f7e896d5a60c1e6bac9b9a991a9d18fbe3c)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.78.0 ([#2252](https://github.com/googleapis/java-spanner-jdbc/issues/2252)) ([37ea3f0](https://github.com/googleapis/java-spanner-jdbc/commit/37ea3f0652462470b76a5d68f54b543b8afa8a97)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.102.1 ([0d335a9](https://github.com/googleapis/java-spanner-jdbc/commit/0d335a932b8a035b90c866a8b3639d225fa329b0)) +* Update dependency com.google.cloud:google-cloud-trace to v2.78.0 ([#2253](https://github.com/googleapis/java-spanner-jdbc/issues/2253)) ([e51eaeb](https://github.com/googleapis/java-spanner-jdbc/commit/e51eaeb401a55161474c2848af51446e7669dca0)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.53.0 ([0d335a9](https://github.com/googleapis/java-spanner-jdbc/commit/0d335a932b8a035b90c866a8b3639d225fa329b0)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.55.0 ([#2251](https://github.com/googleapis/java-spanner-jdbc/issues/2251)) ([14e9ea6](https://github.com/googleapis/java-spanner-jdbc/commit/14e9ea6b9356eb59cd42a14bea4af3ca102a5cf1)) +* Update dependency org.springframework.boot:spring-boot to v3.5.7 ([#2263](https://github.com/googleapis/java-spanner-jdbc/issues/2263)) ([0a916b9](https://github.com/googleapis/java-spanner-jdbc/commit/0a916b97925b0651a8cbc69e546bf6539fc39b27)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.7 ([#2264](https://github.com/googleapis/java-spanner-jdbc/issues/2264)) ([3f8d0db](https://github.com/googleapis/java-spanner-jdbc/commit/3f8d0db636a6278a3eefd8de0835f776efcbb0e0)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.7 ([#2267](https://github.com/googleapis/java-spanner-jdbc/issues/2267)) ([1f79712](https://github.com/googleapis/java-spanner-jdbc/commit/1f79712792587b8827e5546064f61e8e7e0bec11)) +* Update dependency org.springframework.data:spring-data-bom to v2025.0.5 ([#2258](https://github.com/googleapis/java-spanner-jdbc/issues/2258)) ([1054cdd](https://github.com/googleapis/java-spanner-jdbc/commit/1054cddc60b811fe919a8313f433b3490e0f0cfb)) +* Update dependency org.testcontainers:testcontainers to v2 ([#2254](https://github.com/googleapis/java-spanner-jdbc/issues/2254)) ([4058ed5](https://github.com/googleapis/java-spanner-jdbc/commit/4058ed537b4c70d807d589d51410301ea73434be)) +* Update dependency org.testcontainers:testcontainers-bom to v2 ([#2255](https://github.com/googleapis/java-spanner-jdbc/issues/2255)) ([64faa98](https://github.com/googleapis/java-spanner-jdbc/commit/64faa9867b0a6d9535a03fecfcfada6d34687457)) + ## [2.33.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.0...v2.33.1) (2025-10-09) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 8fb6a054d3f9..46c4e8d4853e 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.33.1 + 2.33.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c8cfa7d5376c..4fa663080a36 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.2-SNAPSHOT + 2.33.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 6d76aca66938..55374ef43791 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.2-SNAPSHOT + 2.33.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 35e1d8efadad..09fcf19e3258 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.1:2.33.2-SNAPSHOT +google-cloud-spanner-jdbc:2.33.2:2.33.2 From 81f377bf6a19aec5089526b4f419fe2b4bf54a0c Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:18:22 +0000 Subject: [PATCH 1860/1979] chore(main): release 2.33.3-SNAPSHOT (#2268) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 4fa663080a36..da07cc000d1c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.2 + 2.33.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 55374ef43791..14419ef94d8b 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.2 + 2.33.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 09fcf19e3258..3df04dfd0503 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.2:2.33.2 +google-cloud-spanner-jdbc:2.33.2:2.33.3-SNAPSHOT From 1a19209a425cde53092f396efd38d51c995f69d7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 27 Oct 2025 17:56:22 +0000 Subject: [PATCH 1861/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.2 (#2269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.33.1` -> `2.33.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.33.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.33.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.33.1/2.33.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.33.1/2.33.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.33.2`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2332-2025-10-24) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.33.1...v2.33.2) ##### Bug Fixes - FindColumn is case-sensitive for unquoted identifier ([#​2261](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2261)) ([73889cc](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/73889cc96ebc6422924bb5418d9feedf8b92403e)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.78.0 ([#​2252](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2252)) ([4a62b79](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/4a62b798f86ec4627c796d0afa71920be0e0f335)) - Update dependency com.google.cloud:google-cloud-spanner to v6.102.1 ([ca999f8](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/ca999f8d7b526d507eaf10f71e65d8acce1ba195)) - Update dependency com.google.cloud:google-cloud-trace to v2.78.0 ([#​2253](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2253)) ([ed7b140](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/ed7b14022776d315f6b104d1b86b9f2bcc48f29b)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.53.0 ([ca999f8](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/ca999f8d7b526d507eaf10f71e65d8acce1ba195)) - Update dependency io.opentelemetry:opentelemetry-bom to v1.55.0 ([#​2251](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2251)) ([5c1dc32](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/5c1dc32a07d9f440cbd3c946645879e4f683dec5)) - Update dependency org.springframework.boot:spring-boot to v3.5.7 ([#​2263](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2263)) ([e88e1f6](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/e88e1f6229f4d4eb1ad71886461e0f5d74c8976f)) - Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v3.5.7 ([#​2264](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2264)) ([5336cba](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/5336cba4454a4ed6f689030c74c6f7429c22bebf)) - Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.7 ([#​2267](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2267)) ([db626a4](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/db626a4f34315ae7fcf5eb097ed9dcb4ee765855)) - Update dependency org.springframework.data:spring-data-bom to v2025.0.5 ([#​2258](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2258)) ([8518e4e](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/8518e4e7760cb2f47f79c26ad9abc7523eafd02b)) - Update dependency org.testcontainers:testcontainers to v2 ([#​2254](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2254)) ([497bc2d](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/497bc2ddc5e84e3624d067e2c85ac78869226a0d)) - Update dependency org.testcontainers:testcontainers-bom to v2 ([#​2255](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2255)) ([7c277fd](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/7c277fdd95f3b106a49aaf7cdb8f2c0ad131ff39))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 55f80e80a531..0e24a8973402 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.1 + 2.33.2 From fe861b7aca0fc11bbd85b03eecefed5e852dcb3a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Oct 2025 10:08:23 +0000 Subject: [PATCH 1862/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.71.0 (#2270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/googleapis/java-cloud-bom)) | `26.70.0` -> `26.71.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:libraries-bom/26.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:libraries-bom/26.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:libraries-bom/26.70.0/26.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:libraries-bom/26.70.0/26.71.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-cloud-bom (com.google.cloud:libraries-bom) ### [`v26.71.0`](https://redirect.github.com/googleapis/java-cloud-bom/blob/HEAD/CHANGELOG.md#26710-2025-10-27) [Compare Source](https://redirect.github.com/googleapis/java-cloud-bom/compare/v26.70.0...v26.71.0) ##### Dependencies - update dependency com.google.cloud:first-party-dependencies to v3.53.0 ([#​7243](https://redirect.github.com/googleapis/java-cloud-bom/issues/7243)) ([22ff0f1](https://redirect.github.com/googleapis/java-cloud-bom/commit/22ff0f171b858c186ac3a94b5797cb39f8980e11)) - update dependency com.google.cloud:gapic-libraries-bom to v1.71.0 ([#​7241](https://redirect.github.com/googleapis/java-cloud-bom/issues/7241)) ([c6d3b55](https://redirect.github.com/googleapis/java-cloud-bom/commit/c6d3b55d73ca965a06e0de07a5ff41dc75c39219)) - update dependency com.google.cloud:gapic-libraries-bom to v1.72.0 ([#​7256](https://redirect.github.com/googleapis/java-cloud-bom/issues/7256)) ([43b27a3](https://redirect.github.com/googleapis/java-cloud-bom/commit/43b27a3ed4405e4fc789a8c7778564e5bbed346f)) - update dependency com.google.cloud:google-cloud-bigquery to v2.55.3 ([#​7252](https://redirect.github.com/googleapis/java-cloud-bom/issues/7252)) ([24111df](https://redirect.github.com/googleapis/java-cloud-bom/commit/24111df15341483ffb519dcc3d7f1c23d70a3d7b)) - update dependency com.google.cloud:google-cloud-bigquerystorage-bom to v3.17.3 ([#​7244](https://redirect.github.com/googleapis/java-cloud-bom/issues/7244)) ([562db50](https://redirect.github.com/googleapis/java-cloud-bom/commit/562db50489a177e9706097cb1ac1fa3dca4aeafb)) - update dependency com.google.cloud:google-cloud-bigtable-bom to v2.68.0 ([#​7258](https://redirect.github.com/googleapis/java-cloud-bom/issues/7258)) ([2d9916f](https://redirect.github.com/googleapis/java-cloud-bom/commit/2d9916f128c828056623ddd954ed546c13b4d6b5)) - update dependency com.google.cloud:google-cloud-datastore-bom to v2.32.3 ([#​7245](https://redirect.github.com/googleapis/java-cloud-bom/issues/7245)) ([45bc468](https://redirect.github.com/googleapis/java-cloud-bom/commit/45bc468665abf66b74198bf75e624a9e3700c2ed)) - update dependency com.google.cloud:google-cloud-firestore-bom to v3.33.3 ([#​7246](https://redirect.github.com/googleapis/java-cloud-bom/issues/7246)) ([b4029e6](https://redirect.github.com/googleapis/java-cloud-bom/commit/b4029e6205ebe0f107f491b2f2bd2d826ee0ec30)) - update dependency com.google.cloud:google-cloud-logging-bom to v3.23.7 ([#​7247](https://redirect.github.com/googleapis/java-cloud-bom/issues/7247)) ([1c8d9fa](https://redirect.github.com/googleapis/java-cloud-bom/commit/1c8d9fa3ca79a915734e6677460aa912c25d3687)) - update dependency com.google.cloud:google-cloud-logging-logback to v0.132.18-alpha ([#​7253](https://redirect.github.com/googleapis/java-cloud-bom/issues/7253)) ([b1df096](https://redirect.github.com/googleapis/java-cloud-bom/commit/b1df096499c508504d89c8152565d98a728e20f9)) - update dependency com.google.cloud:google-cloud-nio to v0.128.7 ([#​7255](https://redirect.github.com/googleapis/java-cloud-bom/issues/7255)) ([c13532a](https://redirect.github.com/googleapis/java-cloud-bom/commit/c13532a780a8849eeb5fcf48d752b9c8297b79b6)) - update dependency com.google.cloud:google-cloud-pubsub-bom to v1.143.0 ([#​7248](https://redirect.github.com/googleapis/java-cloud-bom/issues/7248)) ([ddfe793](https://redirect.github.com/googleapis/java-cloud-bom/commit/ddfe793e702be6719b68b822c5f00ebeed39e7d2)) - update dependency com.google.cloud:google-cloud-pubsublite-bom to v1.15.18 ([#​7250](https://redirect.github.com/googleapis/java-cloud-bom/issues/7250)) ([74c338d](https://redirect.github.com/googleapis/java-cloud-bom/commit/74c338ddd0adb6a2b306ca74bc122d4b66d56d9d)) - update dependency com.google.cloud:google-cloud-spanner-bom to v6.102.1 ([#​7259](https://redirect.github.com/googleapis/java-cloud-bom/issues/7259)) ([49160d0](https://redirect.github.com/googleapis/java-cloud-bom/commit/49160d076a336d39d8e7eb21184d1b0a2f9f39c1)) - update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.2 ([#​7260](https://redirect.github.com/googleapis/java-cloud-bom/issues/7260)) ([0d04af6](https://redirect.github.com/googleapis/java-cloud-bom/commit/0d04af61d76a5e8516af524e4ed97713b55f08cf)) - update dependency com.google.cloud:google-cloud-storage-bom to v2.59.0 ([#​7254](https://redirect.github.com/googleapis/java-cloud-bom/issues/7254)) ([9920709](https://redirect.github.com/googleapis/java-cloud-bom/commit/9920709bca6ef6c93e6f90ab7590c9b3125d3843)) - update dependency com.google.protobuf:protobuf-bom to v4.33.0 ([#​7257](https://redirect.github.com/googleapis/java-cloud-bom/issues/7257)) ([4c33cf2](https://redirect.github.com/googleapis/java-cloud-bom/commit/4c33cf2061a80d2a8cf1a2ffaec5020cd7a8b614))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 8450000d9824..961d4510fd18 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d936ece2e6e7..d530b54f09df 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index c9b0390a1cc8..cd696f70cf95 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 581e89ec97e5..1a53393d0721 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 1abc6dd0c3c2..2a3211d21f7b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 83ea8608b1ea..a324b7e7979f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.70.0 + 26.71.0 import pom From 20a22f4d20459bc64b563b7f9ba27ef3def788d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 28 Oct 2025 12:01:13 +0100 Subject: [PATCH 1863/1979] fix: run DatabaseMetadata tests for PG on emulator (#2271) * test: run DatabaseMetadata tests for PG on emulator Run the DatabaseMetadata integration tests for PostgreSQL-dialect databases on the emulator. * fix: add explicit casts to function arguments --- .../jdbc/postgresql/DatabaseMetaData_GetColumns.sql | 2 +- .../google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql index b0ca399442ee..7e450f71fc2f 100644 --- a/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql +++ b/java-spanner-jdbc/src/main/resources/com/google/cloud/spanner/jdbc/postgresql/DatabaseMetaData_GetColumns.sql @@ -32,7 +32,7 @@ SELECT TABLE_CATALOG AS "TABLE_CAT", TABLE_SCHEMA AS "TABLE_SCHEM", TABLE_NAME A WHEN DATA_TYPE LIKE 'ARRAY' THEN CASE WHEN spanner_type LIKE '%[]' THEN - CONCAT('_', REPLACE(spanner_type, '[]', '')) + CONCAT('_'::varchar, REPLACE(spanner_type, '[]'::varchar, ''::varchar)) ELSE spanner_type END ELSE DATA_TYPE diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java index a7c7a206dbf1..b1bf1bce790c 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcPgNumericTest.java @@ -182,6 +182,14 @@ public void testResultSet() throws SQLException { assertEquals(new BigDecimal(negativeBigNumeric), resultSet.getBigDecimal("col1")); assertEquals(new BigDecimal(negativeBigNumeric), resultSet.getObject("col1")); assertEquals(Value.pgNumeric(negativeBigNumeric), resultSet.getObject("col1", Value.class)); + + // Just verify that the getColumns method works + try (ResultSet columns = connection.getMetaData().getColumns(null, null, null, null)) { + //noinspection StatementWithEmptyBody + while (columns.next()) { + // ignore + } + } } } From c42cd9426667f65c55417b09a27009a3463d0dbd Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 11:42:23 +0000 Subject: [PATCH 1864/1979] chore(main): release 2.33.3 (#2272) :robot: I have created a release *beep* *boop* --- ## [2.33.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.33.2...v2.33.3) (2025-10-28) ### Bug Fixes * Run DatabaseMetadata tests for PG on emulator ([#2271](https://togithub.com/googleapis/java-spanner-jdbc/issues/2271)) ([20a22f4](https://togithub.com/googleapis/java-spanner-jdbc/commit/20a22f4d20459bc64b563b7f9ba27ef3def788d2)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4129da1b0692..f9253794c5e1 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.33.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.2...v2.33.3) (2025-10-28) + + +### Bug Fixes + +* Run DatabaseMetadata tests for PG on emulator ([#2271](https://github.com/googleapis/java-spanner-jdbc/issues/2271)) ([e7b20eb](https://github.com/googleapis/java-spanner-jdbc/commit/e7b20ebd0ec1554e969c9097c1d5b7c5b6dcc232)) + ## [2.33.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.1...v2.33.2) (2025-10-24) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 46c4e8d4853e..d6bac06ef3e2 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.33.2 + 2.33.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index da07cc000d1c..d741bb8a51de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.3-SNAPSHOT + 2.33.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 14419ef94d8b..3cf3a3e4cc92 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.3-SNAPSHOT + 2.33.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 3df04dfd0503..c8fb75f41a20 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.2:2.33.3-SNAPSHOT +google-cloud-spanner-jdbc:2.33.3:2.33.3 From 1f59574477e8543727ba0119de82bb15bf020f00 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 12:12:22 +0000 Subject: [PATCH 1865/1979] chore(main): release 2.33.4-SNAPSHOT (#2273) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d741bb8a51de..ea83da528790 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.3 + 2.33.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 3cf3a3e4cc92..5fa54aaacd82 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.3 + 2.33.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c8fb75f41a20..1ffb9187ee5b 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.3:2.33.3 +google-cloud-spanner-jdbc:2.33.3:2.33.4-SNAPSHOT From 6e0462b69dab0913890c4c0422b8b5f41f34058d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 28 Oct 2025 12:34:22 +0000 Subject: [PATCH 1866/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.33.3 (#2274) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-jdbc](https://redirect.github.com/googleapis/java-spanner-jdbc) | `2.33.2` -> `2.33.3` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-jdbc/2.33.3?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.33.3?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.33.2/2.33.3?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.33.2/2.33.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    googleapis/java-spanner-jdbc (com.google.cloud:google-cloud-spanner-jdbc) ### [`v2.33.3`](https://redirect.github.com/googleapis/java-spanner-jdbc/blob/HEAD/CHANGELOG.md#2333-2025-10-28) [Compare Source](https://redirect.github.com/googleapis/java-spanner-jdbc/compare/v2.33.2...v2.33.3) ##### Bug Fixes - Run DatabaseMetadata tests for PG on emulator ([#​2271](https://redirect.github.com/googleapis/java-spanner-jdbc/issues/2271)) ([20a22f4](https://redirect.github.com/googleapis/java-spanner-jdbc/commit/20a22f4d20459bc64b563b7f9ba27ef3def788d2))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 0e24a8973402..8fb4480bb98e 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.2 + 2.33.3 From 64bc84b1c06c62489c03f612192c1aeec7e7aef9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 31 Oct 2025 08:41:41 +0000 Subject: [PATCH 1867/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.1 (#2275) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 961d4510fd18..fa77d4400519 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.20.0 + 2.20.1 From 013f85cc963fe9094cc888e59bb6f8f5091c54ab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 09:54:25 +0000 Subject: [PATCH 1868/1979] deps: update dependency org.testcontainers:testcontainers-bom to v2.0.2 (#2285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.testcontainers:testcontainers-bom](https://java.testcontainers.org) ([source](https://redirect.github.com/testcontainers/testcontainers-java)) | `2.0.1` -> `2.0.2` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.testcontainers:testcontainers-bom/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.testcontainers:testcontainers-bom/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.testcontainers:testcontainers-bom/2.0.1/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.testcontainers:testcontainers-bom/2.0.1/2.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    testcontainers/testcontainers-java (org.testcontainers:testcontainers-bom) ### [`v2.0.2`](https://redirect.github.com/testcontainers/testcontainers-java/releases/tag/2.0.2) [Compare Source](https://redirect.github.com/testcontainers/testcontainers-java/compare/2.0.1...2.0.2) ### What's Changed - Update docker image version to 25.0.5 ([#​11219](https://redirect.github.com/testcontainers/testcontainers-java/issues/11219)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Set default docker API version to 1.44 ([#​11216](https://redirect.github.com/testcontainers/testcontainers-java/issues/11216)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Fix ollama example ([#​11217](https://redirect.github.com/testcontainers/testcontainers-java/issues/11217)) [@​eddumelendez](https://redirect.github.com/eddumelendez) - Update testcontainers version to ${GITHUB\_REF##\*/} ([#​11125](https://redirect.github.com/testcontainers/testcontainers-java/issues/11125)) @​[github-actions\[bot\]](https://redirect.github.com/apps/github-actions) - Update docs version to ${GITHUB\_REF##\*/} ([#​11126](https://redirect.github.com/testcontainers/testcontainers-java/issues/11126)) @​[github-actions\[bot\]](https://redirect.github.com/apps/github-actions) #### 🐛 Bug Fixes - Optimize ScriptSplitter from O(n\*m) to O(1) when initializing database ([#​11130](https://redirect.github.com/testcontainers/testcontainers-java/issues/11130)) [@​hspragg-godaddy](https://redirect.github.com/hspragg-godaddy) #### 📖 Documentation - Update kotest-extensions-testcontainers link ([#​11138](https://redirect.github.com/testcontainers/testcontainers-java/issues/11138)) [@​noojung](https://redirect.github.com/noojung) #### 🧹 Housekeeping - Add getBaseUrl() to NginxContainer using NGINX\_DEFAULT\_PORT ([#​11137](https://redirect.github.com/testcontainers/testcontainers-java/issues/11137)) [@​ghusta](https://redirect.github.com/ghusta) #### 📦 Dependency updates - Update docker-java version to 3.7.0 ([#​11218](https://redirect.github.com/testcontainers/testcontainers-java/issues/11218)) [@​eddumelendez](https://redirect.github.com/eddumelendez)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 2a3211d21f7b..fff3c7dc869f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 2.0.1 + 2.0.2 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index a324b7e7979f..e80416d7262c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 2.0.1 + 2.0.2 import pom From 1045ac8bf8ae225a5e344056373680d6cf06cdc0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 09:56:23 +0000 Subject: [PATCH 1869/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.79.0 (#2282) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.78.0` -> `2.79.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.79.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.79.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.78.0/2.79.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.78.0/2.79.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index ea83da528790..02a10809d8ca 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.78.0 + 2.79.0 test From fdcc65517248a096a99411893c401ce5fbbb7fb5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 09:58:27 +0000 Subject: [PATCH 1870/1979] deps: update dependency net.bytebuddy:byte-buddy-agent to v1.18.1 (#2280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [net.bytebuddy:byte-buddy-agent](https://bytebuddy.net) | `1.17.8` -> `1.18.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/net.bytebuddy:byte-buddy-agent/1.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/net.bytebuddy:byte-buddy-agent/1.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/net.bytebuddy:byte-buddy-agent/1.17.8/1.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/net.bytebuddy:byte-buddy-agent/1.17.8/1.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 1a53393d0721..4d370b3076aa 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -120,7 +120,7 @@ net.bytebuddy byte-buddy-agent - 1.17.8 + 1.18.1 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index fff3c7dc869f..250f2d5ebcf4 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy-agent - 1.17.8 + 1.18.1 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index e80416d7262c..03b3a04735fe 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -111,7 +111,7 @@ net.bytebuddy byte-buddy-agent - 1.17.8 + 1.18.1 test From efaac10473c6eeab7744a53c8d48aeb046fce86e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:02:15 +0000 Subject: [PATCH 1871/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.56.0 (#2278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.opentelemetry:opentelemetry-bom](https://redirect.github.com/open-telemetry/opentelemetry-java) | `1.55.0` -> `1.56.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.opentelemetry:opentelemetry-bom/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.opentelemetry:opentelemetry-bom/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.opentelemetry:opentelemetry-bom/1.55.0/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.opentelemetry:opentelemetry-bom/1.55.0/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    open-telemetry/opentelemetry-java (io.opentelemetry:opentelemetry-bom) ### [`v1.56.0`](https://redirect.github.com/open-telemetry/opentelemetry-java/blob/HEAD/CHANGELOG.md#Version-1560-2025-11-07) ##### API ##### Incubator - Support ExtendedOpenTelemetry in GlobalOpenTelemetry ([#​7799](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7799)) ##### SDK - Changes to MeterConfig, LoggerConfig, TracerConfig are guaranteed to be eventually visible ([#​7706](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7706)) ##### Metrics - Stabilize ExemplarFilter ([#​7768](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7768)) - Type specific exemplar reservoirs ([#​7758](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7758)) ##### Extensions - SDK incubator: Add incubator ComposableRuleBasedSampler ([#​7787](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7787)) - SDK incubator: Add incubator ComposableAnnotatingSampler ([#​7804](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7804)) - SDK incubator: Rename ComposableTraceIdRatioBased to ComposableProbability ([#​7786](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7786)) - Declarative config: **BREAKING** Remove component provider generic type ([#​7606](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7606)) - Declarative config: Add declarative config support for ExemplarFilter ([#​7769](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7769)) - Declarative config: Fix a few declarative configuration bugs ([#​7807](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7807)) ##### Project tooling - Move to oracle bare metal benchmark runner ([#​7740](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7740)) - Enable Develocity build scans ([#​7776](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7776)) - Document GPG signing key ([#​7783](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7783)) - Update build to use java 21 ([#​7784](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7784)) - Sync repository-settings.md documentation ([#​7791](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7791)) - Fix gradle deprecation warning ([#​7780](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7780)) - Small alignments of workflows across the 6 Java repos ([#​7806](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7806)) - Implement min java version gradle tooling from instrumentation repo ([#​7801](https://redirect.github.com/open-telemetry/opentelemetry-java/pull/7801))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index cd696f70cf95..2e53c85ce263 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.55.0 + 1.56.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4d370b3076aa..a20a1fb0c787 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.55.0 + 1.56.0 pom import From f6d5b772fa8665d2334a22da2d77efd047c37d4c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:04:09 +0000 Subject: [PATCH 1872/1979] deps: update dependency org.testcontainers:testcontainers to v2.0.2 (#2284) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 02a10809d8ca..baba67769c6d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 2.0.1 + 2.0.2 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index fa77d4400519..77bb20a5ce87 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 2.0.1 + 2.0.2 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index d530b54f09df..0b58ad4b5b3c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 2.0.1 + 2.0.2 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 2e53c85ce263..928e8be9e6c0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 2.0.1 + 2.0.2 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a20a1fb0c787..a1b4aa171b1e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -132,7 +132,7 @@ org.testcontainers testcontainers - 2.0.1 + 2.0.2 test From 7e716fc1c77e071ecaff2d19d4a72c7484e0a0f6 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:04:21 +0000 Subject: [PATCH 1873/1979] deps: update dependency commons-cli:commons-cli to v1.11.0 (#2283) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 77bb20a5ce87..6b9987ca40f3 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -47,7 +47,7 @@ commons-cli commons-cli - 1.10.0 + 1.11.0 com.google.cloud From 637b1549b951ff0cc4b939e6b3c2611f91277a8a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:04:33 +0000 Subject: [PATCH 1874/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.79.0 (#2281) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index baba67769c6d..273631bef485 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.78.0 + 2.79.0 test From 811766c211288cd40c37be7fc3e24b0980f6be6b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:04:45 +0000 Subject: [PATCH 1875/1979] deps: update dependency net.bytebuddy:byte-buddy to v1.18.1 (#2279) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index a1b4aa171b1e..46c8879165dc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy - 1.17.8 + 1.18.1 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 250f2d5ebcf4..6421c766a2cf 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -108,7 +108,7 @@ net.bytebuddy byte-buddy - 1.17.8 + 1.18.1 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 03b3a04735fe..2d50c8eb46d1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -105,7 +105,7 @@ net.bytebuddy byte-buddy - 1.17.8 + 1.18.1 test From 2768802536afa1fe8b62f88fb61e47cd17260cdb Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 14 Nov 2025 10:04:59 +0000 Subject: [PATCH 1876/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.54.1 (#2277) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index c4ee2b91a8a7..eb282a64ee40 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.53.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.54.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 0cf782fcc73b..df45eaecc6d1 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.53.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.54.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 15deac1d1b14..d110d2ae26e5 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.53.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.54.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 928626c44f6b..8e8342be5f4e 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.53.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.54.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 273631bef485..26bda9b7272d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.53.0 + 3.54.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6b9987ca40f3..1fbf4c702f9f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.53.0 + 3.54.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 0b58ad4b5b3c..75648f01a94a 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.53.0 + 3.54.1 From 5b355540b7a05f8352e6fe9037171fce27b7d801 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Nov 2025 07:26:41 +0000 Subject: [PATCH 1877/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.103.0 (#2292) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 26bda9b7272d..78a361886b1a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.1 + 6.103.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 928e8be9e6c0..22d1138251ef 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.1 + 6.103.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 46c8879165dc..b4256a0383a3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.1 + 6.103.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 6421c766a2cf..be975b6bcb85 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.102.1 + 6.103.0 import pom From 4023903c903497ffa7adad2ca706fa44c5ffd331 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Nov 2025 07:26:58 +0000 Subject: [PATCH 1878/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.103.0 (#2291) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index be975b6bcb85..d48edf9ef48b 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.102.1 + 6.103.0 test-jar test From 0448ac900fc53f8379d63324f7e91b3edd61b527 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Nov 2025 07:27:18 +0000 Subject: [PATCH 1879/1979] deps: update dependency org.apache.commons:commons-lang3 to v3.20.0 (#2290) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 1fbf4c702f9f..52b73e145f2a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -62,7 +62,7 @@ org.apache.commons commons-lang3 - 3.19.0 + 3.20.0 com.fasterxml.jackson.core From a7c1483bbf3466a57d877b9445454eb56034c86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 18 Nov 2025 09:09:32 +0100 Subject: [PATCH 1880/1979] feat: add unknownLength connection property (#2286) Adds an `unknownLength` connection property that can be used to configure the length that the JDBC driver should return as the data type / column length when this is not known. Spanner does not return the (maximum) length of a column in ResultSetMetadata. This means that the JDBC driver does not know what the length is of the various columns in query results. The value of `unknownLength` will be returned when the getPrecision and getColumnDisplaySize methods of ResultSetMetaData are called. This connection property aligns with the same connection parameter in the PostgreSQL JDBC driver: https://jdbc.postgresql.org/documentation/use/#connection-parameters --- .../documentation/connection_properties.md | 8 +++-- .../cloud/spanner/jdbc/JdbcConnection.java | 6 ++++ .../spanner/jdbc/JdbcResultSetMetaData.java | 35 +++++++++++-------- .../jdbc/JdbcResultSetMetaDataTest.java | 6 ++-- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index c0cd13861cf2..3e0f5efe3240 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -13,11 +13,12 @@ The 'Context' value indicates whether the property can only be set when a connec | autocommit_dml_mode | Determines the transaction type that is used to execute DML statements when the connection is in auto-commit mode. | TRANSACTIONAL | TRANSACTIONAL, PARTITIONED_NON_ATOMIC, TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC, null | USER | | autoconfigemulator | Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). The instance and database in the connection string will automatically be created if these do not yet exist on the emulator. Add dialect=postgresql to the connection string to make sure that the database that is created uses the PostgreSQL dialect. | false | true, false | STARTUP | | autopartitionmode | Execute all queries on this connection as partitioned queries. Executing a query that cannot be partitioned will fail. Executing a query in a read/write transaction will also fail. | false | true, false | USER | +| batch_dml_update_count | The update count that is returned for DML statements that are executed in an explicit DML batch. The default is -1 | -1 | | USER | | channelprovider | The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider. | | | STARTUP | | clientcertificate | Specifies the file path to the client certificate required for establishing an mTLS connection. | | | STARTUP | | clientkey | Specifies the file path to the client private key required for establishing an mTLS connection. | | | STARTUP | | connection_state_type | The type of connection state to use for this connection. Can only be set at start up. If no value is set, then the database dialect default will be used, which is NON_TRANSACTIONAL for GoogleSQL and TRANSACTIONAL for PostgreSQL. | | TRANSACTIONAL, NON_TRANSACTIONAL | STARTUP | -| credentials | The location of the credentials file to use for this connection. If neither this property or encoded credentials are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | +| credentials | The location of the credentials file to use for this connection. If neither this property or encoded credentials are set, the connection will use the default Google Cloud credentials for the runtime environment. WARNING: Using this property without proper validation can expose the application to security risks. It is intended for use with credentials from a trusted source only, as it could otherwise allow end-users to supply arbitrary credentials. For more information, seehttps://cloud.google.com/docs/authentication/client-libraries#external-credentials | | | STARTUP | | credentialsprovider | The class name of the com.google.api.gax.core.CredentialsProvider implementation that should be used to obtain credentials for connections. | | | STARTUP | | databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | | databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | true, false | USER | @@ -31,8 +32,9 @@ The 'Context' value indicates whether the property can only be set when a connec | enabledirectaccess | Configure the connection to try to connect to Spanner using DirectPath (true/false). The client will try to connect to Spanner using a direct Google network connection. DirectPath will work only if the client is trying to establish a connection from a Google Cloud VM. Otherwise it will automatically fallback to the standard network path. NOTE: The default for this property is currently false, but this could be changed in the future. | | true, false | STARTUP | | enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | true, false | STARTUP | | enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | true, false | STARTUP | -| encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. | | | STARTUP | +| encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. WARNING: Enabling this property without proper validation can expose the application to security risks. It is intended for use with credentials from a trusted source only, as it could otherwise allow end-users to supply arbitrary credentials. For more information, seehttps://cloud.google.com/docs/authentication/client-libraries#external-credentials | | | STARTUP | | endpoint | The endpoint that the JDBC driver should connect to. The default is the default Spanner production endpoint when autoConfigEmulator=false, and the default Spanner emulator endpoint (localhost:9010) when autoConfigEmulator=true. This property takes precedence over any host name at the start of the connection URL. | | | STARTUP | +| grpc_interceptor_provider | The class name of a com.google.api.gax.grpc.GrpcInterceptorProvider implementation that should be used to provide interceptors for the underlying Spanner client. This is a guarded property that can only be set if the Java System Property ENABLE_GRPC_INTERCEPTOR_PROVIDER has been set to true. This property should only be set to true on systems where an untrusted user cannot modify the connection URL, as using this property will dynamically invoke the constructor of the class specified. This means that any user that can modify the connection URL, can also dynamically invoke code on the host where the application is running. | | | STARTUP | | isexperimentalhost | Set this value to true for communication with a Experimental Host. | false | true, false | STARTUP | | keeptransactionalive | Enabling this option will trigger the connection to keep read/write transactions alive by executing a SELECT 1 query once every 10 seconds if no other statements are being executed. This option should be used with caution, as it can keep transactions alive and hold on to locks longer than intended. This option should typically be used for CLI-type application that might wait for user input for a longer period of time. | false | true, false | USER | | lenient | Silently ignore unknown properties in the connection string/properties (true/false) | false | true, false | STARTUP | @@ -53,11 +55,13 @@ The 'Context' value indicates whether the property can only be set when a connec | routetoleader | Should read/write transactions and partitioned DML be routed to leader region (true/false) | true | true, false | STARTUP | | rpcpriority | Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH. | | LOW, MEDIUM, HIGH, UNSPECIFIED, null | USER | | savepoint_support | Determines the behavior of the connection when savepoints are used. | FAIL_AFTER_ROLLBACK | ENABLED, FAIL_AFTER_ROLLBACK, DISABLED | USER | +| statement_timeout | Adds a timeout to all statements executed on this connection. This property is only used when a statement timeout is specified. | | | USER | | tracing_prefix | The prefix that will be prepended to all OpenTelemetry traces that are generated by a Connection. | CloudSpanner | | STARTUP | | trackconnectionleaks | Capture the call stack of the thread that created a connection. This will pre-create a LeakedConnectionException already when a connection is created. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedConnectionException will only be created when an actual connection leak is detected. The stack trace of the exception will in that case not contain the call stack of when the connection was created. | true | true, false | STARTUP | | tracksessionleaks | Capture the call stack of the thread that checked out a session of the session pool. This will pre-create a LeakedSessionException already when a session is checked out. This can be disabled, for example if a monitoring system logs the pre-created exception. If disabled, the LeakedSessionException will only be created when an actual session leak is detected. The stack trace of the exception will in that case not contain the call stack of when the session was checked out. | true | true, false | STARTUP | | transaction_timeout | Timeout for read/write transactions. | | | USER | | universedomain | Configure the connection to try to connect to Spanner using a different partner Google Universe than GDU (googleapis.com). | googleapis.com | | STARTUP | +| unknownlength | Spanner does not return the length of the selected columns in query results. When returning meta-data about these columns through functions like ResultSetMetaData.getColumnDisplaySize and ResultSetMetaData.getPrecision, we must provide a value. Various client tools and applications have different ideas about what they would like to see. This property specifies the length to return for types of unknown length. | 50 | | USER | | useautosavepointsforemulator | Automatically creates savepoints for each statement in a read/write transaction when using the Emulator. This is no longer needed when using Emulator version 1.5.23 or higher. | false | true, false | STARTUP | | useplaintext | Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator. | false | true, false | STARTUP | | useragent | The custom user-agent property name to use when communicating with Cloud Spanner. This property is intended for internal library usage, and should not be set by applications. | | | STARTUP | diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java index e603c29ac2fb..8041e8d68e3a 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java @@ -29,6 +29,7 @@ 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.ConnectionProperties; import com.google.cloud.spanner.connection.SavepointSupport; import com.google.cloud.spanner.connection.TransactionMode; import com.google.common.annotations.VisibleForTesting; @@ -236,6 +237,11 @@ public String getOptimizerVersion() throws SQLException { return getSpannerConnection().getOptimizerVersion(); } + /** Returns the value that should be returned for column types with an unknown length. */ + int getColumnTypeUnknownLength() { + return getSpannerConnection().getConnectionPropertyValue(ConnectionProperties.UNKNOWN_LENGTH); + } + @Override public boolean isInTransaction() throws SQLException { checkClosed(); diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index ff1ec2e2e488..f582ce45e58d 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -17,7 +17,9 @@ package com.google.cloud.spanner.jdbc; import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.connection.ConnectionProperties; import com.google.common.base.Preconditions; +import java.sql.Connection; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; @@ -25,12 +27,6 @@ /** Implementation of {@link ResultSetMetaData} for Cloud Spanner */ class JdbcResultSetMetaData extends AbstractJdbcWrapper implements ResultSetMetaData { - /** - * The default column display size for columns with a data type of variable size that is used when - * the actual column size is not known. - */ - private static final int DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS = 50; - private final ResultSet spannerResultSet; private final Statement statement; @@ -83,16 +79,15 @@ public boolean isSigned(int column) { } @Override - public int getColumnDisplaySize(int column) { + public int getColumnDisplaySize(int column) throws SQLException { int colType = getColumnType(column); switch (colType) { case Types.ARRAY: - return DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS; + return getUnknownLength(); case Types.BOOLEAN: return 5; case Types.BINARY: - int binaryLength = getPrecision(column); - return binaryLength == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : binaryLength; + return getPrecision(column); case Types.DATE: return 10; case Types.REAL: @@ -105,8 +100,7 @@ public int getColumnDisplaySize(int column) { case Types.NUMERIC: return 14; case Types.NVARCHAR: - int length = getPrecision(column); - return length == 0 ? DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS : length; + return getPrecision(column); case Types.TIMESTAMP: return 16; default: @@ -130,7 +124,7 @@ public String getSchemaName(int column) throws SQLException { } @Override - public int getPrecision(int column) { + public int getPrecision(int column) throws SQLException { int colType = getColumnType(column); switch (colType) { case Types.BOOLEAN: @@ -153,9 +147,20 @@ public int getPrecision(int column) { // For column types with variable size, such as text columns, we should return the length // in characters. We could try to fetch it from INFORMATION_SCHEMA, but that would mean // parsing the SQL statement client side in order to figure out which column it actually - // is. For now we just return the default column display size. - return DEFAULT_COL_DISPLAY_SIZE_FOR_VARIABLE_LENGTH_COLS; + // is. Instead, we return a configurable fixed length. This is also consistent with for + // example the PostgreSQL JDBC driver. See the 'unknownLength' connection property: + // https://jdbc.postgresql.org/documentation/use/#connection-parameters + return getUnknownLength(); + } + } + + private int getUnknownLength() throws SQLException { + Connection connection = statement.getConnection(); + if (connection instanceof JdbcConnection) { + JdbcConnection jdbcConnection = (JdbcConnection) connection; + return jdbcConnection.getColumnTypeUnknownLength(); } + return ConnectionProperties.UNKNOWN_LENGTH.getDefaultValue(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java index 53b58dcc170f..36996c801850 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -362,7 +362,7 @@ public void testIsSigned() { } @Test - public void testGetColumnDisplaySize() { + public void testGetColumnDisplaySize() throws SQLException { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals( "Wrong column display size for " + TEST_COLUMNS.get(i - 1).type, @@ -371,7 +371,7 @@ public void testGetColumnDisplaySize() { } } - private int getDefaultDisplaySize(Type type, int column) { + private int getDefaultDisplaySize(Type type, int column) throws SQLException { Preconditions.checkNotNull(type); switch (type.getCode()) { case BOOL: @@ -425,7 +425,7 @@ public void testGetSchemaName() throws SQLException { } @Test - public void testGetPrecision() { + public void testGetPrecision() throws SQLException { for (int i = 1; i <= TEST_COLUMNS.size(); i++) { assertEquals( "Wrong precision for type " + TEST_COLUMNS.get(i - 1).type, From 5216ff70bcd7189dc9dc4d50b86959cd420bde0f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Nov 2025 08:09:53 +0000 Subject: [PATCH 1881/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.80.0 (#2289) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 78a361886b1a..835c90127c84 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -216,7 +216,7 @@ com.google.cloud google-cloud-trace - 2.79.0 + 2.80.0 test From f69f1daf61b83fc2b150dfba9ee220c40d00471a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 18 Nov 2025 08:10:16 +0000 Subject: [PATCH 1882/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.80.0 (#2288) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 835c90127c84..eabf608d986b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -222,7 +222,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.79.0 + 2.80.0 test From 18783fc33a3f05190af1fbcbab88918ebb960449 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:16:46 +0100 Subject: [PATCH 1883/1979] chore(main): release 2.34.0 (#2276) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 26 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index f9253794c5e1..ddcb0c48e1f1 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [2.34.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.3...v2.34.0) (2025-11-18) + + +### Features + +* Add unknownLength connection property ([#2286](https://github.com/googleapis/java-spanner-jdbc/issues/2286)) ([6aceb64](https://github.com/googleapis/java-spanner-jdbc/commit/6aceb6487e46beb45277dee230a66b09e4de1671)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.20.1 ([#2275](https://github.com/googleapis/java-spanner-jdbc/issues/2275)) ([559cdee](https://github.com/googleapis/java-spanner-jdbc/commit/559cdee7633ae508f857890770f173ac2f18d2ca)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.79.0 ([#2281](https://github.com/googleapis/java-spanner-jdbc/issues/2281)) ([3a15afa](https://github.com/googleapis/java-spanner-jdbc/commit/3a15afa13b1583e0941a909ac09acac49c532a36)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.80.0 ([#2288](https://github.com/googleapis/java-spanner-jdbc/issues/2288)) ([b859d8e](https://github.com/googleapis/java-spanner-jdbc/commit/b859d8e07ae7d9e3f71d431cc16cfa1e4b9fb2e4)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.103.0 ([#2291](https://github.com/googleapis/java-spanner-jdbc/issues/2291)) ([226850e](https://github.com/googleapis/java-spanner-jdbc/commit/226850edd1ba3d85a762872abcb70bad836b3ca1)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.103.0 ([#2292](https://github.com/googleapis/java-spanner-jdbc/issues/2292)) ([1213da6](https://github.com/googleapis/java-spanner-jdbc/commit/1213da65f745b88babe6dc2d3805534b47b34bd6)) +* Update dependency com.google.cloud:google-cloud-trace to v2.79.0 ([#2282](https://github.com/googleapis/java-spanner-jdbc/issues/2282)) ([ebbb0de](https://github.com/googleapis/java-spanner-jdbc/commit/ebbb0deb3e7c1e7f564a9a1a792ecba336d5fcb0)) +* Update dependency com.google.cloud:google-cloud-trace to v2.80.0 ([#2289](https://github.com/googleapis/java-spanner-jdbc/issues/2289)) ([d64f6c6](https://github.com/googleapis/java-spanner-jdbc/commit/d64f6c6adb2f17b53acda3006aff9dc2aabb4dfc)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.54.1 ([#2277](https://github.com/googleapis/java-spanner-jdbc/issues/2277)) ([7a48db6](https://github.com/googleapis/java-spanner-jdbc/commit/7a48db68cb769246b9307e39e37d8af12641a0fb)) +* Update dependency commons-cli:commons-cli to v1.11.0 ([#2283](https://github.com/googleapis/java-spanner-jdbc/issues/2283)) ([7582363](https://github.com/googleapis/java-spanner-jdbc/commit/75823638436e446f1e0a7904dd485b2f84b16f3d)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.56.0 ([#2278](https://github.com/googleapis/java-spanner-jdbc/issues/2278)) ([1fd49aa](https://github.com/googleapis/java-spanner-jdbc/commit/1fd49aa604a395032df675f5f9589eed9ea901c2)) +* Update dependency net.bytebuddy:byte-buddy to v1.18.1 ([#2279](https://github.com/googleapis/java-spanner-jdbc/issues/2279)) ([fa83919](https://github.com/googleapis/java-spanner-jdbc/commit/fa83919382619c3cb6abc567e7d6753a2e2ead33)) +* Update dependency net.bytebuddy:byte-buddy-agent to v1.18.1 ([#2280](https://github.com/googleapis/java-spanner-jdbc/issues/2280)) ([4237635](https://github.com/googleapis/java-spanner-jdbc/commit/4237635cc33784cecf9aa62d757fbf3fd4d1702d)) +* Update dependency org.apache.commons:commons-lang3 to v3.20.0 ([#2290](https://github.com/googleapis/java-spanner-jdbc/issues/2290)) ([eacbecb](https://github.com/googleapis/java-spanner-jdbc/commit/eacbecb7e5340d34d2de1208280dc9432144da26)) +* Update dependency org.testcontainers:testcontainers to v2.0.2 ([#2284](https://github.com/googleapis/java-spanner-jdbc/issues/2284)) ([092f5a1](https://github.com/googleapis/java-spanner-jdbc/commit/092f5a129761f0c8c9d8207c611232a086328896)) +* Update dependency org.testcontainers:testcontainers-bom to v2.0.2 ([#2285](https://github.com/googleapis/java-spanner-jdbc/issues/2285)) ([360a9fb](https://github.com/googleapis/java-spanner-jdbc/commit/360a9fbe0077abe072f2834823c9f208e2325fcf)) + ## [2.33.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.2...v2.33.3) (2025-10-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index d6bac06ef3e2..c43a63e3e8b0 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.33.3 + 2.34.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.33.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.34.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.33.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.34.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index eabf608d986b..6495c5601d1e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.33.4-SNAPSHOT + 2.34.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 5fa54aaacd82..0eaafc475be0 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.4-SNAPSHOT + 2.34.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 1ffb9187ee5b..5bc601e206fe 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.33.3:2.33.4-SNAPSHOT +google-cloud-spanner-jdbc:2.34.0:2.34.0 From 68ace0613f24a9ccfa3da54b187cc6e4add5eb2f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 11:24:20 +0100 Subject: [PATCH 1884/1979] chore(main): release 2.34.1-SNAPSHOT (#2293) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6495c5601d1e..7b8042371b85 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.34.0 + 2.34.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 0eaafc475be0..9e28d67dee7c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.0 + 2.34.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 5bc601e206fe..e012595c7c89 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.34.0:2.34.0 +google-cloud-spanner-jdbc:2.34.0:2.34.1-SNAPSHOT From beba91c5efc89362aa1f3f9418b17e744c90b6cf Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:29:12 +0000 Subject: [PATCH 1885/1979] deps: update dependency org.springframework.boot:spring-boot to v4 (#2300) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 52b73e145f2a..5dba65aa975a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 3.5.7 + 4.0.0 test From 1d0b5d40cc41d903cad3c1c63c473b86143665a3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:29:32 +0000 Subject: [PATCH 1886/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4 (#2301) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 22d1138251ef..28db825dff39 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.7 + 4.0.0 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index b4256a0383a3..adc3c61f490d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 3.5.7 + 4.0.0 From b89fbc804a8b675e47ecdc566ee49df3427beb19 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:30:45 +0000 Subject: [PATCH 1887/1979] deps: update actions/checkout action to v6 (#2299) --- .../.github/workflows/integration-tests-against-emulator.yaml | 2 +- java-spanner-jdbc/.github/workflows/quickperf.yaml | 2 +- java-spanner-jdbc/.github/workflows/sample-tests.yml | 2 +- .../.github/workflows/spring-data-jdbc-sample.yaml | 2 +- .../.github/workflows/spring-data-mybatis-sample.yaml | 2 +- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml index 7669c2806927..700845182512 100644 --- a/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml +++ b/java-spanner-jdbc/.github/workflows/integration-tests-against-emulator.yaml @@ -16,7 +16,7 @@ jobs: - 9020:9020 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/quickperf.yaml b/java-spanner-jdbc/.github/workflows/quickperf.yaml index aa0bf2b547d4..13d55b664d14 100644 --- a/java-spanner-jdbc/.github/workflows/quickperf.yaml +++ b/java-spanner-jdbc/.github/workflows/quickperf.yaml @@ -20,7 +20,7 @@ jobs: quickperf: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/sample-tests.yml b/java-spanner-jdbc/.github/workflows/sample-tests.yml index 056ef15cc20c..4074cabfa6f2 100644 --- a/java-spanner-jdbc/.github/workflows/sample-tests.yml +++ b/java-spanner-jdbc/.github/workflows/sample-tests.yml @@ -20,7 +20,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml index 07b41e4ec7fb..d229347ca57c 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-jdbc-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-jdbc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml index 84dc6e521e4d..f44d1388c60a 100644 --- a/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml +++ b/java-spanner-jdbc/.github/workflows/spring-data-mybatis-sample.yaml @@ -20,7 +20,7 @@ jobs: spring-data-mybatis: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index eb282a64ee40..68563931f830 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -5,7 +5,7 @@ jobs: unmanaged_dependency_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-java@v5 with: distribution: temurin From 0d260c11355a5d2c06bc2e26b2e722c4155e3fce Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:31:32 +0000 Subject: [PATCH 1888/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.72.0 (#2295) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 5dba65aa975a..2dc418ca3f5a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 75648f01a94a..f07e72d1bf7c 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 28db825dff39..6f393bd9f84d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index adc3c61f490d..cf92e5121451 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index d48edf9ef48b..4e0441e89196 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 2d50c8eb46d1..0cbc6ddb998a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.71.0 + 26.72.0 import pom From 6427be04eb76abf557456e94d0758ed31900a7b4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:32:26 +0000 Subject: [PATCH 1889/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.34.0 (#2294) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 8fb4480bb98e..1d139b2cf1ce 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.33.3 + 2.34.0 From 58d067076d16f50573e53991e25fc5f3935d2a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Fri, 28 Nov 2025 11:42:27 +0100 Subject: [PATCH 1890/1979] fix: cast double Inf and NaN to float (#2304) Casting a FLOAT64 value containing either Inf or NaN to a Java float failed, while Java itself allows the same conversion from a double Inf or NaN to the corresponding float Inf or NaN. Fixes #2256 --- .../cloud/spanner/jdbc/AbstractJdbcWrapper.java | 2 +- .../cloud/spanner/jdbc/AbstractJdbcWrapperTest.java | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index cd66cb38c17b..022a9a5daca3 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -291,7 +291,7 @@ static int checkedCastToInt(BigInteger val) throws SQLException { /** Cast value and throw {@link SQLException} if out-of-range. */ static float checkedCastToFloat(double val) throws SQLException { - if (val > Float.MAX_VALUE || val < -Float.MAX_VALUE) { + if (Double.isFinite(val) && (val > Float.MAX_VALUE || val < -Float.MAX_VALUE)) { throw JdbcSqlExceptionFactory.of( String.format(OUT_OF_RANGE_MSG, "float", val), com.google.rpc.Code.OUT_OF_RANGE); } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index f8473f638642..702477f45401 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -256,7 +256,7 @@ public void testCheckedCastFromBigIntegerToLong() { } @Test - public void testCheckedCastToFloat() { + public void testCheckedCastToFloat() throws SQLException { final CheckedCastChecker checker = new CheckedCastChecker<>(AbstractJdbcWrapper::checkedCastToFloat); assertThat(checker.cast(0D)).isTrue(); @@ -268,6 +268,16 @@ public void testCheckedCastToFloat() { assertThat(checker.cast((double) Float.MIN_VALUE)).isTrue(); assertThat(checker.cast(-Float.MAX_VALUE * 2d)).isFalse(); assertThat(checker.cast(-Double.MAX_VALUE)).isFalse(); + + assertEquals( + Float.POSITIVE_INFINITY, + AbstractJdbcWrapper.checkedCastToFloat(Double.POSITIVE_INFINITY), + 0.0d); + assertEquals( + Float.NEGATIVE_INFINITY, + AbstractJdbcWrapper.checkedCastToFloat(Double.NEGATIVE_INFINITY), + 0.0d); + assertEquals(Float.NaN, AbstractJdbcWrapper.checkedCastToFloat(Double.NaN), 0.0d); } @Test From 5a9c025fae0904ec4870c1db5b0dc4cfb63b08fc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 28 Nov 2025 10:58:26 +0000 Subject: [PATCH 1891/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.8 (#2298) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://redirect.github.com/spring-projects/spring-boot)) | `3.5.7` -> `3.5.8` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.5.8?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.5.8?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.5.7/3.5.8?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.5.7/3.5.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.5.8`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.7...v3.5.8) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.7...v3.5.8)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 4e0441e89196..8e0f26b490a0 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.7 + 3.5.8 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 0cbc6ddb998a..afb4717a97f6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.7 + 3.5.8 From d00928b329abf974663438154e3daca09aa0c823 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Thu, 4 Dec 2025 15:53:53 -0500 Subject: [PATCH 1892/1979] chore: add release-please config for protobuf-4.x (#2311) --- java-spanner-jdbc/.github/release-please.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index bd201477430d..8c51cd7d67e1 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -6,4 +6,9 @@ branches: releaseType: java-yoshi bumpMinorPreMajor: true handleGHRelease: true +- branch: protobuf-4.x-rc + releaseType: java-yoshi + bumpMinorPreMajor: true + handleGHRelease: true + manifest: true extraFiles: ["README.md"] From 37ce0f72d5bc38461b2002ec2a26311d92b7dc8c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 07:52:28 +0000 Subject: [PATCH 1893/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.54.2 (#2322) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 68563931f830..1aded26889a2 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.54.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.54.2 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index df45eaecc6d1..38cc2a00c39c 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.54.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.54.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index d110d2ae26e5..952e958134e8 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.54.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.54.2" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 8e8342be5f4e..f673877b3cfb 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.54.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.54.2" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7b8042371b85..1795d51ad2bd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.54.1 + 3.54.2 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 2dc418ca3f5a..7c76ba020a55 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.54.1 + 3.54.2 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f07e72d1bf7c..a8cfbaec3679 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.54.1 + 3.54.2 From ba29e835248385bb5a7ad2ceec12eca8cdd7792d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 07:54:59 +0000 Subject: [PATCH 1894/1979] deps: update dependency net.bytebuddy:byte-buddy-agent to v1.18.2 (#2307) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index cf92e5121451..8b7ef34e3fb4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -120,7 +120,7 @@ net.bytebuddy byte-buddy-agent - 1.18.1 + 1.18.2 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 8e0f26b490a0..9eb46af9f874 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy-agent - 1.18.1 + 1.18.2 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index afb4717a97f6..43e7a9378d96 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -111,7 +111,7 @@ net.bytebuddy byte-buddy-agent - 1.18.1 + 1.18.2 test From 28b47edec46a220ccb1b5759c58d152c94271156 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 07:55:26 +0000 Subject: [PATCH 1895/1979] deps: update dependency net.bytebuddy:byte-buddy to v1.18.2 (#2306) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 8b7ef34e3fb4..3397db8aa484 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -114,7 +114,7 @@ net.bytebuddy byte-buddy - 1.18.1 + 1.18.2 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 9eb46af9f874..eff62fef1e7a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -108,7 +108,7 @@ net.bytebuddy byte-buddy - 1.18.1 + 1.18.2 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 43e7a9378d96..9a95563d1e8a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -105,7 +105,7 @@ net.bytebuddy byte-buddy - 1.18.1 + 1.18.2 test From 6e41a1ec3a422a0f76fd864a15163a18fb9d03c3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 08:04:10 +0000 Subject: [PATCH 1896/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.57.0 (#2316) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 6f393bd9f84d..c21ab5bb5afe 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.56.0 + 1.57.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 3397db8aa484..bb132d1b2db8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -44,7 +44,7 @@ io.opentelemetry opentelemetry-bom - 1.56.0 + 1.57.0 pom import From bc371a893801853723ab0c12245d69638044c733 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 08:04:22 +0000 Subject: [PATCH 1897/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.104.0 (#2313) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 1795d51ad2bd..744c5dedf9b2 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.103.0 + 6.104.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index c21ab5bb5afe..ce4b65991ff1 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.103.0 + 6.104.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index bb132d1b2db8..05aa58467ef8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.103.0 + 6.104.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index eff62fef1e7a..126d1f7a00dc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.103.0 + 6.104.0 import pom From 3f812434cddebdabbf8403807ad284fa40eeee25 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 Dec 2025 08:04:37 +0000 Subject: [PATCH 1898/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.104.0 (#2312) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 126d1f7a00dc..9855e9f095ed 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.103.0 + 6.104.0 test-jar test From aaa6683885736214612949445934b6de499667b1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Dec 2025 18:19:14 +0000 Subject: [PATCH 1899/1979] deps: update dependency org.testcontainers:testcontainers to v2.0.3 (#2323) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 744c5dedf9b2..9a08db03f671 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -166,7 +166,7 @@ org.testcontainers testcontainers - 2.0.2 + 2.0.3 test diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 7c76ba020a55..3618b64613f9 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -73,7 +73,7 @@ org.testcontainers testcontainers - 2.0.2 + 2.0.3 test diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index a8cfbaec3679..12b2c88c8307 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -54,7 +54,7 @@ org.testcontainers testcontainers - 2.0.2 + 2.0.3 test diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index ce4b65991ff1..ec5de12fc2fe 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -90,7 +90,7 @@ org.testcontainers testcontainers - 2.0.2 + 2.0.3 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 05aa58467ef8..3db0c1aa3b17 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -132,7 +132,7 @@ org.testcontainers testcontainers - 2.0.2 + 2.0.3 test From 92dc39111a365d56969d5cad7856f8a867c8968b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Dec 2025 18:19:36 +0000 Subject: [PATCH 1900/1979] deps: update dependency org.testcontainers:testcontainers-bom to v2.0.3 (#2324) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 9855e9f095ed..8eb642fe7350 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -49,7 +49,7 @@ org.testcontainers testcontainers-bom - 2.0.2 + 2.0.3 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 9a95563d1e8a..96cec67c1213 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -42,7 +42,7 @@ org.testcontainers testcontainers-bom - 2.0.2 + 2.0.3 import pom From 6b97652432c42887241a94e649331d77c8dccfbc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Dec 2025 19:12:27 +0000 Subject: [PATCH 1901/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.105.0 (#2325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner](https://redirect.github.com/googleapis/java-spanner) | `6.104.0` -> `6.105.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner/6.105.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner/6.105.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner/6.104.0/6.105.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner/6.104.0/6.105.0?slim=true) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner) ### [`v6.105.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61050-2025-12-16) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.104.0...v6.105.0) ##### Features - Add support of dynamic channel pooling ([#​4265](https://redirect.github.com/googleapis/java-spanner/issues/4265)) ([923a14a](https://redirect.github.com/googleapis/java-spanner/commit/923a14aad99ff6fc91868f02d657145dd0f31c18)) - Include RequestID in requests and errors ([#​4263](https://redirect.github.com/googleapis/java-spanner/issues/4263)) ([afd7d6b](https://redirect.github.com/googleapis/java-spanner/commit/afd7d6b008f13d7a4d1a3b7f924122bd41d14b59)) - Make grpc-gcp default enabled ([#​4239](https://redirect.github.com/googleapis/java-spanner/issues/4239)) ([bb82f9e](https://redirect.github.com/googleapis/java-spanner/commit/bb82f9e55c40cac29b090e54be780c2e42545ee1)) ##### Bug Fixes - Refine connecitivity metrics to capture RPCs with no response he… ([#​4252](https://redirect.github.com/googleapis/java-spanner/issues/4252)) ([7b49412](https://redirect.github.com/googleapis/java-spanner/commit/7b4941221969f48d077ff459214c7d1e65ef843c)) - Retry as PDML dit not retry Resource limit exceeded ([#​4258](https://redirect.github.com/googleapis/java-spanner/issues/4258)) ([c735d42](https://redirect.github.com/googleapis/java-spanner/commit/c735d42875092b0d1482fe641b99645f288cdf4f)), closes [#​4253](https://redirect.github.com/googleapis/java-spanner/issues/4253) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.54.2 ([#​4261](https://redirect.github.com/googleapis/java-spanner/issues/4261)) ([61dfd62](https://redirect.github.com/googleapis/java-spanner/commit/61dfd620637da6ef76b699edbad1095c26b81950)) - Update googleapis/sdk-platform-java action to v2.64.2 ([#​4262](https://redirect.github.com/googleapis/java-spanner/issues/4262)) ([f9505a9](https://redirect.github.com/googleapis/java-spanner/commit/f9505a97bdd9f6da7dd5ab1b60b47f7ed0a70402))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 8eb642fe7350..fdadc5004cd5 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -94,7 +94,7 @@ com.google.cloud google-cloud-spanner - 6.104.0 + 6.105.0 test-jar test From 3122d1c2c758cfa7565ba4a937f27fcfe4589863 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 16 Dec 2025 20:10:32 +0000 Subject: [PATCH 1902/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.105.0 (#2326) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-bom](https://redirect.github.com/googleapis/java-spanner) | `6.104.0` -> `6.105.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.105.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-bom/6.105.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-bom/6.104.0/6.105.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-bom/6.104.0/6.105.0?slim=true) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.105.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61050-2025-12-16) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.104.0...v6.105.0) ##### Features - Add support of dynamic channel pooling ([#​4265](https://redirect.github.com/googleapis/java-spanner/issues/4265)) ([923a14a](https://redirect.github.com/googleapis/java-spanner/commit/923a14aad99ff6fc91868f02d657145dd0f31c18)) - Include RequestID in requests and errors ([#​4263](https://redirect.github.com/googleapis/java-spanner/issues/4263)) ([afd7d6b](https://redirect.github.com/googleapis/java-spanner/commit/afd7d6b008f13d7a4d1a3b7f924122bd41d14b59)) - Make grpc-gcp default enabled ([#​4239](https://redirect.github.com/googleapis/java-spanner/issues/4239)) ([bb82f9e](https://redirect.github.com/googleapis/java-spanner/commit/bb82f9e55c40cac29b090e54be780c2e42545ee1)) ##### Bug Fixes - Refine connecitivity metrics to capture RPCs with no response he… ([#​4252](https://redirect.github.com/googleapis/java-spanner/issues/4252)) ([7b49412](https://redirect.github.com/googleapis/java-spanner/commit/7b4941221969f48d077ff459214c7d1e65ef843c)) - Retry as PDML dit not retry Resource limit exceeded ([#​4258](https://redirect.github.com/googleapis/java-spanner/issues/4258)) ([c735d42](https://redirect.github.com/googleapis/java-spanner/commit/c735d42875092b0d1482fe641b99645f288cdf4f)), closes [#​4253](https://redirect.github.com/googleapis/java-spanner/issues/4253) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.54.2 ([#​4261](https://redirect.github.com/googleapis/java-spanner/issues/4261)) ([61dfd62](https://redirect.github.com/googleapis/java-spanner/commit/61dfd620637da6ef76b699edbad1095c26b81950)) - Update googleapis/sdk-platform-java action to v2.64.2 ([#​4262](https://redirect.github.com/googleapis/java-spanner/issues/4262)) ([f9505a9](https://redirect.github.com/googleapis/java-spanner/commit/f9505a97bdd9f6da7dd5ab1b60b47f7ed0a70402))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 7 ++++++- .../samples/spring-data-jdbc/googlesql/pom.xml | 7 ++++++- .../samples/spring-data-jdbc/postgresql/pom.xml | 7 ++++++- .../cloud/spanner/sample/OpenTelemetryConfiguration.java | 2 -- .../samples/spring-data-mybatis/googlesql/pom.xml | 7 ++++++- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 9a08db03f671..756073fc250a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,10 +61,15 @@ com.google.cloud google-cloud-spanner-bom - 6.104.0 + 6.105.0 pom import + + com.google.cloud + grpc-gcp + 1.9.0 + com.google.cloud google-cloud-shared-dependencies diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index ec5de12fc2fe..a8c714ad522d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,10 +30,15 @@ com.google.cloud google-cloud-spanner-bom - 6.104.0 + 6.105.0 import pom + + com.google.cloud + grpc-gcp + 1.9.0 + com.google.cloud libraries-bom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 3db0c1aa3b17..bc60ad011718 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,10 +30,15 @@ com.google.cloud google-cloud-spanner-bom - 6.104.0 + 6.105.0 import pom + + com.google.cloud + grpc-gcp + 1.9.0 + com.google.cloud libraries-bom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java index f1e615290212..b833e48b7c50 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/src/main/java/com/google/cloud/spanner/sample/OpenTelemetryConfiguration.java @@ -36,8 +36,6 @@ import java.io.IOException; import java.util.concurrent.ThreadLocalRandom; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index fdadc5004cd5..8bd42c99c711 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,10 +35,15 @@ com.google.cloud google-cloud-spanner-bom - 6.104.0 + 6.105.0 import pom + + com.google.cloud + grpc-gcp + 1.9.0 + com.google.cloud libraries-bom From 3d96a2651f4cc6901522b792f271c10630a1b6d5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:44:26 +0000 Subject: [PATCH 1903/1979] chore(main): release 2.34.1 (#2305) :robot: I have created a release *beep* *boop* --- ## [2.34.1](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.34.0...v2.34.1) (2025-12-16) ### Bug Fixes * Cast double Inf and NaN to float ([#2304](https://togithub.com/googleapis/java-spanner-jdbc/issues/2304)) ([58d0670](https://togithub.com/googleapis/java-spanner-jdbc/commit/58d067076d16f50573e53991e25fc5f3935d2a19)), closes [#2256](https://togithub.com/googleapis/java-spanner-jdbc/issues/2256) ### Dependencies * Update actions/checkout action to v6 ([#2299](https://togithub.com/googleapis/java-spanner-jdbc/issues/2299)) ([b89fbc8](https://togithub.com/googleapis/java-spanner-jdbc/commit/b89fbc804a8b675e47ecdc566ee49df3427beb19)) * Update dependency com.google.cloud:google-cloud-spanner to v6.104.0 ([#2312](https://togithub.com/googleapis/java-spanner-jdbc/issues/2312)) ([3f81243](https://togithub.com/googleapis/java-spanner-jdbc/commit/3f812434cddebdabbf8403807ad284fa40eeee25)) * Update dependency com.google.cloud:google-cloud-spanner to v6.105.0 ([#2325](https://togithub.com/googleapis/java-spanner-jdbc/issues/2325)) ([6b97652](https://togithub.com/googleapis/java-spanner-jdbc/commit/6b97652432c42887241a94e649331d77c8dccfbc)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.104.0 ([#2313](https://togithub.com/googleapis/java-spanner-jdbc/issues/2313)) ([bc371a8](https://togithub.com/googleapis/java-spanner-jdbc/commit/bc371a893801853723ab0c12245d69638044c733)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.105.0 ([#2326](https://togithub.com/googleapis/java-spanner-jdbc/issues/2326)) ([3122d1c](https://togithub.com/googleapis/java-spanner-jdbc/commit/3122d1c2c758cfa7565ba4a937f27fcfe4589863)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.54.2 ([#2322](https://togithub.com/googleapis/java-spanner-jdbc/issues/2322)) ([37ce0f7](https://togithub.com/googleapis/java-spanner-jdbc/commit/37ce0f72d5bc38461b2002ec2a26311d92b7dc8c)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.57.0 ([#2316](https://togithub.com/googleapis/java-spanner-jdbc/issues/2316)) ([6e41a1e](https://togithub.com/googleapis/java-spanner-jdbc/commit/6e41a1ec3a422a0f76fd864a15163a18fb9d03c3)) * Update dependency net.bytebuddy:byte-buddy to v1.18.2 ([#2306](https://togithub.com/googleapis/java-spanner-jdbc/issues/2306)) ([28b47ed](https://togithub.com/googleapis/java-spanner-jdbc/commit/28b47edec46a220ccb1b5759c58d152c94271156)) * Update dependency net.bytebuddy:byte-buddy-agent to v1.18.2 ([#2307](https://togithub.com/googleapis/java-spanner-jdbc/issues/2307)) ([ba29e83](https://togithub.com/googleapis/java-spanner-jdbc/commit/ba29e835248385bb5a7ad2ceec12eca8cdd7792d)) * Update dependency org.springframework.boot:spring-boot to v4 ([#2300](https://togithub.com/googleapis/java-spanner-jdbc/issues/2300)) ([beba91c](https://togithub.com/googleapis/java-spanner-jdbc/commit/beba91c5efc89362aa1f3f9418b17e744c90b6cf)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4 ([#2301](https://togithub.com/googleapis/java-spanner-jdbc/issues/2301)) ([1d0b5d4](https://togithub.com/googleapis/java-spanner-jdbc/commit/1d0b5d40cc41d903cad3c1c63c473b86143665a3)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.8 ([#2298](https://togithub.com/googleapis/java-spanner-jdbc/issues/2298)) ([5a9c025](https://togithub.com/googleapis/java-spanner-jdbc/commit/5a9c025fae0904ec4870c1db5b0dc4cfb63b08fc)) * Update dependency org.testcontainers:testcontainers to v2.0.3 ([#2323](https://togithub.com/googleapis/java-spanner-jdbc/issues/2323)) ([aaa6683](https://togithub.com/googleapis/java-spanner-jdbc/commit/aaa6683885736214612949445934b6de499667b1)) * Update dependency org.testcontainers:testcontainers-bom to v2.0.3 ([#2324](https://togithub.com/googleapis/java-spanner-jdbc/issues/2324)) ([92dc391](https://togithub.com/googleapis/java-spanner-jdbc/commit/92dc39111a365d56969d5cad7856f8a867c8968b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 25 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index ddcb0c48e1f1..11ebcecf4155 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [2.34.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.34.0...v2.34.1) (2025-12-16) + + +### Bug Fixes + +* Cast double Inf and NaN to float ([#2304](https://github.com/googleapis/java-spanner-jdbc/issues/2304)) ([a947024](https://github.com/googleapis/java-spanner-jdbc/commit/a94702446aee20013157b45bf1d9c3938f0b6982)), closes [#2256](https://github.com/googleapis/java-spanner-jdbc/issues/2256) + + +### Dependencies + +* Update actions/checkout action to v6 ([#2299](https://github.com/googleapis/java-spanner-jdbc/issues/2299)) ([fbc8969](https://github.com/googleapis/java-spanner-jdbc/commit/fbc8969d66f4687ce91268309a862a0cbe0a114c)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.104.0 ([#2312](https://github.com/googleapis/java-spanner-jdbc/issues/2312)) ([930797b](https://github.com/googleapis/java-spanner-jdbc/commit/930797b71f30e458dee20679178ff3510fcba919)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.105.0 ([#2325](https://github.com/googleapis/java-spanner-jdbc/issues/2325)) ([34a9768](https://github.com/googleapis/java-spanner-jdbc/commit/34a9768b203c967f4191427a815b71e1a503de8f)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.104.0 ([#2313](https://github.com/googleapis/java-spanner-jdbc/issues/2313)) ([5250e2d](https://github.com/googleapis/java-spanner-jdbc/commit/5250e2d069179bdeb773e5e0a1f2a5defd411811)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.105.0 ([#2326](https://github.com/googleapis/java-spanner-jdbc/issues/2326)) ([8f3e6b7](https://github.com/googleapis/java-spanner-jdbc/commit/8f3e6b72baccc5ae8dd5ce3c55807bc889a7f208)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.54.2 ([#2322](https://github.com/googleapis/java-spanner-jdbc/issues/2322)) ([2faffb4](https://github.com/googleapis/java-spanner-jdbc/commit/2faffb46c71e4b44b42dbc4bfd5d70a3e55eb5f6)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.57.0 ([#2316](https://github.com/googleapis/java-spanner-jdbc/issues/2316)) ([77aab00](https://github.com/googleapis/java-spanner-jdbc/commit/77aab00ec385a7bfe61615b6b250c0b97a9a9f07)) +* Update dependency net.bytebuddy:byte-buddy to v1.18.2 ([#2306](https://github.com/googleapis/java-spanner-jdbc/issues/2306)) ([ba7430c](https://github.com/googleapis/java-spanner-jdbc/commit/ba7430cd229214487dfe4db208cb274d4662bf19)) +* Update dependency net.bytebuddy:byte-buddy-agent to v1.18.2 ([#2307](https://github.com/googleapis/java-spanner-jdbc/issues/2307)) ([86dc72b](https://github.com/googleapis/java-spanner-jdbc/commit/86dc72b0e1d7199b229474008cb68400458f233e)) +* Update dependency org.springframework.boot:spring-boot to v4 ([#2300](https://github.com/googleapis/java-spanner-jdbc/issues/2300)) ([a6dddf2](https://github.com/googleapis/java-spanner-jdbc/commit/a6dddf2aef2e9d35ec2bf26ea1a1586ab65e122a)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4 ([#2301](https://github.com/googleapis/java-spanner-jdbc/issues/2301)) ([92efa98](https://github.com/googleapis/java-spanner-jdbc/commit/92efa986a0880524a3d19685df0e08cf7815a69a)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.8 ([#2298](https://github.com/googleapis/java-spanner-jdbc/issues/2298)) ([5603846](https://github.com/googleapis/java-spanner-jdbc/commit/5603846fc004a0e31cbcf10bc246d477cd80d9dd)) +* Update dependency org.testcontainers:testcontainers to v2.0.3 ([#2323](https://github.com/googleapis/java-spanner-jdbc/issues/2323)) ([65302d4](https://github.com/googleapis/java-spanner-jdbc/commit/65302d44315548af3406853121e341523c89521c)) +* Update dependency org.testcontainers:testcontainers-bom to v2.0.3 ([#2324](https://github.com/googleapis/java-spanner-jdbc/issues/2324)) ([8e8b3a0](https://github.com/googleapis/java-spanner-jdbc/commit/8e8b3a0b4c613324a07609fa142330322e8eab95)) + ## [2.34.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.33.3...v2.34.0) (2025-11-18) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c43a63e3e8b0..c8b59f1ef9b1 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.34.0 + 2.34.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.34.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.34.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.34.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.34.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 756073fc250a..f12633460fa8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.34.1-SNAPSHOT + 2.34.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 9e28d67dee7c..14bd31d70c94 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.1-SNAPSHOT + 2.34.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e012595c7c89..f3b324ac5f05 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.34.0:2.34.1-SNAPSHOT +google-cloud-spanner-jdbc:2.34.1:2.34.1 From cb5db504250f06def640761c9602a482732cb801 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 21:24:27 +0000 Subject: [PATCH 1904/1979] chore(main): release 2.34.2-SNAPSHOT (#2328) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f12633460fa8..b10b4f77e89d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.34.1 + 2.34.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 14bd31d70c94..d80be289eabb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.1 + 2.34.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f3b324ac5f05..06f38cdc696f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.34.1:2.34.1 +google-cloud-spanner-jdbc:2.34.1:2.34.2-SNAPSHOT From e02d1a177d72a4985367cfc1a328ed39cfa717ef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 17 Dec 2025 07:55:57 +0000 Subject: [PATCH 1905/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.73.0 (#2334) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 3618b64613f9..eedc86494c54 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 12b2c88c8307..5d356f670fe8 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a8c714ad522d..b30af0dfd2bc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index bc60ad011718..ea0f19d9a145 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 8bd42c99c711..83cb7b99674a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -47,7 +47,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 96cec67c1213..a84ae3766ea3 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.72.0 + 26.73.0 import pom From 4452ab743cf9c4df3565b2efe0f5fe4769404d8b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 17 Dec 2025 07:56:23 +0000 Subject: [PATCH 1906/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.81.0 (#2331) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b10b4f77e89d..7c79ea803c63 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -227,7 +227,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.80.0 + 2.81.0 test From 9e0c61d5a324d433df2501d96fd3a7b7c2fd4f1f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 17 Dec 2025 07:56:43 +0000 Subject: [PATCH 1907/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.34.1 (#2329) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 1d139b2cf1ce..78ae62ddd7e9 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.0 + 2.34.1 From 2aabda8b2b760c42c93f80edefd615b6ad56eb63 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 18 Dec 2025 09:45:41 +0000 Subject: [PATCH 1908/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.81.0 (#2332) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7c79ea803c63..6b9d8613f73a 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -221,7 +221,7 @@ com.google.cloud google-cloud-trace - 2.80.0 + 2.81.0 test From 0058db012837a6fd95f85e7a2723ff72352ffe01 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Tue, 23 Dec 2025 16:31:04 -0500 Subject: [PATCH 1909/1979] chore: remove build badges (#2346) b/468377909 --- java-spanner-jdbc/README.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c8b59f1ef9b1..d8754d4987d9 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -243,29 +243,10 @@ information. Apache 2.0 - See [LICENSE][license] for more information. -## CI Status - -Java Version | Status ------------- | ------ -Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2] -Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] -Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] -Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] - Java is a registered trademark of Oracle and/or its affiliates. [product-docs]: https://cloud.google.com/spanner/docs/use-oss-jdbc [javadocs]: https://googleapis.dev/java/google-cloud-spanner-jdbc/latest/index.html -[kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.svg -[kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java7.html -[kokoro-badge-image-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8.svg -[kokoro-badge-link-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8.html -[kokoro-badge-image-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-osx.svg -[kokoro-badge-link-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-osx.html -[kokoro-badge-image-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-win.svg -[kokoro-badge-link-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java8-win.html -[kokoro-badge-image-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java11.svg -[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner-jdbc/java11.html [stability-image]: https://img.shields.io/badge/stability-ga-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner-jdbc.svg [maven-version-link]: https://search.maven.org/search?q=g:com.google.cloud%20AND%20a:google-cloud-spanner-jdbc&core=gav From 441c91ed8f58f6083888a95ee4d563e5bbb1824b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Jan 2026 12:52:51 +0000 Subject: [PATCH 1910/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.9 (#2342) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 83cb7b99674a..3d6d23a49752 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.8 + 3.5.9 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index a84ae3766ea3..85199a3c455a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.8 + 3.5.9 From da07b14177862052a228751efce03ca91d64cb51 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Jan 2026 12:53:07 +0000 Subject: [PATCH 1911/1979] deps: update dependency org.springframework.boot:spring-boot to v4.0.1 (#2343) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index eedc86494c54..de93984f5953 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 4.0.0 + 4.0.1 test From 67cfffc558c7c089565e65ff31dd0dfcb5e9ad7c Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Jan 2026 12:53:23 +0000 Subject: [PATCH 1912/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.1 (#2344) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index b30af0dfd2bc..67c84376b0fc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -60,7 +60,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.0 + 4.0.1 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index ea0f19d9a145..49983c25a2a8 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -60,7 +60,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.0 + 4.0.1 From 3e7751b0b762d4f44fdac784e10473025df8f553 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Jan 2026 14:28:39 +0000 Subject: [PATCH 1913/1979] deps: update dependency com.google.cloud:grpc-gcp to v1.9.1 (#2348) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 6b9d8613f73a..72bf3e03c3f0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -68,7 +68,7 @@ com.google.cloud grpc-gcp - 1.9.0 + 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 67c84376b0fc..48fc509f2d39 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud grpc-gcp - 1.9.0 + 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 49983c25a2a8..8479bee7a131 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,7 @@ com.google.cloud grpc-gcp - 1.9.0 + 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 3d6d23a49752..22075ceb7d01 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,7 @@ com.google.cloud grpc-gcp - 1.9.0 + 1.9.1 com.google.cloud From c9fe8272793fa7d93e01313170e1052b52b4a661 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Jan 2026 14:29:01 +0000 Subject: [PATCH 1914/1979] build(deps): update dependency org.codehaus.mojo:exec-maven-plugin to v3.6.3 (#2347) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index de93984f5953..388ffcaf1eb6 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -95,7 +95,7 @@ org.codehaus.mojo exec-maven-plugin - 3.6.2 + 3.6.3 com.google.cloud.jdbc.quickperf.QuickPerf From 34ceefef2467bedf57ab9b736b54fd2ee4939504 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Fri, 9 Jan 2026 12:48:47 +0530 Subject: [PATCH 1915/1979] chore: Update product name in JDBC metadata for PG dialect (#2353) --- .../com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java | 3 ++- .../google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java index 98d23a2261f5..7168e2f9204b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaData.java @@ -48,6 +48,7 @@ class JdbcDatabaseMetaData extends AbstractJdbcWrapper implements DatabaseMetaDa private static final int DATABASE_MAJOR_VERSION = 1; private static final int DATABASE_MINOR_VERSION = 0; private static final String PRODUCT_NAME = "Google Cloud Spanner"; + private static final String POSTGRESQL_PRODUCT_NAME = PRODUCT_NAME + " PostgreSQL"; @VisibleForTesting static String readSqlFromFile(String filename, Dialect dialect) { @@ -137,7 +138,7 @@ public boolean nullsAreSortedAtEnd() { @Override public String getDatabaseProductName() { - return PRODUCT_NAME; + return connection.getDialect() == Dialect.POSTGRESQL ? POSTGRESQL_PRODUCT_NAME : PRODUCT_NAME; } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java index 4545bb56ec21..fc3168ab4f0a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDatabaseMetaDataTest.java @@ -57,6 +57,8 @@ public static Object[] data() { private static final int DATABASE_MAJOR_VERSION = 1; private static final int DATABASE_MINOR_VERSION = 0; private static final String DATABASE_PRODUCT_NAME = "Google Cloud Spanner"; + private static final String POSTGRESQL_DATABASE_PRODUCT_NAME = + DATABASE_PRODUCT_NAME + " PostgreSQL"; @Test public void testTrivialMethods() throws SQLException { @@ -90,7 +92,6 @@ public void testTrivialMethods() throws SQLException { assertEquals("CATALOG", meta.getCatalogTerm()); assertEquals(DATABASE_MAJOR_VERSION, meta.getDatabaseMajorVersion()); assertEquals(DATABASE_MINOR_VERSION, meta.getDatabaseMinorVersion()); - assertEquals(DATABASE_PRODUCT_NAME, meta.getDatabaseProductName()); assertEquals( DATABASE_MAJOR_VERSION + "." + DATABASE_MINOR_VERSION, meta.getDatabaseProductVersion()); assertEquals(Connection.TRANSACTION_SERIALIZABLE, meta.getDefaultTransactionIsolation()); @@ -134,8 +135,10 @@ public void testTrivialMethods() throws SQLException { assertFalse(meta.isCatalogAtStart()); assertEquals(connection.isReadOnly(), meta.isReadOnly()); if (dialect == Dialect.POSTGRESQL) { + assertEquals(POSTGRESQL_DATABASE_PRODUCT_NAME, meta.getDatabaseProductName()); assertTrue(meta.storesLowerCaseIdentifiers()); } else { + assertEquals(DATABASE_PRODUCT_NAME, meta.getDatabaseProductName()); assertFalse(meta.storesLowerCaseIdentifiers()); } assertFalse(meta.storesLowerCaseQuotedIdentifiers()); From 22ca02fa6d27a6224a1b416ca94589d4877ae339 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Tue, 13 Jan 2026 20:50:11 +0530 Subject: [PATCH 1916/1979] feat: Support float4 in JDBC (#2336) --- .../java/com/google/cloud/spanner/jdbc/JdbcDataType.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index c80db530226c..bb2f7c00711b 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -113,6 +113,8 @@ public Type getSpannerType() { } }, FLOAT32 { + private final Set aliases = new HashSet<>(Collections.singletonList("float4")); + @Override public int getSqlType() { return Types.REAL; @@ -152,6 +154,11 @@ public List getArrayElements(ResultSet rs, int columnIndex) { public Type getSpannerType() { return Type.float32(); } + + @Override + public Set getPostgreSQLAliases() { + return aliases; + } }, FLOAT64 { private final Set> classes = new HashSet<>(Arrays.asList(Float.class, Double.class)); From 208e61187e0075eeda2f2a9ad124526c968c1253 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Tue, 13 Jan 2026 15:55:10 -0500 Subject: [PATCH 1917/1979] chore: cleanup release-please config (#2315) - Remove redundant options already declared at the top level.\n- Remove bumpMinorPreMajor for repositories after the first major release. --- java-spanner-jdbc/.github/release-please.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/java-spanner-jdbc/.github/release-please.yml b/java-spanner-jdbc/.github/release-please.yml index 8c51cd7d67e1..3ae6e07da033 100644 --- a/java-spanner-jdbc/.github/release-please.yml +++ b/java-spanner-jdbc/.github/release-please.yml @@ -2,13 +2,7 @@ releaseType: java-yoshi bumpMinorPreMajor: true handleGHRelease: true branches: -- branch: 1.21.x - releaseType: java-yoshi - bumpMinorPreMajor: true - handleGHRelease: true -- branch: protobuf-4.x-rc - releaseType: java-yoshi - bumpMinorPreMajor: true - handleGHRelease: true - manifest: true + - branch: 1.21.x + - branch: protobuf-4.x-rc + manifest: true extraFiles: ["README.md"] From 40814f1c6686b60d23cc905665eda332fdc17a4b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 14 Jan 2026 07:50:50 +0000 Subject: [PATCH 1918/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.55.1 (#2355) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 1aded26889a2..9496d664f4fa 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.54.2 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.55.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 38cc2a00c39c..5f83c06eeb0b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.54.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.55.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 952e958134e8..09ee760210f0 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.54.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.55.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index f673877b3cfb..15a92eb2e28b 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.54.2" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.55.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 72bf3e03c3f0..fcd4d3abad15 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.54.2 + 3.55.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 388ffcaf1eb6..7fb46c05d6e6 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.54.2 + 3.55.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 5d356f670fe8..c52c6f64470b 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.54.2 + 3.55.1 From 380697d46d3184fd8c5517f0ea508b0ca99ba245 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Wed, 14 Jan 2026 20:03:50 +0530 Subject: [PATCH 1919/1979] chore: remove explicit grpc-gcp version pinning (#2356) --- java-spanner-jdbc/pom.xml | 1 - java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 1 - java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 1 - java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 1 - 4 files changed, 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fcd4d3abad15..d04dceb0165c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -68,7 +68,6 @@ com.google.cloud grpc-gcp - 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 48fc509f2d39..a5122b511f4b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -37,7 +37,6 @@ com.google.cloud grpc-gcp - 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 8479bee7a131..bea1397c98d4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -37,7 +37,6 @@ com.google.cloud grpc-gcp - 1.9.1 com.google.cloud diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 22075ceb7d01..35bf9051b751 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -42,7 +42,6 @@ com.google.cloud grpc-gcp - 1.9.1 com.google.cloud From 2af488c4f12b4909414b8722153ae8abc65dd2c1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:42:47 +0000 Subject: [PATCH 1920/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.106.0 (#2352) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d04dceb0165c..88b24cba97d8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.105.0 + 6.106.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index a5122b511f4b..54820314499d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.105.0 + 6.106.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index bea1397c98d4..fc876d3d4a4a 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.105.0 + 6.106.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 35bf9051b751..8e892785ab11 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.105.0 + 6.106.0 import pom From caa0ccc134a5f531750590c79291747b9833d1b4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:43:09 +0000 Subject: [PATCH 1921/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.106.0 (#2351) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 8e892785ab11..28b45d236bdb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -98,7 +98,7 @@ com.google.cloud google-cloud-spanner - 6.105.0 + 6.106.0 test-jar test From da8bab0a5b756f64a51d240eae230cb80f4aba4b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:43:35 +0000 Subject: [PATCH 1922/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.58.0 (#2354) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 54820314499d..5fe45e3daa77 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -48,7 +48,7 @@ io.opentelemetry opentelemetry-bom - 1.57.0 + 1.58.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index fc876d3d4a4a..4724639c9b5c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -48,7 +48,7 @@ io.opentelemetry opentelemetry-bom - 1.57.0 + 1.58.0 pom import From b1d24e84e3ccb4af782f3cfc81fd0ac5aa958bb3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:46:14 +0000 Subject: [PATCH 1923/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.82.0 (#2358) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 88b24cba97d8..08b30c5706ba 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -220,7 +220,7 @@ com.google.cloud google-cloud-trace - 2.81.0 + 2.82.0 test From 8680aebfa69369bd94b203b28dbe9bbe9a2ccd01 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:46:34 +0000 Subject: [PATCH 1924/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.82.0 (#2357) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 08b30c5706ba..79dc8fef5a5b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.81.0 + 2.82.0 test From 19437f033f34c98dd35e6e2f412d9dc72cbbe503 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:46:54 +0000 Subject: [PATCH 1925/1979] deps: update dependency net.bytebuddy:byte-buddy-agent to v1.18.4 (#2350) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4724639c9b5c..f0c197da26bc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -124,7 +124,7 @@ net.bytebuddy byte-buddy-agent - 1.18.2 + 1.18.4 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 28b45d236bdb..6afa902dc4ac 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -118,7 +118,7 @@ net.bytebuddy byte-buddy-agent - 1.18.2 + 1.18.4 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 85199a3c455a..e762d80e7592 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -111,7 +111,7 @@ net.bytebuddy byte-buddy-agent - 1.18.2 + 1.18.4 test From 22bdf8092c446dab6b904f14b925eedf6d1360aa Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 15:47:14 +0000 Subject: [PATCH 1926/1979] deps: update dependency net.bytebuddy:byte-buddy to v1.18.4 (#2349) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index f0c197da26bc..2a1cbf9912ee 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -118,7 +118,7 @@ net.bytebuddy byte-buddy - 1.18.2 + 1.18.4 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 6afa902dc4ac..401767b04256 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -112,7 +112,7 @@ net.bytebuddy byte-buddy - 1.18.2 + 1.18.4 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index e762d80e7592..d6194f8df38e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -105,7 +105,7 @@ net.bytebuddy byte-buddy - 1.18.2 + 1.18.4 test From b35164ad6a52b2c0b90bd6920b8568dae5361701 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 18:47:38 +0000 Subject: [PATCH 1927/1979] deps: update dependency org.postgresql:postgresql to v42.7.9 (#2359) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 2a1cbf9912ee..d6b965dbd585 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -76,7 +76,7 @@ org.postgresql postgresql - 42.7.8 + 42.7.9 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index d6194f8df38e..f5f1c33b0331 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.8 + 42.7.9 org.testcontainers From da3d74f103fbec85421a686091730bc5edc5b27f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 19:44:27 +0000 Subject: [PATCH 1928/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.107.0 (#2360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner](https://redirect.github.com/googleapis/java-spanner) | `6.106.0` → `6.107.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner/6.107.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner/6.107.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner/6.106.0/6.107.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner/6.106.0/6.107.0?slim=true) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner) ### [`v6.107.0`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61070-2026-01-16) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.106.0...v6.107.0) ##### Features - Add Dynamic Channel Pooling (DCP) support to Connection API ([#​4299](https://redirect.github.com/googleapis/java-spanner/issues/4299)) ([bba03a4](https://redirect.github.com/googleapis/java-spanner/commit/bba03a44dbfbd59288ecd33e3e53276809ad69b1)) - Add SsFormat encoding library ([#​4292](https://redirect.github.com/googleapis/java-spanner/issues/4292)) ([338a9b1](https://redirect.github.com/googleapis/java-spanner/commit/338a9b1409cafedcdef674bdff09a72c3f2cd772)) ##### Dependencies - Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.82.0 ([#​4227](https://redirect.github.com/googleapis/java-spanner/issues/4227)) ([22bc6cf](https://redirect.github.com/googleapis/java-spanner/commit/22bc6cf3431f6e507d384f6e86a36503f1175ee7)) - Update dependency com.google.cloud:google-cloud-monitoring to v3.83.0 ([#​4169](https://redirect.github.com/googleapis/java-spanner/issues/4169)) ([61ae915](https://redirect.github.com/googleapis/java-spanner/commit/61ae915242a3c8a0aa1385bc1367f67df2c209d6)) - Update dependency com.google.cloud:sdk-platform-java-config to v3.55.1 ([#​4302](https://redirect.github.com/googleapis/java-spanner/issues/4302)) ([52acc0c](https://redirect.github.com/googleapis/java-spanner/commit/52acc0c620fec0aa67ecd81d634eec271fe4e429)) - Update dependency net.bytebuddy:byte-buddy to v1.18.4 ([#​4244](https://redirect.github.com/googleapis/java-spanner/issues/4244)) ([c8e4d91](https://redirect.github.com/googleapis/java-spanner/commit/c8e4d912155ab6829498822dcf0783fac5fe2747)) - Update google.cloud.monitoring.version to v3.83.0 ([#​4270](https://redirect.github.com/googleapis/java-spanner/issues/4270)) ([7ae68c8](https://redirect.github.com/googleapis/java-spanner/commit/7ae68c8e889f44f1057310bc45b70c086af9c385)) - Update googleapis/sdk-platform-java action to v2.65.1 ([#​4301](https://redirect.github.com/googleapis/java-spanner/issues/4301)) ([7d98f4e](https://redirect.github.com/googleapis/java-spanner/commit/7d98f4e12843826c18cbb8e0998c8687c94fc3d2))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 401767b04256..94a01256da04 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -98,7 +98,7 @@ com.google.cloud google-cloud-spanner - 6.106.0 + 6.107.0 test-jar test From f6f59429ed8c8eb3e66e122901fa71bf4961274a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 16 Jan 2026 19:45:56 +0000 Subject: [PATCH 1929/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.107.0 (#2361) --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 79dc8fef5a5b..c958073e51df 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.106.0 + 6.107.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 5fe45e3daa77..d789c91a6061 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.106.0 + 6.107.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index d6b965dbd585..984ecf62a8f4 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.106.0 + 6.107.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 94a01256da04..0917b8df9bc9 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.106.0 + 6.107.0 import pom From 1122372cc21721827a1e4489e51c7460e282f919 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:14:24 +0000 Subject: [PATCH 1930/1979] chore(main): release 2.35.0 (#2335) :robot: I have created a release *beep* *boop* --- ## [2.35.0](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.34.1...v2.35.0) (2026-01-16) ### Features * Support float4 in JDBC ([#2336](https://togithub.com/googleapis/java-spanner-jdbc/issues/2336)) ([22ca02f](https://togithub.com/googleapis/java-spanner-jdbc/commit/22ca02fa6d27a6224a1b416ca94589d4877ae339)) ### Dependencies * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.81.0 ([#2331](https://togithub.com/googleapis/java-spanner-jdbc/issues/2331)) ([4452ab7](https://togithub.com/googleapis/java-spanner-jdbc/commit/4452ab743cf9c4df3565b2efe0f5fe4769404d8b)) * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.82.0 ([#2357](https://togithub.com/googleapis/java-spanner-jdbc/issues/2357)) ([8680aeb](https://togithub.com/googleapis/java-spanner-jdbc/commit/8680aebfa69369bd94b203b28dbe9bbe9a2ccd01)) * Update dependency com.google.cloud:google-cloud-spanner to v6.106.0 ([#2351](https://togithub.com/googleapis/java-spanner-jdbc/issues/2351)) ([caa0ccc](https://togithub.com/googleapis/java-spanner-jdbc/commit/caa0ccc134a5f531750590c79291747b9833d1b4)) * Update dependency com.google.cloud:google-cloud-spanner to v6.107.0 ([#2360](https://togithub.com/googleapis/java-spanner-jdbc/issues/2360)) ([da3d74f](https://togithub.com/googleapis/java-spanner-jdbc/commit/da3d74f103fbec85421a686091730bc5edc5b27f)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.106.0 ([#2352](https://togithub.com/googleapis/java-spanner-jdbc/issues/2352)) ([2af488c](https://togithub.com/googleapis/java-spanner-jdbc/commit/2af488c4f12b4909414b8722153ae8abc65dd2c1)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.107.0 ([#2361](https://togithub.com/googleapis/java-spanner-jdbc/issues/2361)) ([f6f5942](https://togithub.com/googleapis/java-spanner-jdbc/commit/f6f59429ed8c8eb3e66e122901fa71bf4961274a)) * Update dependency com.google.cloud:google-cloud-trace to v2.81.0 ([#2332](https://togithub.com/googleapis/java-spanner-jdbc/issues/2332)) ([2aabda8](https://togithub.com/googleapis/java-spanner-jdbc/commit/2aabda8b2b760c42c93f80edefd615b6ad56eb63)) * Update dependency com.google.cloud:google-cloud-trace to v2.82.0 ([#2358](https://togithub.com/googleapis/java-spanner-jdbc/issues/2358)) ([b1d24e8](https://togithub.com/googleapis/java-spanner-jdbc/commit/b1d24e84e3ccb4af782f3cfc81fd0ac5aa958bb3)) * Update dependency com.google.cloud:grpc-gcp to v1.9.1 ([#2348](https://togithub.com/googleapis/java-spanner-jdbc/issues/2348)) ([3e7751b](https://togithub.com/googleapis/java-spanner-jdbc/commit/3e7751b0b762d4f44fdac784e10473025df8f553)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.55.1 ([#2355](https://togithub.com/googleapis/java-spanner-jdbc/issues/2355)) ([40814f1](https://togithub.com/googleapis/java-spanner-jdbc/commit/40814f1c6686b60d23cc905665eda332fdc17a4b)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.58.0 ([#2354](https://togithub.com/googleapis/java-spanner-jdbc/issues/2354)) ([da8bab0](https://togithub.com/googleapis/java-spanner-jdbc/commit/da8bab0a5b756f64a51d240eae230cb80f4aba4b)) * Update dependency net.bytebuddy:byte-buddy to v1.18.4 ([#2349](https://togithub.com/googleapis/java-spanner-jdbc/issues/2349)) ([22bdf80](https://togithub.com/googleapis/java-spanner-jdbc/commit/22bdf8092c446dab6b904f14b925eedf6d1360aa)) * Update dependency net.bytebuddy:byte-buddy-agent to v1.18.4 ([#2350](https://togithub.com/googleapis/java-spanner-jdbc/issues/2350)) ([19437f0](https://togithub.com/googleapis/java-spanner-jdbc/commit/19437f033f34c98dd35e6e2f412d9dc72cbbe503)) * Update dependency org.postgresql:postgresql to v42.7.9 ([#2359](https://togithub.com/googleapis/java-spanner-jdbc/issues/2359)) ([b35164a](https://togithub.com/googleapis/java-spanner-jdbc/commit/b35164ad6a52b2c0b90bd6920b8568dae5361701)) * Update dependency org.springframework.boot:spring-boot to v4.0.1 ([#2343](https://togithub.com/googleapis/java-spanner-jdbc/issues/2343)) ([da07b14](https://togithub.com/googleapis/java-spanner-jdbc/commit/da07b14177862052a228751efce03ca91d64cb51)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.1 ([#2344](https://togithub.com/googleapis/java-spanner-jdbc/issues/2344)) ([67cfffc](https://togithub.com/googleapis/java-spanner-jdbc/commit/67cfffc558c7c089565e65ff31dd0dfcb5e9ad7c)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.9 ([#2342](https://togithub.com/googleapis/java-spanner-jdbc/issues/2342)) ([441c91e](https://togithub.com/googleapis/java-spanner-jdbc/commit/441c91ed8f58f6083888a95ee4d563e5bbb1824b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 28 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 ++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 11ebcecf4155..3298d765512e 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [2.35.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.34.1...v2.35.0) (2026-01-16) + + +### Features + +* Support float4 in JDBC ([#2336](https://github.com/googleapis/java-spanner-jdbc/issues/2336)) ([6bbcac6](https://github.com/googleapis/java-spanner-jdbc/commit/6bbcac65aaa02bcb9a062459de5e36630e27e88c)) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.81.0 ([#2331](https://github.com/googleapis/java-spanner-jdbc/issues/2331)) ([a207dea](https://github.com/googleapis/java-spanner-jdbc/commit/a207dea27e97fde2b84da412dd701890c5d8a308)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.82.0 ([#2357](https://github.com/googleapis/java-spanner-jdbc/issues/2357)) ([6dd218f](https://github.com/googleapis/java-spanner-jdbc/commit/6dd218fcac050b196f5433e20fd9b07bf3122546)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.106.0 ([#2351](https://github.com/googleapis/java-spanner-jdbc/issues/2351)) ([c07d754](https://github.com/googleapis/java-spanner-jdbc/commit/c07d754b4308ae88ec4239dda20671b2ad05cd36)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.107.0 ([#2360](https://github.com/googleapis/java-spanner-jdbc/issues/2360)) ([e45f327](https://github.com/googleapis/java-spanner-jdbc/commit/e45f327272283a5b4a679bc97349bbe66ab3da53)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.106.0 ([#2352](https://github.com/googleapis/java-spanner-jdbc/issues/2352)) ([f7b660a](https://github.com/googleapis/java-spanner-jdbc/commit/f7b660a659eb650b1aef8891b8dfe2a031179513)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.107.0 ([#2361](https://github.com/googleapis/java-spanner-jdbc/issues/2361)) ([033eceb](https://github.com/googleapis/java-spanner-jdbc/commit/033eceb0e30e872154d1a6c43dabfd5f4794d2b5)) +* Update dependency com.google.cloud:google-cloud-trace to v2.81.0 ([#2332](https://github.com/googleapis/java-spanner-jdbc/issues/2332)) ([c389ffc](https://github.com/googleapis/java-spanner-jdbc/commit/c389ffce9fdfde1f1a24742f64ec00b4fc8845b7)) +* Update dependency com.google.cloud:google-cloud-trace to v2.82.0 ([#2358](https://github.com/googleapis/java-spanner-jdbc/issues/2358)) ([9565583](https://github.com/googleapis/java-spanner-jdbc/commit/9565583115b3feb99296de61a4c1be272790994d)) +* Update dependency com.google.cloud:grpc-gcp to v1.9.1 ([#2348](https://github.com/googleapis/java-spanner-jdbc/issues/2348)) ([7de2507](https://github.com/googleapis/java-spanner-jdbc/commit/7de25072cc5b1706c0a66a09d78e08ff67212441)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.55.1 ([#2355](https://github.com/googleapis/java-spanner-jdbc/issues/2355)) ([b278e20](https://github.com/googleapis/java-spanner-jdbc/commit/b278e203d1f7ceb077e7a13b0657aaa78016ab90)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.58.0 ([#2354](https://github.com/googleapis/java-spanner-jdbc/issues/2354)) ([efd4380](https://github.com/googleapis/java-spanner-jdbc/commit/efd43805057333ef3079c78538e0c99c767a5e01)) +* Update dependency net.bytebuddy:byte-buddy to v1.18.4 ([#2349](https://github.com/googleapis/java-spanner-jdbc/issues/2349)) ([e4daede](https://github.com/googleapis/java-spanner-jdbc/commit/e4daedea8a29038974c8bc73c0d930a997d2116e)) +* Update dependency net.bytebuddy:byte-buddy-agent to v1.18.4 ([#2350](https://github.com/googleapis/java-spanner-jdbc/issues/2350)) ([cb68853](https://github.com/googleapis/java-spanner-jdbc/commit/cb6885347527a14ffe95bd9e0ca5c18745419dfc)) +* Update dependency org.postgresql:postgresql to v42.7.9 ([#2359](https://github.com/googleapis/java-spanner-jdbc/issues/2359)) ([3c869dd](https://github.com/googleapis/java-spanner-jdbc/commit/3c869ddc3abc9f19e6e21cfa8ff7922b5bbcd65e)) +* Update dependency org.springframework.boot:spring-boot to v4.0.1 ([#2343](https://github.com/googleapis/java-spanner-jdbc/issues/2343)) ([9f84c07](https://github.com/googleapis/java-spanner-jdbc/commit/9f84c0782fccf3e93d03498b247e926ad6d24056)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.1 ([#2344](https://github.com/googleapis/java-spanner-jdbc/issues/2344)) ([661566d](https://github.com/googleapis/java-spanner-jdbc/commit/661566d90fe91a31b7152181704c5f508c3dcb36)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.9 ([#2342](https://github.com/googleapis/java-spanner-jdbc/issues/2342)) ([e1fb27a](https://github.com/googleapis/java-spanner-jdbc/commit/e1fb27a821f0fe2b61b0790be578ba6851bf3b96)) + ## [2.34.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.34.0...v2.34.1) (2025-12-16) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index d8754d4987d9..c7e4a8b7b217 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.34.1 + 2.35.0 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.34.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.0' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.34.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.0" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c958073e51df..d8ac3be2c4c0 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.34.2-SNAPSHOT + 2.35.0 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index d80be289eabb..f190545bbdc2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.2-SNAPSHOT + 2.35.0 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 06f38cdc696f..26ac9e8549fb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.34.1:2.34.2-SNAPSHOT +google-cloud-spanner-jdbc:2.35.0:2.35.0 From 3ce9e4d987fce81ed4c11e85e593f63c9d0be77a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 12:35:56 +0100 Subject: [PATCH 1931/1979] chore(main): release 2.35.1-SNAPSHOT (#2362) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index d8ac3be2c4c0..f0ea9a46f608 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.0 + 2.35.1-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index f190545bbdc2..62997c229ae8 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 26ac9e8549fb..f6c5b1fa8bc4 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.0:2.35.0 +google-cloud-spanner-jdbc:2.35.0:2.35.1-SNAPSHOT From 5f64260e5ffe12775134b7a0c0577a82834ff122 Mon Sep 17 00:00:00 2001 From: "rayudu.alp" Date: Tue, 20 Jan 2026 15:01:08 +0530 Subject: [PATCH 1932/1979] fix: accept Arrays of Integer, Short, Byte for Array (#2365) --- .../google/cloud/spanner/jdbc/JdbcArray.java | 38 ++++++++-- .../cloud/spanner/jdbc/JdbcDataType.java | 2 +- .../spanner/jdbc/JdbcParameterStore.java | 2 + .../cloud/spanner/jdbc/JdbcArrayTest.java | 76 +++++++++++++++++++ 4 files changed, 109 insertions(+), 9 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java index 1dd83f8171a4..3cb523186517 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcArray.java @@ -92,19 +92,41 @@ private JdbcArray(JdbcDataType type, Object[] elements) throws SQLException { this.data = java.lang.reflect.Array.newInstance( elements.getClass().getComponentType(), elements.length); + System.arraycopy(elements, 0, this.data, 0, elements.length); + } else if (type == JdbcDataType.INT64 && requiresWideningToLong(elements)) { + // Convert Byte[], Short[], and Integer[] to Long[] for INT64 type + // since Spanner only supports ARRAY + this.data = convertToLongArray(elements); } else { this.data = java.lang.reflect.Array.newInstance(type.getJavaClass(), elements.length); + try { + System.arraycopy(elements, 0, this.data, 0, elements.length); + } catch (Exception e) { + throw JdbcSqlExceptionFactory.of( + "Could not copy array elements. Make sure the supplied array only contains elements of class " + + type.getJavaClass().getName(), + Code.UNKNOWN, + e); + } } - try { - System.arraycopy(elements, 0, this.data, 0, elements.length); - } catch (Exception e) { - throw JdbcSqlExceptionFactory.of( - "Could not copy array elements. Make sure the supplied array only contains elements of class " - + type.getJavaClass().getName(), - Code.UNKNOWN, - e); + } + } + + private static boolean requiresWideningToLong(Object[] elements) { + Class componentType = elements.getClass().getComponentType(); + return componentType == Byte.class + || componentType == Short.class + || componentType == Integer.class; + } + + private static Long[] convertToLongArray(Object[] elements) { + Long[] longElements = new Long[elements.length]; + for (int i = 0; i < elements.length; i++) { + if (elements[i] != null) { + longElements[i] = ((Number) elements[i]).longValue(); } } + return longElements; } private JdbcArray(JdbcDataType type, List elements) { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java index bb2f7c00711b..892c0057ce60 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataType.java @@ -201,7 +201,7 @@ public Set getPostgreSQLAliases() { }, INT64 { private final Set> classes = - new HashSet<>(Arrays.asList(Byte.class, Integer.class, Long.class)); + new HashSet<>(Arrays.asList(Byte.class, Short.class, Integer.class, Long.class)); @Override public int getSqlType() { diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java index 0964db08799e..b43b44ddc7d0 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcParameterStore.java @@ -875,6 +875,8 @@ private Builder setArrayValue(ValueBinder binder, int type, Object valu return binder.toBoolArray((boolean[]) value); } else if (Boolean[].class.isAssignableFrom(value.getClass())) { return binder.toBoolArray(Arrays.asList((Boolean[]) value)); + } else if (Byte[].class.isAssignableFrom(value.getClass())) { + return binder.toInt64Array(toLongList((Byte[]) value)); } else if (short[].class.isAssignableFrom(value.getClass())) { long[] l = new long[((short[]) value).length]; for (int i = 0; i < l.length; i++) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java index bfae4e556e0f..44dd1a78f863 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcArrayTest.java @@ -144,6 +144,82 @@ public void testCreateArrayTypeName() throws SQLException { assertThat(rs.next()).isFalse(); } + // Test that Byte[] arrays are automatically widened to Long[] for INT64 type + Long[] data; + array = JdbcArray.createArray("INT64", new Byte[] {1, 2, 3, null, Byte.MAX_VALUE}); + assertThat(array.getBaseType()).isEqualTo(Types.BIGINT); + // Data should be stored as Long[] + assertThat(array.getArray()).isInstanceOf(Long[].class); + data = (Long[]) array.getArray(); + assertThat(data[0]).isEqualTo(1L); + assertThat(data[1]).isEqualTo(2L); + assertThat(data[2]).isEqualTo(3L); + assertThat(data[3]).isNull(); + assertThat(data[4]).isEqualTo((long) Byte.MAX_VALUE); + + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getByte(2)).isEqualTo((byte) 1); + assertThat(rs.next()).isTrue(); + assertThat(rs.getByte(2)).isEqualTo((byte) 2); + assertThat(rs.next()).isTrue(); + assertThat(rs.getByte(2)).isEqualTo((byte) 3); + assertThat(rs.next()).isTrue(); + assertThat(rs.getByte(2)).isEqualTo((byte) 0); + assertTrue(rs.wasNull()); + assertThat(rs.next()).isTrue(); + assertThat(rs.getByte(2)).isEqualTo(Byte.MAX_VALUE); + assertThat(rs.next()).isFalse(); + } + + // Test that Short[] arrays are automatically widened to Long[] for INT64 type + array = JdbcArray.createArray("INT64", new Short[] {100, 200, null, Short.MAX_VALUE}); + assertThat(array.getBaseType()).isEqualTo(Types.BIGINT); + // Data should be stored as Long[] + assertThat(array.getArray()).isInstanceOf(Long[].class); + data = (Long[]) array.getArray(); + assertThat(data[0]).isEqualTo(100L); + assertThat(data[1]).isEqualTo(200L); + assertThat(data[2]).isNull(); + assertThat(data[3]).isEqualTo((long) Short.MAX_VALUE); + + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getShort(2)).isEqualTo((short) 100); + assertThat(rs.next()).isTrue(); + assertThat(rs.getShort(2)).isEqualTo((short) 200); + assertThat(rs.next()).isTrue(); + assertThat(rs.getShort(2)).isEqualTo((short) 0); + assertTrue(rs.wasNull()); + assertThat(rs.next()).isTrue(); + assertThat(rs.getShort(2)).isEqualTo(Short.MAX_VALUE); + assertThat(rs.next()).isFalse(); + } + + // Test that Integer[] arrays are automatically widened to Long[] for INT64 type + array = JdbcArray.createArray("INT64", new Integer[] {1000, 2000, null, Integer.MAX_VALUE}); + assertThat(array.getBaseType()).isEqualTo(Types.BIGINT); + // Data should be stored as Long[] + assertThat(array.getArray()).isInstanceOf(Long[].class); + data = (Long[]) array.getArray(); + assertThat(data[0]).isEqualTo(1000L); + assertThat(data[1]).isEqualTo(2000L); + assertThat(data[2]).isNull(); + assertThat(data[3]).isEqualTo((long) Integer.MAX_VALUE); + + try (ResultSet rs = array.getResultSet()) { + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(2)).isEqualTo(1000); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(2)).isEqualTo(2000); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(2)).isEqualTo(0); + assertTrue(rs.wasNull()); + assertThat(rs.next()).isTrue(); + assertThat(rs.getInt(2)).isEqualTo(Integer.MAX_VALUE); + assertThat(rs.next()).isFalse(); + } + array = JdbcArray.createArray("NUMERIC", new BigDecimal[] {BigDecimal.ONE, null, BigDecimal.TEN}); assertThat(array.getBaseType()).isEqualTo(Types.NUMERIC); From b3e9e5e3466c662090cfb2fa5318a6e531dea9c0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 Jan 2026 16:00:07 +0000 Subject: [PATCH 1933/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.35.0 (#2363) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 78ae62ddd7e9..865447824a32 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.34.1 + 2.35.0 From 075b29892082967d71b5b801adb53d6f4ac170a3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jan 2026 09:30:12 +0000 Subject: [PATCH 1934/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.2 (#2370) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index d789c91a6061..560f3ad4461c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -59,7 +59,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.1 + 4.0.2 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 984ecf62a8f4..61760a48be37 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -59,7 +59,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.1 + 4.0.2 From 3425c0d8e9f586d771d7d10c2b28ad2d1dc80c41 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jan 2026 09:30:42 +0000 Subject: [PATCH 1935/1979] deps: update dependency org.springframework.boot:spring-boot to v4.0.2 (#2369) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 7fb46c05d6e6..00d4c6a25043 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 4.0.1 + 4.0.2 test From d29244b2cacc7768c1fedb86810008667293faa7 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jan 2026 09:31:12 +0000 Subject: [PATCH 1936/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.10 (#2368) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 0917b8df9bc9..1efa0d2981cb 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.9 + 3.5.10 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index f5f1c33b0331..061f92696ea7 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.9 + 3.5.10 From a194bc679b3c7607923abd214ba2f228918cc16d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jan 2026 09:31:43 +0000 Subject: [PATCH 1937/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.74.0 (#2366) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 00d4c6a25043..4ff92403b513 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index c52c6f64470b..666ba5664b14 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 560f3ad4461c..5029fe0e7e18 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 61760a48be37..58978949ebe0 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 1efa0d2981cb..3fa032f644c6 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -46,7 +46,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 061f92696ea7..eb262a03115a 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.73.0 + 26.74.0 import pom From d26eea82bc58f7d4992650502b917a2956d3f49d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 26 Jan 2026 09:32:09 +0000 Subject: [PATCH 1938/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.0 (#2364) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4ff92403b513..4fe8c079ea3b 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.20.1 + 2.21.0 From c1a0382e94a930084ff23e723387f6372e498572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Jan 2026 16:19:47 +0100 Subject: [PATCH 1939/1979] perf: optimize JdbcDataSource#getConnection() (#2371) The `JdbcDataSource#getConnection()` method repeatedly executed a number of steps that were not necessary for each new connection. This has now been optimized, so they are only executed once, as long as the properties of the DataSource do not change. --- java-spanner-jdbc/pom.xml | 2 + .../cloud/spanner/jdbc/JdbcDataSource.java | 38 +++++++++-- .../google/cloud/spanner/jdbc/JdbcDriver.java | 63 ++++++++++--------- .../spanner/jdbc/JdbcDataSourceTest.java | 63 +++++++++++++++++++ .../src/test/resources/logging.properties | 7 +++ 5 files changed, 137 insertions(+), 36 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDataSourceTest.java create mode 100644 java-spanner-jdbc/src/test/resources/logging.properties diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f0ea9a46f608..dd0d253740dd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -260,6 +260,7 @@ projects/gcloud-devel/instances/spanner-testing-east1 + logging.properties
    @@ -274,6 +275,7 @@ projects/gcloud-devel/instances/spanner-testing-east1 + logging.properties 2400 4 diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java index d4f415d273fd..f0f073aad29c 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDataSource.java @@ -16,11 +16,14 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.JdbcDriver.appendPropertiesToUrl; +import static com.google.cloud.spanner.jdbc.JdbcDriver.buildConnectionOptions; +import static com.google.cloud.spanner.jdbc.JdbcDriver.maybeAddUserAgent; + import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.rpc.Code; import java.io.PrintWriter; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; @@ -35,6 +38,8 @@ public class JdbcDataSource extends AbstractJdbcWrapper implements DataSource { private Boolean readonly; private Boolean retryAbortsInternally; + private volatile ConnectionOptions cachedConnectionOptions; + // Make sure the JDBC driver class is loaded. static { try { @@ -76,12 +81,22 @@ public Connection getConnection() throws SQLException { throw JdbcSqlExceptionFactory.of( "There is no URL specified for this data source", Code.FAILED_PRECONDITION); } - if (!JdbcDriver.getRegisteredDriver().acceptsURL(getUrl())) { - throw JdbcSqlExceptionFactory.of( - "The URL " + getUrl() + " is not valid for the data source " + getClass().getName(), - Code.FAILED_PRECONDITION); + if (cachedConnectionOptions == null) { + synchronized (this) { + if (cachedConnectionOptions == null) { + if (!JdbcDriver.getRegisteredDriver().acceptsURL(getUrl())) { + throw JdbcSqlExceptionFactory.of( + "The URL " + getUrl() + " is not valid for the data source " + getClass().getName(), + Code.FAILED_PRECONDITION); + } + Properties properties = createProperties(); + maybeAddUserAgent(properties); + String connectionUri = appendPropertiesToUrl(url.substring(5), properties); + cachedConnectionOptions = buildConnectionOptions(connectionUri, properties); + } + } } - return DriverManager.getConnection(getUrl(), createProperties()); + return new JdbcConnection(getUrl(), cachedConnectionOptions); } @Override @@ -114,6 +129,12 @@ public boolean isClosed() { return false; } + private void clearCachedConnectionOptions() { + synchronized (this) { + cachedConnectionOptions = null; + } + } + /** * @return the JDBC URL to use for this {@link DataSource}. */ @@ -125,6 +146,7 @@ public String getUrl() { * @param url The JDBC URL to use for this {@link DataSource}. */ public void setUrl(String url) { + clearCachedConnectionOptions(); this.url = url; } @@ -143,6 +165,7 @@ public String getCredentials() { * connection URL will be used. */ public void setCredentials(String credentials) { + clearCachedConnectionOptions(); this.credentials = credentials; } @@ -161,6 +184,7 @@ public Boolean getAutocommit() { * the connection URL will be used. */ public void setAutocommit(Boolean autocommit) { + clearCachedConnectionOptions(); this.autocommit = autocommit; } @@ -179,6 +203,7 @@ public Boolean getReadonly() { * URL will be used. */ public void setReadonly(Boolean readonly) { + clearCachedConnectionOptions(); this.readonly = readonly; } @@ -197,6 +222,7 @@ public Boolean getRetryAbortsInternally() { * this property, the value in the connection URL will be used. */ public void setRetryAbortsInternally(Boolean retryAbortsInternally) { + clearCachedConnectionOptions(); this.retryAbortsInternally = retryAbortsInternally; } } diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java index 120880fee29d..8e8bd0726317 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcDriver.java @@ -37,6 +37,7 @@ import java.sql.SQLWarning; import java.util.Map.Entry; import java.util.Properties; +import java.util.function.Supplier; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -247,7 +248,7 @@ public Connection connect(String url, Properties info) throws SQLException { return null; } - private ConnectionOptions buildConnectionOptions(String connectionUrl, Properties info) { + static ConnectionOptions buildConnectionOptions(String connectionUrl, Properties info) { ConnectionOptions.Builder builder = ConnectionOptions.newBuilder().setTracingPrefix("JDBC").setUri(connectionUrl); if (info.containsKey(OPEN_TELEMETRY_PROPERTY_KEY) @@ -272,40 +273,42 @@ static void maybeAddUserAgent(Properties properties) { } } - static boolean isHibernate() { - // Cache the result as the check is relatively expensive, and we also don't want to create - // multiple different Spanner instances just to get the correct user-agent in every case. - return Suppliers.memoize( - () -> { - try { - // First check if the Spanner Hibernate dialect is on the classpath. If it is, then - // we assume that Hibernate will (eventually) be used. - Class.forName( - "com.google.cloud.spanner.hibernate.SpannerDialect", - /* initialize= */ false, - JdbcDriver.class.getClassLoader()); - return true; - } catch (Throwable ignore) { - } + private static final Supplier isHibernate = + Suppliers.memoize( + () -> { + try { + // First check if the Spanner Hibernate dialect is on the classpath. If it is, then + // we assume that Hibernate will (eventually) be used. + Class.forName( + "com.google.cloud.spanner.hibernate.SpannerDialect", + /* initialize= */ false, + JdbcDriver.class.getClassLoader()); + return true; + } catch (Throwable ignore) { + } - // If we did not find the Spanner Hibernate dialect on the classpath, then do a - // check if the connection is still being created by Hibernate using the built-in - // Spanner dialect in Hibernate. - try { - StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); - for (StackTraceElement element : callStack) { - if (element.getClassName().contains(".hibernate.")) { - return true; - } + // If we did not find the Spanner Hibernate dialect on the classpath, then do a + // check if the connection is still being created by Hibernate using the built-in + // Spanner dialect in Hibernate. + try { + StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); + for (StackTraceElement element : callStack) { + if (element.getClassName().contains(".hibernate.")) { + return true; } - } catch (Throwable ignore) { } - return false; - }) - .get(); + } catch (Throwable ignore) { + } + return false; + }); + + static boolean isHibernate() { + // Cache the result as the check is relatively expensive, and we also don't want to create + // multiple different Spanner instances just to get the correct user-agent in every case. + return isHibernate.get(); } - private String appendPropertiesToUrl(String url, Properties info) { + static String appendPropertiesToUrl(String url, Properties info) { StringBuilder res = new StringBuilder(url); for (Entry entry : info.entrySet()) { if (entry.getValue() instanceof String && !"".equals(entry.getValue())) { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDataSourceTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDataSourceTest.java new file mode 100644 index 000000000000..196cb9169df5 --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcDataSourceTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2026 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 com.google.cloud.spanner.connection.AbstractMockServerTest; +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class JdbcDataSourceTest extends AbstractMockServerTest { + + @Override + protected String getBaseUrl() { + return String.format( + "jdbc:cloudspanner://localhost:%d/projects/p/instances/i/databases/d?usePlainText=true", + getPort()); + } + + @Test + public void testGetConnectionFromNewDataSource() throws SQLException { + for (boolean autoCommit : new boolean[] {true, false}) { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setUrl(getBaseUrl()); + dataSource.setAutocommit(autoCommit); + try (Connection connection = dataSource.getConnection()) { + assertEquals(autoCommit, connection.getAutoCommit()); + } + } + } + + @Test + public void testGetConnectionFromCachedDataSource() throws SQLException { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setUrl(getBaseUrl()); + for (boolean autoCommit : new boolean[] {true, false}) { + // Changing a property on the DataSource should invalidate the internally cached + // ConnectionOptions. + dataSource.setAutocommit(autoCommit); + try (Connection connection = dataSource.getConnection()) { + assertEquals(autoCommit, connection.getAutoCommit()); + } + } + } +} diff --git a/java-spanner-jdbc/src/test/resources/logging.properties b/java-spanner-jdbc/src/test/resources/logging.properties new file mode 100644 index 000000000000..c817ab7acd9f --- /dev/null +++ b/java-spanner-jdbc/src/test/resources/logging.properties @@ -0,0 +1,7 @@ +.level=INFO +.handlers=java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=INFO +java.util.logging.Logger.useParentHandlers=true + +# Set log level to WARN for SpannerImpl to prevent log spamming of the Spanner configuration. +com.google.cloud.spanner.SpannerImpl.LEVEL=WARN From 4e3cc49370e7258ff05081232eceb29a0560741c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 26 Jan 2026 16:20:03 +0100 Subject: [PATCH 1940/1979] docs: update connection properties docs with DCP (#2372) --- java-spanner-jdbc/documentation/connection_properties.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java-spanner-jdbc/documentation/connection_properties.md b/java-spanner-jdbc/documentation/connection_properties.md index 3e0f5efe3240..99e3e1d169c4 100644 --- a/java-spanner-jdbc/documentation/connection_properties.md +++ b/java-spanner-jdbc/documentation/connection_properties.md @@ -22,6 +22,9 @@ The 'Context' value indicates whether the property can only be set when a connec | credentialsprovider | The class name of the com.google.api.gax.core.CredentialsProvider implementation that should be used to obtain credentials for connections. | | | STARTUP | | databaserole | Sets the database role to use for this connection. The default is privileges assigned to IAM role | | | STARTUP | | databoostenabled | Enable data boost for all partitioned queries that are executed by this connection. This setting is only used for partitioned queries and is ignored by all other statements. | false | true, false | USER | +| dcpinitialchannels | The initial number of channels in the dynamic channel pool. Only used when enableDynamicChannelPool is true. The default is SpannerOptions.DEFAULT_DYNAMIC_POOL_INITIAL_SIZE (4). | | | STARTUP | +| dcpmaxchannels | The maximum number of channels in the dynamic channel pool. Only used when enableDynamicChannelPool is true. The default is SpannerOptions.DEFAULT_DYNAMIC_POOL_MAX_CHANNELS (10). | | | STARTUP | +| dcpminchannels | The minimum number of channels in the dynamic channel pool. Only used when enableDynamicChannelPool is true. The default is SpannerOptions.DEFAULT_DYNAMIC_POOL_MIN_CHANNELS (2). | | | STARTUP | | ddlintransactionmode | Determines how the connection should handle DDL statements in a read/write transaction. | ALLOW_IN_EMPTY_TRANSACTION | FAIL, ALLOW_IN_EMPTY_TRANSACTION, AUTO_COMMIT_TRANSACTION | USER | | default_isolation_level | The transaction isolation level that is used by default for read/write transactions. The default is isolation_level_unspecified, which means that the connection will use the default isolation level of the database that it is connected to. | ISOLATION_LEVEL_UNSPECIFIED | ISOLATION_LEVEL_UNSPECIFIED, SERIALIZABLE, REPEATABLE_READ | USER | | defaultsequencekind | The default sequence kind that should be used for the database. This property is only used when a DDL statement that requires a default sequence kind is executed on this connection. | | | USER | @@ -30,6 +33,7 @@ The 'Context' value indicates whether the property can only be set when a connec | directed_read | The directed read options to apply to read-only transactions. | | | USER | | enableapitracing | Add OpenTelemetry traces for each individual RPC call. Enable this to get a detailed view of each RPC that is being executed by your application, or if you want to debug potential latency problems caused by RPCs that are being retried. | | true, false | STARTUP | | enabledirectaccess | Configure the connection to try to connect to Spanner using DirectPath (true/false). The client will try to connect to Spanner using a direct Google network connection. DirectPath will work only if the client is trying to establish a connection from a Google Cloud VM. Otherwise it will automatically fallback to the standard network path. NOTE: The default for this property is currently false, but this could be changed in the future. | | true, false | STARTUP | +| enabledynamicchannelpool | Enable dynamic channel pooling for automatic gRPC channel scaling. When enabled, the client will automatically scale the number of channels based on load. Setting numChannels will disable dynamic channel pooling even if this is set to true. The default is currently false (disabled), but this may change to true in a future version. Set this property explicitly to ensure consistent behavior. | | true, false | STARTUP | | enableendtoendtracing | Enable end-to-end tracing (true/false) to generate traces for both the time that is spent in the client, as well as time that is spent in the Spanner server. Server side traces can only go to Google Cloud Trace, so to see end to end traces, the application should configure an exporter that exports the traces to Google Cloud Trace. | false | true, false | STARTUP | | enableextendedtracing | Include the SQL string in the OpenTelemetry traces that are generated by this connection. The SQL string is added as the standard OpenTelemetry attribute 'db.statement'. | | true, false | STARTUP | | encodedcredentials | Base64-encoded credentials to use for this connection. If neither this property or a credentials location are set, the connection will use the default Google Cloud credentials for the runtime environment. WARNING: Enabling this property without proper validation can expose the application to security risks. It is intended for use with credentials from a trusted source only, as it could otherwise allow end-users to supply arbitrary credentials. For more information, seehttps://cloud.google.com/docs/authentication/client-libraries#external-credentials | | | STARTUP | From 01a764863008a13f1fa9df07ec45980915a91412 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 17:15:07 +0100 Subject: [PATCH 1941/1979] chore(main): release 2.35.1 (#2367) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 25 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 3298d765512e..d7895ebe06d5 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [2.35.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.0...v2.35.1) (2026-01-26) + + +### Bug Fixes + +* Accept Arrays of Integer, Short, Byte for Array<Int64> ([#2365](https://github.com/googleapis/java-spanner-jdbc/issues/2365)) ([7429508](https://github.com/googleapis/java-spanner-jdbc/commit/7429508b82b26a55b6d7910416f3c72cfa63af2e)) + + +### Performance Improvements + +* Optimize JdbcDataSource#getConnection() ([#2371](https://github.com/googleapis/java-spanner-jdbc/issues/2371)) ([832064c](https://github.com/googleapis/java-spanner-jdbc/commit/832064ca2bca0d2d29e00c6b1417c7a4ce22f847)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.0 ([#2364](https://github.com/googleapis/java-spanner-jdbc/issues/2364)) ([a4b5c21](https://github.com/googleapis/java-spanner-jdbc/commit/a4b5c21a449fca70bab45eb756addcba57f0b080)) +* Update dependency org.springframework.boot:spring-boot to v4.0.2 ([#2369](https://github.com/googleapis/java-spanner-jdbc/issues/2369)) ([6c2b28e](https://github.com/googleapis/java-spanner-jdbc/commit/6c2b28e966dbb4c12a8c877b7eac2935146eaeb5)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.2 ([#2370](https://github.com/googleapis/java-spanner-jdbc/issues/2370)) ([61714fb](https://github.com/googleapis/java-spanner-jdbc/commit/61714fb5537d3676e7942738a86f08ec0b6e2707)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.10 ([#2368](https://github.com/googleapis/java-spanner-jdbc/issues/2368)) ([db1755c](https://github.com/googleapis/java-spanner-jdbc/commit/db1755ca41b4c7fd0a232be94f66d5965677e46e)) + + +### Documentation + +* Update connection properties docs with DCP ([#2372](https://github.com/googleapis/java-spanner-jdbc/issues/2372)) ([094ab5a](https://github.com/googleapis/java-spanner-jdbc/commit/094ab5a62a723cd895a6ea54259a3bbef98d56fc)) + ## [2.35.0](https://github.com/googleapis/java-spanner-jdbc/compare/v2.34.1...v2.35.0) (2026-01-16) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index c7e4a8b7b217..5893ab94b623 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.35.0 + 2.35.1 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.0' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.1' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.1" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dd0d253740dd..f299e9002c9d 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.1-SNAPSHOT + 2.35.1 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 62997c229ae8..fc6ff5f0c89f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.1-SNAPSHOT + 2.35.1 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index f6c5b1fa8bc4..0bd58ebcf68f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.0:2.35.1-SNAPSHOT +google-cloud-spanner-jdbc:2.35.1:2.35.1 From dfce4a6eacc7a16e0c04e564e920657181a3fa93 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:59:17 +0100 Subject: [PATCH 1942/1979] chore(main): release 2.35.2-SNAPSHOT (#2374) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f299e9002c9d..a285b1473fb7 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.1 + 2.35.2-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index fc6ff5f0c89f..62306eec97bb 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.1 + 2.35.2-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 0bd58ebcf68f..e704b6c1c44f 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.1:2.35.1 +google-cloud-spanner-jdbc:2.35.1:2.35.2-SNAPSHOT From 9d71deb79b96b35dcc8893312a2f790e12e5d819 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 28 Jan 2026 16:40:23 +0000 Subject: [PATCH 1943/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.56.0 (#2373) * deps: update dependency com.google.cloud:sdk-platform-java-config to v3.56.0 * update spanner version --------- Co-authored-by: Joe Wang --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 4 ++-- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 9496d664f4fa..7ba4f2c61f9e 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.55.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.56.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 5f83c06eeb0b..e07f1d7e180d 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.55.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.56.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 09ee760210f0..6c4674765444 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.55.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.56.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 15a92eb2e28b..cef52244e2a5 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.55.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.56.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index a285b1473fb7..7fa9ed7bb4de 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.55.1 + 3.56.0 @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.107.0 + 6.108.0 pom import diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 4fe8c079ea3b..03e48ac63bad 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.55.1 + 3.56.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 666ba5664b14..ffb389f591b4 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.55.1 + 3.56.0 From 3fd8b604a72d23788aebcb6ebe11c57eeb817d2e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 28 Jan 2026 16:50:32 +0000 Subject: [PATCH 1944/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.35.1 (#2375) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 865447824a32..a159f25343d0 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.0 + 2.35.1 From 4ec766d6cc73ae6b562c9d22715347bcb7a6bf0e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:20:15 -0500 Subject: [PATCH 1945/1979] chore(main): release 2.35.2 (#2378) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/CHANGELOG.md | 7 +++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index d7895ebe06d5..3f6cbf86c096 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.35.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.1...v2.35.2) (2026-01-28) + + +### Dependencies + +* Update dependency com.google.cloud:sdk-platform-java-config to v3.56.0 ([#2373](https://github.com/googleapis/java-spanner-jdbc/issues/2373)) ([ffa398a](https://github.com/googleapis/java-spanner-jdbc/commit/ffa398a3ca079b337bf90b1344fc8eeac68c17af)) + ## [2.35.1](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.0...v2.35.1) (2026-01-26) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 5893ab94b623..1b9bf4efe7af 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.35.1 + 2.35.2 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.1' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.2' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.1" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.2" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 7fa9ed7bb4de..fd6a4202c5db 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.2-SNAPSHOT + 2.35.2 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 62306eec97bb..33de4156ca45 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.2-SNAPSHOT + 2.35.2 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e704b6c1c44f..c52de3b5601e 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.1:2.35.2-SNAPSHOT +google-cloud-spanner-jdbc:2.35.2:2.35.2 From 6d23506bbd25466536328d96472878e5dc69e643 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Fri, 30 Jan 2026 14:17:16 -0500 Subject: [PATCH 1946/1979] chore: replace old java team with cloud-sdk-java-team (#2381) Replace old teams with new ones. b/479542582 --- java-spanner-jdbc/.github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index c5107b508607..4402cc751214 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -5,7 +5,7 @@ # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax # The @googleapis/api-spanner-java is the default owner for changes in this repo -* @googleapis/yoshi-java @googleapis/api-spanner-java +* @googleapis/cloud-sdk-java-team @googleapis/api-spanner-java # for handwritten libraries, keep codeowner_team in .repo-metadata.json as owner **/*.java @googleapis/api-spanner-java @@ -15,4 +15,4 @@ samples/**/*.java @googleapis/java-samples-reviewers # Generated snippets should not be owned by samples reviewers -samples/snippets/generated/ @googleapis/yoshi-java +samples/snippets/generated/ @googleapis/cloud-sdk-java-team From c05f3648e88b9e8f51977469cc40efecc2bc0588 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:11:04 +0000 Subject: [PATCH 1947/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.56.1 (#2386) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index 7ba4f2c61f9e..eccfa428c0d2 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.56.0 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.56.1 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index e07f1d7e180d..8449f549f05a 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.56.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.56.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 6c4674765444..360f589c1be2 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.56.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.56.1" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index cef52244e2a5..65c50c1d96aa 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.56.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.56.1" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index fd6a4202c5db..8215a2b01395 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.56.0 + 3.56.1 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 03e48ac63bad..d62bdba7639a 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.56.0 + 3.56.1 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index ffb389f591b4..7f196103b414 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.56.0 + 3.56.1 From 135d85225c6dee6046d5332279c527c287b0d0e1 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:11:22 +0000 Subject: [PATCH 1948/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.84.0 (#2383) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 8215a2b01395..88184e6e7bd3 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -220,7 +220,7 @@ com.google.cloud google-cloud-trace - 2.82.0 + 2.84.0 test From 3d3e9a8debd14961661a68f5f7967419402daf22 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:11:44 +0000 Subject: [PATCH 1949/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.84.0 (#2382) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 88184e6e7bd3..239429e3a986 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.82.0 + 2.84.0 test From 5f8ebdfdf1fae74316c27e1f2e17521304686bb9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:12:03 +0000 Subject: [PATCH 1950/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.75.0 (#2384) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index d62bdba7639a..1ea791578f3f 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 7f196103b414..69119cd79f7e 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 5029fe0e7e18..e71a89f3d397 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 58978949ebe0..ee7841ce04de 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 3fa032f644c6..25603f5fa18c 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -46,7 +46,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index eb262a03115a..f0c4bf60bb03 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.74.0 + 26.75.0 import pom From 928146442df7b6af1e6d85de73c497c7a320c803 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:12:26 +0000 Subject: [PATCH 1951/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.35.2 (#2380) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index a159f25343d0..81d96f334822 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.1 + 2.35.2 From 34c2e0bd786da131ab5fc98df8cb778bc0a05608 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 14:13:50 +0100 Subject: [PATCH 1952/1979] chore(main): release 2.35.3-SNAPSHOT (#2379) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 239429e3a986..70a991d255d8 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.2 + 2.35.3-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 33de4156ca45..90ecd3e6a184 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.2 + 2.35.3-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c52de3b5601e..c91e4d194deb 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.2:2.35.2 +google-cloud-spanner-jdbc:2.35.2:2.35.3-SNAPSHOT From 7f854c9d91bb0ea05261acafc0f1ca77db93f11f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:55:33 +0000 Subject: [PATCH 1953/1979] deps: update dependency io.opentelemetry:opentelemetry-bom to v1.59.0 (#2391) --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index e71a89f3d397..cc6ce956574e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -48,7 +48,7 @@ io.opentelemetry opentelemetry-bom - 1.58.0 + 1.59.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index ee7841ce04de..f7eaeb79825e 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -48,7 +48,7 @@ io.opentelemetry opentelemetry-bom - 1.58.0 + 1.59.0 pom import From ca0920d350d032bf10b3ad7248dc9d26c4fdac9b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 13:55:51 +0000 Subject: [PATCH 1954/1979] deps: update dependency org.postgresql:postgresql to v42.7.10 (#2390) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index f7eaeb79825e..62796369c6fb 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -76,7 +76,7 @@ org.postgresql postgresql - 42.7.9 + 42.7.10 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index f0c4bf60bb03..657264b8f62d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -75,7 +75,7 @@ org.postgresql postgresql - 42.7.9 + 42.7.10 org.testcontainers From 88ed2e97ff92efc8c8730ad4e14b2fb78cc8deba Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 13 Feb 2026 14:04:44 +0000 Subject: [PATCH 1955/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.0 (#2377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.0 * deps: update test library as well --------- Co-authored-by: Knut Olav Løite --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- .../samples/spring-data-mybatis/googlesql/pom.xml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 70a991d255d8..b38d7a08551f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.108.0 + 6.111.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index cc6ce956574e..be896f8c8c64 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.107.0 + 6.111.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 62796369c6fb..e5cef1e733c5 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.107.0 + 6.111.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 25603f5fa18c..4f188dd8783e 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.107.0 + 6.111.0 import pom @@ -98,7 +98,7 @@ com.google.cloud google-cloud-spanner - 6.107.0 + 6.111.0 test-jar test From 3a733b8ad4deb30d990a0d626a55f38067aa72e4 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 14:42:25 +0000 Subject: [PATCH 1956/1979] chore(main): release 2.35.3 (#2392) :robot: I have created a release *beep* *boop* --- ## [2.35.3](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.35.2...v2.35.3) (2026-02-13) ### Dependencies * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.84.0 ([#2382](https://togithub.com/googleapis/java-spanner-jdbc/issues/2382)) ([3d3e9a8](https://togithub.com/googleapis/java-spanner-jdbc/commit/3d3e9a8debd14961661a68f5f7967419402daf22)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.0 ([#2377](https://togithub.com/googleapis/java-spanner-jdbc/issues/2377)) ([88ed2e9](https://togithub.com/googleapis/java-spanner-jdbc/commit/88ed2e97ff92efc8c8730ad4e14b2fb78cc8deba)) * Update dependency com.google.cloud:google-cloud-trace to v2.84.0 ([#2383](https://togithub.com/googleapis/java-spanner-jdbc/issues/2383)) ([135d852](https://togithub.com/googleapis/java-spanner-jdbc/commit/135d85225c6dee6046d5332279c527c287b0d0e1)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.56.1 ([#2386](https://togithub.com/googleapis/java-spanner-jdbc/issues/2386)) ([c05f364](https://togithub.com/googleapis/java-spanner-jdbc/commit/c05f3648e88b9e8f51977469cc40efecc2bc0588)) * Update dependency io.opentelemetry:opentelemetry-bom to v1.59.0 ([#2391](https://togithub.com/googleapis/java-spanner-jdbc/issues/2391)) ([7f854c9](https://togithub.com/googleapis/java-spanner-jdbc/commit/7f854c9d91bb0ea05261acafc0f1ca77db93f11f)) * Update dependency org.postgresql:postgresql to v42.7.10 ([#2390](https://togithub.com/googleapis/java-spanner-jdbc/issues/2390)) ([ca0920d](https://togithub.com/googleapis/java-spanner-jdbc/commit/ca0920d350d032bf10b3ad7248dc9d26c4fdac9b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 12 ++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 3f6cbf86c096..4074fcf5dc8c 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [2.35.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.2...v2.35.3) (2026-02-13) + + +### Dependencies + +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.84.0 ([#2382](https://github.com/googleapis/java-spanner-jdbc/issues/2382)) ([3f9a5fa](https://github.com/googleapis/java-spanner-jdbc/commit/3f9a5fa066a1ebf03472a23e0f279ed5ce47dcf8)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.0 ([#2377](https://github.com/googleapis/java-spanner-jdbc/issues/2377)) ([cbccc66](https://github.com/googleapis/java-spanner-jdbc/commit/cbccc6666c3b9c7348a30615b3d71a822734a55a)) +* Update dependency com.google.cloud:google-cloud-trace to v2.84.0 ([#2383](https://github.com/googleapis/java-spanner-jdbc/issues/2383)) ([cb4b6cf](https://github.com/googleapis/java-spanner-jdbc/commit/cb4b6cf39ad59bd274311be35cade7c9b55707d4)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.56.1 ([#2386](https://github.com/googleapis/java-spanner-jdbc/issues/2386)) ([cf943d8](https://github.com/googleapis/java-spanner-jdbc/commit/cf943d851bdcdf7042c63f493a1021908f984915)) +* Update dependency io.opentelemetry:opentelemetry-bom to v1.59.0 ([#2391](https://github.com/googleapis/java-spanner-jdbc/issues/2391)) ([ac66b78](https://github.com/googleapis/java-spanner-jdbc/commit/ac66b78f033837b98f68a6e722ed163f87cda41c)) +* Update dependency org.postgresql:postgresql to v42.7.10 ([#2390](https://github.com/googleapis/java-spanner-jdbc/issues/2390)) ([dbb5c7a](https://github.com/googleapis/java-spanner-jdbc/commit/dbb5c7abc57a832198131f914cd75864f1607025)) + ## [2.35.2](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.1...v2.35.2) (2026-01-28) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 1b9bf4efe7af..91548492a6ef 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.35.2 + 2.35.3 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.2' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.3' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.2" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.3" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index b38d7a08551f..71b2a28af18b 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.3-SNAPSHOT + 2.35.3 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 90ecd3e6a184..ef40a813f2a2 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.3-SNAPSHOT + 2.35.3 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c91e4d194deb..47e2ea470ee3 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.2:2.35.3-SNAPSHOT +google-cloud-spanner-jdbc:2.35.3:2.35.3 From 8a3b5a836ac65ffb55d1068dac2ec3d9fda2aaf0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:44:50 +0100 Subject: [PATCH 1957/1979] chore(main): release 2.35.4-SNAPSHOT (#2393) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 71b2a28af18b..dbeb9da67497 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.3 + 2.35.4-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index ef40a813f2a2..25f5e13976ae 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.3 + 2.35.4-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index 47e2ea470ee3..e9569d16873c 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.3:2.35.3 +google-cloud-spanner-jdbc:2.35.3:2.35.4-SNAPSHOT From d95f608b522234ecba594902c264e85907a59e18 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:24:00 +0000 Subject: [PATCH 1958/1979] chore(deps): update dependency com.google.cloud:libraries-bom to v26.76.0 (#2399) --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 1ea791578f3f..6f7b95f9e9cc 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -27,7 +27,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 pom import diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index 69119cd79f7e..f1598e9b01b3 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -26,7 +26,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index be896f8c8c64..446dca52c97c 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index e5cef1e733c5..9f7a2a5f029d 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -41,7 +41,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 4f188dd8783e..cf956946b8db 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -46,7 +46,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 657264b8f62d..024c37b857c8 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud libraries-bom - 26.75.0 + 26.76.0 import pom From f498b66202aec9bceedc7fb9ed4eb962dcfdad07 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:24:19 +0000 Subject: [PATCH 1959/1979] deps: update dependency net.bytebuddy:byte-buddy to v1.18.5 (#2397) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 9f7a2a5f029d..4f2e3a6fd96b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -118,7 +118,7 @@ net.bytebuddy byte-buddy - 1.18.4 + 1.18.5 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index cf956946b8db..0ad0be82b26f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -112,7 +112,7 @@ net.bytebuddy byte-buddy - 1.18.4 + 1.18.5 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 024c37b857c8..6e677c8922dc 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -105,7 +105,7 @@ net.bytebuddy byte-buddy - 1.18.4 + 1.18.5 test From 507c255ba6a55e79855643c5c4143fd9d23f5a02 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:24:38 +0000 Subject: [PATCH 1960/1979] deps: update dependency net.bytebuddy:byte-buddy-agent to v1.18.5 (#2398) --- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4f2e3a6fd96b..4e1950396421 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -124,7 +124,7 @@ net.bytebuddy byte-buddy-agent - 1.18.4 + 1.18.5 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 0ad0be82b26f..50ad2e6a086d 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -118,7 +118,7 @@ net.bytebuddy byte-buddy-agent - 1.18.4 + 1.18.5 test diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index 6e677c8922dc..a213d6bec627 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -111,7 +111,7 @@ net.bytebuddy byte-buddy-agent - 1.18.4 + 1.18.5 test From 2f9359434f25191e5db827c9fa2c33e6493e7650 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:24:56 +0000 Subject: [PATCH 1961/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.85.0 (#2396) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index dbeb9da67497..f8aec2253efd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -220,7 +220,7 @@ com.google.cloud google-cloud-trace - 2.84.0 + 2.85.0 test From c0e7ac257707f7c5b1a895bef325e99f0f2b2e71 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:25:15 +0000 Subject: [PATCH 1962/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.85.0 (#2395) --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index f8aec2253efd..e41cbbf1acbd 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.84.0 + 2.85.0 test From af6f1c45894b2ecc83172e86f6e211f8e50074f9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 17 Feb 2026 13:25:35 +0000 Subject: [PATCH 1963/1979] chore(deps): update dependency com.google.cloud:google-cloud-spanner-jdbc to v2.35.3 (#2394) --- java-spanner-jdbc/samples/install-without-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/install-without-bom/pom.xml b/java-spanner-jdbc/samples/install-without-bom/pom.xml index 81d96f334822..80876b00da84 100644 --- a/java-spanner-jdbc/samples/install-without-bom/pom.xml +++ b/java-spanner-jdbc/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.2 + 2.35.3 From 04a251af6f582f162996ad1f3dfe305314fe93a6 Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Wed, 18 Feb 2026 06:15:50 -0500 Subject: [PATCH 1964/1979] chore: replace old spanner teams with spanner-team (#2401) --- java-spanner-jdbc/.github/CODEOWNERS | 6 +++--- java-spanner-jdbc/.repo-metadata.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/.github/CODEOWNERS b/java-spanner-jdbc/.github/CODEOWNERS index 4402cc751214..0a3279e1fef2 100644 --- a/java-spanner-jdbc/.github/CODEOWNERS +++ b/java-spanner-jdbc/.github/CODEOWNERS @@ -4,11 +4,11 @@ # For syntax help see: # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax -# The @googleapis/api-spanner-java is the default owner for changes in this repo -* @googleapis/cloud-sdk-java-team @googleapis/api-spanner-java +# The @googleapis/spanner-team is the default owner for changes in this repo +* @googleapis/cloud-sdk-java-team @googleapis/spanner-team # for handwritten libraries, keep codeowner_team in .repo-metadata.json as owner -**/*.java @googleapis/api-spanner-java +**/*.java @googleapis/spanner-team # The java-samples-reviewers team is the default owner for samples changes diff --git a/java-spanner-jdbc/.repo-metadata.json b/java-spanner-jdbc/.repo-metadata.json index 8887ec91f3d2..6564e0bbf736 100644 --- a/java-spanner-jdbc/.repo-metadata.json +++ b/java-spanner-jdbc/.repo-metadata.json @@ -10,7 +10,7 @@ "repo_short": "java-spanner-jdbc", "distribution_name": "com.google.cloud:google-cloud-spanner-jdbc", "library_type": "OTHER", - "codeowner_team": "@googleapis/api-spanner-java", + "codeowner_team": "@googleapis/spanner-team", "recommended_package": "com.google.cloud.spanner.jdbc" } From a628fbc2569af1eab47f56c2bafc6cbbbe7566c8 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Fri, 27 Feb 2026 15:51:49 +0530 Subject: [PATCH 1965/1979] fix: Fix UTC<->Timezone conversion issue for DST start and end timestamp (#2260) --- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 13 ++++++++-- .../spanner/jdbc/JdbcTypeConverterTest.java | 25 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 942be1587ea8..46a35c1a4f06 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -43,6 +43,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.List; +import java.util.TimeZone; import java.util.concurrent.TimeUnit; /** Convenience class for converting values between Java, JDBC and Cloud Spanner. */ @@ -496,10 +497,18 @@ private static java.sql.Timestamp getOrSetTimestampInCalendar( Calendar newCal = Calendar.getInstance(cal.getTimeZone()); // set the millisecond time on this calendar from the timestamp newCal.setTimeInMillis(sqlTs.getTime()); - newCal.set(Calendar.MILLISECOND, 0); + + TimeZone timeZone = newCal.getTimeZone(); + long totalMillis = newCal.getTimeInMillis(); + // to calculate the offset for DST correctly, we need to add DST savings and check if + // given epoch milli is in daylight savings time. + if (getOrSet == GetOrSetTimestampInCalendar.GET) { + totalMillis += timeZone.getRawOffset() + timeZone.getDSTSavings(); + } + // then shift the time of the calendar by the difference between UTC and the timezone of the // given calendar - int offset = newCal.getTimeZone().getOffset(newCal.getTimeInMillis()); + int offset = newCal.getTimeZone().getOffset(totalMillis); newCal.add( Calendar.MILLISECOND, getOrSet == GetOrSetTimestampInCalendar.GET ? offset : -offset); // then use that to create a sql timestamp diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index 26eaffe2d9a4..db36b47fa86a 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -51,6 +51,8 @@ import java.sql.Time; import java.sql.Timestamp; import java.text.DecimalFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -959,6 +961,29 @@ public void testDateToSqlTimestampWithCalendar() { .toSqlTimestamp()); } + @Test + public void testDateToSqlTimestampWithCalendarWithStartOfDST() { + TimeZone timeZone = TimeZone.getTimeZone("Europe/Oslo"); + + List zonedDateTimes = + Arrays.asList( + ZonedDateTime.of(2018, 3, 25, 2, 0, 0, 0, ZoneId.of("+01:00")), + ZonedDateTime.of(2018, 10, 28, 2, 0, 0, 0, ZoneId.of("+01:00"))); + + zonedDateTimes.forEach( + expected -> { + Timestamp expectedTimestamp = Timestamp.from(expected.toInstant()); + Calendar cal = Calendar.getInstance(timeZone); + Timestamp storeTimestamp = + JdbcTypeConverter.setTimestampInCalendar(expectedTimestamp, cal); + + Timestamp resultTimestamp = JdbcTypeConverter.getTimestampInCalendar(storeTimestamp, cal); + ZonedDateTime actual = resultTimestamp.toInstant().atZone(timeZone.toZoneId()); + + assertThat(actual).isEqualTo(expected.withZoneSameInstant(timeZone.toZoneId())); + }); + } + @Test public void testParseSqlTimeWithCalendar() { assertThat( From cc9535517ac7a91b098e99ec53242663747bed63 Mon Sep 17 00:00:00 2001 From: Sakthivel Subramanian <179120858+sakthivelmanii@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:25:13 +0530 Subject: [PATCH 1966/1979] fix: Fix Column Type Name for PostgreSQL ARRAY types (#2409) --- .../spanner/jdbc/AbstractJdbcWrapper.java | 7 ++++++ .../spanner/jdbc/JdbcResultSetMetaData.java | 9 ++++++- .../spanner/jdbc/AbstractJdbcWrapperTest.java | 19 ++++++++++++++ .../jdbc/JdbcResultSetMetaDataTest.java | 25 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java index 022a9a5daca3..7c387d301a4e 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapper.java @@ -80,6 +80,13 @@ static String getSpannerTypeName(Type type, Dialect dialect) { return Preconditions.checkNotNull(type).getSpannerTypeName(dialect); } + static String getSpannerColumnTypeName(Type type, Dialect dialect) { + if (dialect == Dialect.POSTGRESQL && type.getCode() == Code.ARRAY) { + return "_" + getSpannerTypeName(type.getArrayElementType(), dialect); + } + return getSpannerTypeName(type, dialect); + } + /** * Extract Spanner type name from {@link java.sql.Types} code. * diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java index f582ce45e58d..1502a97031ab 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaData.java @@ -16,7 +16,9 @@ package com.google.cloud.spanner.jdbc; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.ConnectionProperties; import com.google.common.base.Preconditions; import java.sql.Connection; @@ -192,7 +194,12 @@ public int getColumnType(int column) { @Override public String getColumnTypeName(int column) { - return spannerResultSet.getColumnType(column - 1).getCode().name(); + Type columnType = spannerResultSet.getColumnType(column - 1); + if (statement instanceof JdbcStatement) { + Dialect dialect = ((JdbcStatement) statement).getConnection().getDialect(); + return getSpannerColumnTypeName(columnType, dialect); + } + return columnType.getCode().name(); } @Override diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java index 702477f45401..f381d56586d1 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/AbstractJdbcWrapperTest.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.jdbc; +import static com.google.cloud.spanner.jdbc.AbstractJdbcWrapper.getSpannerColumnTypeName; import static com.google.cloud.spanner.jdbc.AbstractJdbcWrapper.getSpannerTypeName; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -502,5 +503,23 @@ public void testPostgreSQLTypeNames() { getSpannerTypeName(Type.array(Type.timestamp()), Dialect.POSTGRESQL)); assertEquals("jsonb[]", getSpannerTypeName(Type.array(Type.pgJsonb()), Dialect.POSTGRESQL)); assertEquals("numeric[]", getSpannerTypeName(Type.array(Type.pgNumeric()), Dialect.POSTGRESQL)); + + assertEquals("_bigint", getSpannerColumnTypeName(Type.array(Type.int64()), Dialect.POSTGRESQL)); + assertEquals("_boolean", getSpannerColumnTypeName(Type.array(Type.bool()), Dialect.POSTGRESQL)); + assertEquals( + "_double precision", + getSpannerColumnTypeName(Type.array(Type.float64()), Dialect.POSTGRESQL)); + assertEquals( + "_character varying", + getSpannerColumnTypeName(Type.array(Type.string()), Dialect.POSTGRESQL)); + assertEquals("_bytea", getSpannerColumnTypeName(Type.array(Type.bytes()), Dialect.POSTGRESQL)); + assertEquals("_date", getSpannerColumnTypeName(Type.array(Type.date()), Dialect.POSTGRESQL)); + assertEquals( + "_timestamp with time zone", + getSpannerColumnTypeName(Type.array(Type.timestamp()), Dialect.POSTGRESQL)); + assertEquals( + "_jsonb", getSpannerColumnTypeName(Type.array(Type.pgJsonb()), Dialect.POSTGRESQL)); + assertEquals( + "_numeric", getSpannerColumnTypeName(Type.array(Type.pgNumeric()), Dialect.POSTGRESQL)); } } diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java index 36996c801850..18f5de94f113 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetMetaDataTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import com.google.cloud.ByteArray; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.ResultSets; import com.google.cloud.spanner.Struct; @@ -540,6 +541,30 @@ public void getColumnTypeName() { } } + @Test + public void getColumnTypeNameForPostgreSQL() throws SQLException { + JdbcConnection connection = mock(JdbcConnection.class); + JdbcStatement statement = mock(JdbcStatement.class); + JdbcResultSet resultSet = getFooTestResultSet(statement); + when(connection.getSchema()).thenReturn(""); + when(connection.getCatalog()).thenReturn("test-database"); + when(statement.getConnection()).then(new Returns(connection)); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); + + JdbcResultSetMetaData sub = resultSet.getMetaData(); + + int index = 1; + for (TestColumn col : TEST_COLUMNS) { + if (col.type.getCode() == Type.Code.ARRAY + && col.type.getSpannerTypeName(Dialect.POSTGRESQL).contains("bool")) { + assertEquals("_boolean", sub.getColumnTypeName(index)); + } else if (col.type.getCode() == Type.Code.BOOL) { + assertEquals("boolean", sub.getColumnTypeName(index)); + } + index++; + } + } + @Test public void testIsReadOnly() { for (int i = 0; i < TEST_COLUMNS.size(); i++) { From 2bedcba91133e079829812c3dcdf88b7994caad4 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:12:25 +0000 Subject: [PATCH 1967/1979] deps: update dependency com.google.cloud:google-cloud-trace to v2.86.0 (#2408) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://redirect.github.com/googleapis/google-cloud-java) | `2.85.0` → `2.86.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-trace/2.86.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-trace/2.86.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-trace/2.85.0/2.86.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-trace/2.85.0/2.86.0?slim=true) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index e41cbbf1acbd..634c9b88ad97 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -220,7 +220,7 @@ com.google.cloud google-cloud-trace - 2.85.0 + 2.86.0 test From a2fbe8d497d95940f1deaf1efc9dda7d2f913e45 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:12:31 +0000 Subject: [PATCH 1968/1979] deps: update dependency org.springframework.boot:spring-boot to v4.0.3 (#2403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `4.0.2` → `4.0.3` | ![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot/4.0.3?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot/4.0.3?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot/4.0.2/4.0.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot/4.0.2/4.0.3?slim=true) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot) ### [`v4.0.3`](https://redirect.github.com/spring-projects/spring-boot/releases/tag/v4.0.3) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v4.0.2...v4.0.3) #### :star: New Features - Add TWENTY\_SIX to JavaVersion enum [#​49193](https://redirect.github.com/spring-projects/spring-boot/issues/49193) #### :lady\_beetle: Bug Fixes - Jackson properties may not be applied correctly to RestClients [#​49223](https://redirect.github.com/spring-projects/spring-boot/issues/49223) - ClassNotFoundException when using Actuator without spring-boot-health [#​49196](https://redirect.github.com/spring-projects/spring-boot/issues/49196) - Using the OTel and Zipkin starters together creates invalid configuration [#​49183](https://redirect.github.com/spring-projects/spring-boot/issues/49183) - Whitespace can be incorrectly removed when spring-boot-configuration-processor runs on multi-line javadoc [#​49060](https://redirect.github.com/spring-projects/spring-boot/issues/49060) - Jackson2HttpMessageConvertersConfiguration uses ConditionOn Jackson3 XMLMapper class [#​49015](https://redirect.github.com/spring-projects/spring-boot/issues/49015) - server.jetty.threads.max is ignored when using virtual threads [#​48989](https://redirect.github.com/spring-projects/spring-boot/issues/48989) - Slice test includes fail to load when using spring-boot-starter-test-classic [#​48981](https://redirect.github.com/spring-projects/spring-boot/issues/48981) - Docker credential helpers with file extensions cannot be executed on Windows [#​48979](https://redirect.github.com/spring-projects/spring-boot/issues/48979) - Java version requirement check for native image is confusing if AOT didn't run [#​48963](https://redirect.github.com/spring-projects/spring-boot/issues/48963) - TestPropertyValues.Pair.fromMapEntry(Entry\) does not comply with its nullability contract [#​48948](https://redirect.github.com/spring-projects/spring-boot/issues/48948) #### :notebook\_with\_decorative\_cover: Documentation - Couchbase and Kafka are incorrectly listed as supporting SSL with Docker Compose [#​49212](https://redirect.github.com/spring-projects/spring-boot/issues/49212) - Document that use of non idiomatic format for '`@Value`' still apply for environment variables [#​49109](https://redirect.github.com/spring-projects/spring-boot/issues/49109) - Document naming convention for custom test-scoped starters [#​49017](https://redirect.github.com/spring-projects/spring-boot/issues/49017) - Delay removal of Jackson 2 support until 4.3 at the earliest [#​49010](https://redirect.github.com/spring-projects/spring-boot/issues/49010) - LICENSE.txt and NOTICE.txt files have the wrong content in the latest releases [#​49003](https://redirect.github.com/spring-projects/spring-boot/issues/49003) - ApplicationContextAssert documents a non-existent assertion in getFailure() [#​48977](https://redirect.github.com/spring-projects/spring-boot/issues/48977) - Highlight the importance of the preStop hook when configuring Kubernetes probes [#​48946](https://redirect.github.com/spring-projects/spring-boot/issues/48946) #### :hammer: Dependency Upgrades - Upgrade to AssertJ 3.27.7 [#​49095](https://redirect.github.com/spring-projects/spring-boot/issues/49095) - Upgrade to Elasticsearch Client 9.2.5 [#​49184](https://redirect.github.com/spring-projects/spring-boot/issues/49184) - Upgrade to Groovy 5.0.4 [#​49097](https://redirect.github.com/spring-projects/spring-boot/issues/49097) - Upgrade to Hibernate 7.2.3.Final [#​49098](https://redirect.github.com/spring-projects/spring-boot/issues/49098) - Upgrade to Hibernate 7.2.4.Final [#​49167](https://redirect.github.com/spring-projects/spring-boot/issues/49167) - Upgrade to Jaybird 6.0.4 [#​49099](https://redirect.github.com/spring-projects/spring-boot/issues/49099) - Upgrade to JBoss Logging 3.6.2.Final [#​49100](https://redirect.github.com/spring-projects/spring-boot/issues/49100) - Upgrade to Jersey 4.0.2 [#​49101](https://redirect.github.com/spring-projects/spring-boot/issues/49101) - Upgrade to Jetty 12.1.6 [#​49102](https://redirect.github.com/spring-projects/spring-boot/issues/49102) - Upgrade to jOOQ 3.19.30 [#​49103](https://redirect.github.com/spring-projects/spring-boot/issues/49103) - Upgrade to JUnit Jupiter 6.0.3 [#​49233](https://redirect.github.com/spring-projects/spring-boot/issues/49233) - Upgrade to Logback 1.5.29 [#​49169](https://redirect.github.com/spring-projects/spring-boot/issues/49169) - Upgrade to Logback 1.5.32 [#​49245](https://redirect.github.com/spring-projects/spring-boot/issues/49245) - Upgrade to Micrometer 1.16.3 [#​49111](https://redirect.github.com/spring-projects/spring-boot/issues/49111) - Upgrade to Micrometer Tracing 1.6.3 [#​49112](https://redirect.github.com/spring-projects/spring-boot/issues/49112) - Upgrade to MongoDB 5.6.3 [#​49105](https://redirect.github.com/spring-projects/spring-boot/issues/49105) - Upgrade to MySQL 9.6.0 [#​49106](https://redirect.github.com/spring-projects/spring-boot/issues/49106) - Upgrade to Netty 4.2.10.Final [#​49107](https://redirect.github.com/spring-projects/spring-boot/issues/49107) - Upgrade to Postgresql 42.7.10 [#​49202](https://redirect.github.com/spring-projects/spring-boot/issues/49202) - Upgrade to Reactor Bom 2025.0.3 [#​49087](https://redirect.github.com/spring-projects/spring-boot/issues/49087) - Upgrade to Spring Data Bom 2025.1.3 [#​49088](https://redirect.github.com/spring-projects/spring-boot/issues/49088) - Upgrade to Spring Framework 7.0.5 [#​49216](https://redirect.github.com/spring-projects/spring-boot/issues/49216) - Upgrade to Spring Integration 7.0.3 [#​49217](https://redirect.github.com/spring-projects/spring-boot/issues/49217) - Upgrade to Spring Kafka 4.0.3 [#​49090](https://redirect.github.com/spring-projects/spring-boot/issues/49090) - Upgrade to Spring LDAP 4.0.2 [#​49091](https://redirect.github.com/spring-projects/spring-boot/issues/49091) - Upgrade to Spring Pulsar 2.0.3 [#​49092](https://redirect.github.com/spring-projects/spring-boot/issues/49092) - Upgrade to Spring Security 7.0.3 [#​49093](https://redirect.github.com/spring-projects/spring-boot/issues/49093) - Upgrade to Spring Session 4.0.2 [#​49094](https://redirect.github.com/spring-projects/spring-boot/issues/49094) - Upgrade to Tomcat 11.0.18 [#​49108](https://redirect.github.com/spring-projects/spring-boot/issues/49108) #### :heart: Contributors Thank you to all the contributors who worked on this release: [@​GaetanoCerciello](https://redirect.github.com/GaetanoCerciello), [@​dsyer](https://redirect.github.com/dsyer), [@​linkian209](https://redirect.github.com/linkian209), [@​nosan](https://redirect.github.com/nosan), [@​quaff](https://redirect.github.com/quaff), [@​scordio](https://redirect.github.com/scordio), and [@​srt](https://redirect.github.com/srt)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6f7b95f9e9cc..6279d1af72a2 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -79,7 +79,7 @@ org.springframework.boot spring-boot - 4.0.2 + 4.0.3 test From b1a9cfd087d43b8d4b8a9f563f77df96c303c9ca Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:12:36 +0000 Subject: [PATCH 1969/1979] deps: update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.1 (#2406) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.fasterxml.jackson.core:jackson-databind](https://redirect.github.com/FasterXML/jackson) ([source](https://redirect.github.com/FasterXML/jackson-databind)) | `2.21.0` → `2.21.1` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.fasterxml.jackson.core:jackson-databind/2.21.1?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.fasterxml.jackson.core:jackson-databind/2.21.1?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.fasterxml.jackson.core:jackson-databind/2.21.0/2.21.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.fasterxml.jackson.core:jackson-databind/2.21.0/2.21.1?slim=true) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index 6279d1af72a2..a81f393b44b2 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.21.0 + 2.21.1 From 626096d6428defed74e7c62f5810898c8f0f931b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:14:22 +0000 Subject: [PATCH 1970/1979] deps: update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.11 (#2402) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-parent](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `3.5.10` → `3.5.11` | ![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-parent/3.5.11?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-parent/3.5.11?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-parent/3.5.10/3.5.11?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-parent/3.5.10/3.5.11?slim=true) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-parent) ### [`v3.5.11`](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.10...v3.5.11) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v3.5.10...v3.5.11)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- .../samples/spring-data-mybatis/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 50ad2e6a086d..54660a523578 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.10 + 3.5.11 diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml index a213d6bec627..5836f36ecdf1 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/postgresql/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.10 + 3.5.11 From 3f6e7fc65d0c2f989dd83cb6b13196fb72278203 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:14:29 +0000 Subject: [PATCH 1971/1979] deps: update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.86.0 (#2407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.api.grpc:proto-google-cloud-trace-v1](https://redirect.github.com/googleapis/google-cloud-java) | `2.85.0` → `2.86.0` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.86.0?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.86.0?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.85.0/2.86.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.api.grpc:proto-google-cloud-trace-v1/2.85.0/2.86.0?slim=true) | --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 634c9b88ad97..58c385210b0e 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -226,7 +226,7 @@ com.google.api.grpc proto-google-cloud-trace-v1 - 2.85.0 + 2.86.0 test From e1ae5353123477669fbe4e2efd1003ba5eaff6be Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:16:23 +0000 Subject: [PATCH 1972/1979] deps: update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.3 (#2404) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [org.springframework.boot:spring-boot-starter-data-jdbc](https://spring.io/projects/spring-boot) ([source](https://redirect.github.com/spring-projects/spring-boot)) | `4.0.2` → `4.0.3` | ![age](https://developer.mend.io/api/mc/badges/age/maven/org.springframework.boot:spring-boot-starter-data-jdbc/4.0.3?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.springframework.boot:spring-boot-starter-data-jdbc/4.0.3?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.springframework.boot:spring-boot-starter-data-jdbc/4.0.2/4.0.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.springframework.boot:spring-boot-starter-data-jdbc/4.0.2/4.0.3?slim=true) | --- ### Release Notes
    spring-projects/spring-boot (org.springframework.boot:spring-boot-starter-data-jdbc) ### [`v4.0.3`](https://redirect.github.com/spring-projects/spring-boot/compare/v4.0.2...v4.0.3) [Compare Source](https://redirect.github.com/spring-projects/spring-boot/compare/v4.0.2...v4.0.3)
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index 446dca52c97c..fb713dca63dc 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -59,7 +59,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.2 + 4.0.3 diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index 4e1950396421..fa0a31bd8b0b 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -59,7 +59,7 @@ org.springframework.boot spring-boot-starter-data-jdbc - 4.0.2 + 4.0.3 From fb803624c94d5b04c1212fb2c1765107b0e887a0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:17:25 +0000 Subject: [PATCH 1973/1979] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.57.0 (#2405) --- .../.github/workflows/unmanaged_dependency_check.yaml | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg | 2 +- java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg | 2 +- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/quickperf/pom.xml | 2 +- java-spanner-jdbc/samples/snippets/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml index eccfa428c0d2..d8c413311aad 100644 --- a/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml +++ b/java-spanner-jdbc/.github/workflows/unmanaged_dependency_check.yaml @@ -14,6 +14,6 @@ jobs: shell: bash run: .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.56.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.57.0 with: bom-path: pom.xml diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg index 8449f549f05a..bd40eb90657f 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.56.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.57.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg index 360f589c1be2..9f10ecf3fe28 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.56.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.57.0" } env_vars: { diff --git a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg index 65c50c1d96aa..255806a117b4 100644 --- a/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg +++ b/java-spanner-jdbc/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.56.1" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.57.0" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 58c385210b0e..857b052e23ab 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.56.1 + 3.57.0 diff --git a/java-spanner-jdbc/samples/quickperf/pom.xml b/java-spanner-jdbc/samples/quickperf/pom.xml index a81f393b44b2..99c400000bd3 100644 --- a/java-spanner-jdbc/samples/quickperf/pom.xml +++ b/java-spanner-jdbc/samples/quickperf/pom.xml @@ -12,7 +12,7 @@ com.google.cloud sdk-platform-java-config - 3.56.1 + 3.57.0 diff --git a/java-spanner-jdbc/samples/snippets/pom.xml b/java-spanner-jdbc/samples/snippets/pom.xml index f1598e9b01b3..c683ecc6b437 100644 --- a/java-spanner-jdbc/samples/snippets/pom.xml +++ b/java-spanner-jdbc/samples/snippets/pom.xml @@ -9,7 +9,7 @@ com.google.cloud sdk-platform-java-config - 3.56.1 + 3.57.0 From 644c0816a1a061ca4c73fb0187dbcf57729d64c2 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 13:44:33 +0000 Subject: [PATCH 1974/1979] deps: update dependency com.google.cloud:google-cloud-spanner to v6.111.1 (#2410) --- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 54660a523578..2c2c813e290f 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -98,7 +98,7 @@ com.google.cloud google-cloud-spanner - 6.111.0 + 6.111.1 test-jar test From 351a974567edca6e387bb56d14ef09eb038cbfb5 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 4 Mar 2026 14:14:27 +0000 Subject: [PATCH 1975/1979] deps: update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.1 (#2411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Adoption](https://docs.renovatebot.com/merge-confidence/) | [Passing](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner-bom](https://redirect.github.com/googleapis/java-spanner) | `6.111.0` → `6.111.1` | ![age](https://developer.mend.io/api/mc/badges/age/maven/com.google.cloud:google-cloud-spanner-bom/6.111.1?slim=true) | ![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.google.cloud:google-cloud-spanner-bom/6.111.1?slim=true) | ![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.google.cloud:google-cloud-spanner-bom/6.111.0/6.111.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.google.cloud:google-cloud-spanner-bom/6.111.0/6.111.1?slim=true) | --- ### Release Notes
    googleapis/java-spanner (com.google.cloud:google-cloud-spanner-bom) ### [`v6.111.1`](https://redirect.github.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#61111-2026-03-03) [Compare Source](https://redirect.github.com/googleapis/java-spanner/compare/v6.111.0...v6.111.1) ##### Bug Fixes - Retry CreateSession also when waitForMinSessions is zero ([#​4360](https://redirect.github.com/googleapis/java-spanner/issues/4360)) ([9263972](https://redirect.github.com/googleapis/java-spanner/commit/92639722793a994032761155013e506c9693b464)) ##### Dependencies - Update dependency com.google.cloud:sdk-platform-java-config to v3.57.0 ([#​4358](https://redirect.github.com/googleapis/java-spanner/issues/4358)) ([1ce4b8e](https://redirect.github.com/googleapis/java-spanner/commit/1ce4b8e24bac44c89f742f0afb395ae4c711abfd)) - Update googleapis/sdk-platform-java action to v2.67.0 ([#​4359](https://redirect.github.com/googleapis/java-spanner/issues/4359)) ([23781d9](https://redirect.github.com/googleapis/java-spanner/commit/23781d9f05db66d033d4d9125707a9988e1697db))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/java-spanner-jdbc). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml | 2 +- java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 857b052e23ab..87775e45cc0f 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.111.0 + 6.111.1 pom import diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml index fb713dca63dc..b15cc01e31b3 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.111.0 + 6.111.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml index fa0a31bd8b0b..2272eb5ca8fa 100644 --- a/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.111.0 + 6.111.1 import pom diff --git a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml index 2c2c813e290f..5777b429a3f2 100644 --- a/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml +++ b/java-spanner-jdbc/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.111.0 + 6.111.1 import pom From 1062949447c9a267b537e0abe5ed5f5a52242af0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:24:23 +0000 Subject: [PATCH 1976/1979] chore(main): release 2.35.4 (#2400) :robot: I have created a release *beep* *boop* --- ## [2.35.4](https://togithub.com/googleapis/java-spanner-jdbc/compare/v2.35.3...v2.35.4) (2026-03-04) ### Bug Fixes * Fix Column Type Name for PostgreSQL ARRAY types ([#2409](https://togithub.com/googleapis/java-spanner-jdbc/issues/2409)) ([cc95355](https://togithub.com/googleapis/java-spanner-jdbc/commit/cc9535517ac7a91b098e99ec53242663747bed63)) * Fix UTC<->Timezone conversion issue for DST start and end timestamp ([#2260](https://togithub.com/googleapis/java-spanner-jdbc/issues/2260)) ([a628fbc](https://togithub.com/googleapis/java-spanner-jdbc/commit/a628fbc2569af1eab47f56c2bafc6cbbbe7566c8)) ### Dependencies * Update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.1 ([#2406](https://togithub.com/googleapis/java-spanner-jdbc/issues/2406)) ([b1a9cfd](https://togithub.com/googleapis/java-spanner-jdbc/commit/b1a9cfd087d43b8d4b8a9f563f77df96c303c9ca)) * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.85.0 ([#2395](https://togithub.com/googleapis/java-spanner-jdbc/issues/2395)) ([c0e7ac2](https://togithub.com/googleapis/java-spanner-jdbc/commit/c0e7ac257707f7c5b1a895bef325e99f0f2b2e71)) * Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.86.0 ([#2407](https://togithub.com/googleapis/java-spanner-jdbc/issues/2407)) ([3f6e7fc](https://togithub.com/googleapis/java-spanner-jdbc/commit/3f6e7fc65d0c2f989dd83cb6b13196fb72278203)) * Update dependency com.google.cloud:google-cloud-spanner to v6.111.1 ([#2410](https://togithub.com/googleapis/java-spanner-jdbc/issues/2410)) ([644c081](https://togithub.com/googleapis/java-spanner-jdbc/commit/644c0816a1a061ca4c73fb0187dbcf57729d64c2)) * Update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.1 ([#2411](https://togithub.com/googleapis/java-spanner-jdbc/issues/2411)) ([351a974](https://togithub.com/googleapis/java-spanner-jdbc/commit/351a974567edca6e387bb56d14ef09eb038cbfb5)) * Update dependency com.google.cloud:google-cloud-trace to v2.85.0 ([#2396](https://togithub.com/googleapis/java-spanner-jdbc/issues/2396)) ([2f93594](https://togithub.com/googleapis/java-spanner-jdbc/commit/2f9359434f25191e5db827c9fa2c33e6493e7650)) * Update dependency com.google.cloud:google-cloud-trace to v2.86.0 ([#2408](https://togithub.com/googleapis/java-spanner-jdbc/issues/2408)) ([2bedcba](https://togithub.com/googleapis/java-spanner-jdbc/commit/2bedcba91133e079829812c3dcdf88b7994caad4)) * Update dependency com.google.cloud:sdk-platform-java-config to v3.57.0 ([#2405](https://togithub.com/googleapis/java-spanner-jdbc/issues/2405)) ([fb80362](https://togithub.com/googleapis/java-spanner-jdbc/commit/fb803624c94d5b04c1212fb2c1765107b0e887a0)) * Update dependency net.bytebuddy:byte-buddy to v1.18.5 ([#2397](https://togithub.com/googleapis/java-spanner-jdbc/issues/2397)) ([f498b66](https://togithub.com/googleapis/java-spanner-jdbc/commit/f498b66202aec9bceedc7fb9ed4eb962dcfdad07)) * Update dependency net.bytebuddy:byte-buddy-agent to v1.18.5 ([#2398](https://togithub.com/googleapis/java-spanner-jdbc/issues/2398)) ([507c255](https://togithub.com/googleapis/java-spanner-jdbc/commit/507c255ba6a55e79855643c5c4143fd9d23f5a02)) * Update dependency org.springframework.boot:spring-boot to v4.0.3 ([#2403](https://togithub.com/googleapis/java-spanner-jdbc/issues/2403)) ([a2fbe8d](https://togithub.com/googleapis/java-spanner-jdbc/commit/a2fbe8d497d95940f1deaf1efc9dda7d2f913e45)) * Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.3 ([#2404](https://togithub.com/googleapis/java-spanner-jdbc/issues/2404)) ([e1ae535](https://togithub.com/googleapis/java-spanner-jdbc/commit/e1ae5353123477669fbe4e2efd1003ba5eaff6be)) * Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.11 ([#2402](https://togithub.com/googleapis/java-spanner-jdbc/issues/2402)) ([626096d](https://togithub.com/googleapis/java-spanner-jdbc/commit/626096d6428defed74e7c62f5810898c8f0f931b)) --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- java-spanner-jdbc/CHANGELOG.md | 25 ++++++++++++++++++++++ java-spanner-jdbc/README.md | 6 +++--- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/java-spanner-jdbc/CHANGELOG.md b/java-spanner-jdbc/CHANGELOG.md index 4074fcf5dc8c..eca8e75685bf 100644 --- a/java-spanner-jdbc/CHANGELOG.md +++ b/java-spanner-jdbc/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [2.35.4](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.3...v2.35.4) (2026-03-04) + + +### Bug Fixes + +* Fix Column Type Name for PostgreSQL ARRAY types ([#2409](https://github.com/googleapis/java-spanner-jdbc/issues/2409)) ([c171388](https://github.com/googleapis/java-spanner-jdbc/commit/c1713882f7d945b60aa9e305234535e0b5a37e6c)) +* Fix UTC<->Timezone conversion issue for DST start and end timestamp ([#2260](https://github.com/googleapis/java-spanner-jdbc/issues/2260)) ([14837f8](https://github.com/googleapis/java-spanner-jdbc/commit/14837f8d195a338089eca1b2bfe316f030012967)) + + +### Dependencies + +* Update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.1 ([#2406](https://github.com/googleapis/java-spanner-jdbc/issues/2406)) ([96f106e](https://github.com/googleapis/java-spanner-jdbc/commit/96f106e551d3c47a557fac2ec95aadb4d9cc1990)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.85.0 ([#2395](https://github.com/googleapis/java-spanner-jdbc/issues/2395)) ([8a214f8](https://github.com/googleapis/java-spanner-jdbc/commit/8a214f8b3ddb2c823dacc82ad1559cdf0db67004)) +* Update dependency com.google.api.grpc:proto-google-cloud-trace-v1 to v2.86.0 ([#2407](https://github.com/googleapis/java-spanner-jdbc/issues/2407)) ([b542d69](https://github.com/googleapis/java-spanner-jdbc/commit/b542d696e171b894483b8a4bff5d0c7befaddd96)) +* Update dependency com.google.cloud:google-cloud-spanner to v6.111.1 ([#2410](https://github.com/googleapis/java-spanner-jdbc/issues/2410)) ([39dd81b](https://github.com/googleapis/java-spanner-jdbc/commit/39dd81b9b456bea03a1018125c3f5db7e4ff047a)) +* Update dependency com.google.cloud:google-cloud-spanner-bom to v6.111.1 ([#2411](https://github.com/googleapis/java-spanner-jdbc/issues/2411)) ([5e636ed](https://github.com/googleapis/java-spanner-jdbc/commit/5e636edb5712b90815c14f72d0d6e8d559642550)) +* Update dependency com.google.cloud:google-cloud-trace to v2.85.0 ([#2396](https://github.com/googleapis/java-spanner-jdbc/issues/2396)) ([122545c](https://github.com/googleapis/java-spanner-jdbc/commit/122545c3b0b3c660defd9aeae37a9442a16ebd8f)) +* Update dependency com.google.cloud:google-cloud-trace to v2.86.0 ([#2408](https://github.com/googleapis/java-spanner-jdbc/issues/2408)) ([6af6e48](https://github.com/googleapis/java-spanner-jdbc/commit/6af6e48cad6c6229058d68b599d96f4cdd64df40)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.57.0 ([#2405](https://github.com/googleapis/java-spanner-jdbc/issues/2405)) ([8e54669](https://github.com/googleapis/java-spanner-jdbc/commit/8e54669eae29522a15da84f4aec819ca3305a25c)) +* Update dependency net.bytebuddy:byte-buddy to v1.18.5 ([#2397](https://github.com/googleapis/java-spanner-jdbc/issues/2397)) ([6736c63](https://github.com/googleapis/java-spanner-jdbc/commit/6736c63fda79bfc1c2071b4de64e2e6bdd70594e)) +* Update dependency net.bytebuddy:byte-buddy-agent to v1.18.5 ([#2398](https://github.com/googleapis/java-spanner-jdbc/issues/2398)) ([deaef26](https://github.com/googleapis/java-spanner-jdbc/commit/deaef26f58d865a995dc99562fa058091455bcb4)) +* Update dependency org.springframework.boot:spring-boot to v4.0.3 ([#2403](https://github.com/googleapis/java-spanner-jdbc/issues/2403)) ([37aed98](https://github.com/googleapis/java-spanner-jdbc/commit/37aed98531e986827d8e5169ae434493d81059c2)) +* Update dependency org.springframework.boot:spring-boot-starter-data-jdbc to v4.0.3 ([#2404](https://github.com/googleapis/java-spanner-jdbc/issues/2404)) ([385e930](https://github.com/googleapis/java-spanner-jdbc/commit/385e930f1d102fb3a35d300f8c838fdaf6a6617c)) +* Update dependency org.springframework.boot:spring-boot-starter-parent to v3.5.11 ([#2402](https://github.com/googleapis/java-spanner-jdbc/issues/2402)) ([f451bca](https://github.com/googleapis/java-spanner-jdbc/commit/f451bca0f6aa24a3ea0e47361797186eafac34b1)) + ## [2.35.3](https://github.com/googleapis/java-spanner-jdbc/compare/v2.35.2...v2.35.3) (2026-02-13) diff --git a/java-spanner-jdbc/README.md b/java-spanner-jdbc/README.md index 91548492a6ef..874179672ab0 100644 --- a/java-spanner-jdbc/README.md +++ b/java-spanner-jdbc/README.md @@ -20,7 +20,7 @@ If you are using Maven, add this to your pom.xml file: com.google.cloud google-cloud-spanner-jdbc - 2.35.3 + 2.35.4 ``` @@ -30,7 +30,7 @@ If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.3' +implementation 'com.google.cloud:google-cloud-spanner-jdbc:2.35.4' ``` @@ -38,7 +38,7 @@ If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.3" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner-jdbc" % "2.35.4" ``` diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 87775e45cc0f..28446e592a9c 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.4-SNAPSHOT + 2.35.4 jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index 25f5e13976ae..a32523772d1c 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.4-SNAPSHOT + 2.35.4 diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index e9569d16873c..c55e44feba08 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.3:2.35.4-SNAPSHOT +google-cloud-spanner-jdbc:2.35.4:2.35.4 From b0a017dade352421540e97ba5cf4697825521ae9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:54:23 +0000 Subject: [PATCH 1977/1979] chore(main): release 2.35.5-SNAPSHOT (#2414) :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). --- java-spanner-jdbc/pom.xml | 2 +- java-spanner-jdbc/samples/snapshot/pom.xml | 2 +- java-spanner-jdbc/versions.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index 28446e592a9c..f689e25f8de5 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/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.35.4 + 2.35.5-SNAPSHOT jar Google Cloud Spanner JDBC https://github.com/googleapis/java-spanner-jdbc diff --git a/java-spanner-jdbc/samples/snapshot/pom.xml b/java-spanner-jdbc/samples/snapshot/pom.xml index a32523772d1c..c2a919dec96f 100644 --- a/java-spanner-jdbc/samples/snapshot/pom.xml +++ b/java-spanner-jdbc/samples/snapshot/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-spanner-jdbc - 2.35.4 + 2.35.5-SNAPSHOT diff --git a/java-spanner-jdbc/versions.txt b/java-spanner-jdbc/versions.txt index c55e44feba08..e3521a6d9771 100644 --- a/java-spanner-jdbc/versions.txt +++ b/java-spanner-jdbc/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-cloud-spanner-jdbc:2.35.4:2.35.4 +google-cloud-spanner-jdbc:2.35.4:2.35.5-SNAPSHOT From 75ec5c266d8c9cdb9174dcc3ee7a6f6b8769ddda Mon Sep 17 00:00:00 2001 From: "rayudu.alp" Date: Mon, 23 Mar 2026 15:05:17 +0530 Subject: [PATCH 1978/1979] fix: fix getLong on NUMERIC (#2420) * fix: fix getLong on NUMERIC * address review comments --- .../cloud/spanner/jdbc/JdbcResultSet.java | 12 +- .../cloud/spanner/jdbc/JdbcTypeConverter.java | 31 ++- .../ConcurrentTransactionOnEmulatorTest.java | 2 +- .../cloud/spanner/jdbc/JdbcResultSetTest.java | 216 ++++++++++------ .../spanner/jdbc/JdbcTypeConverterTest.java | 49 +++- .../spanner/jdbc/it/ITJdbcNumericTest.java | 242 ++++++++++++++++++ 6 files changed, 454 insertions(+), 98 deletions(-) create mode 100644 java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcNumericTest.java diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java index d9bfe818b729..da0620ee6f9f 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcResultSet.java @@ -307,7 +307,9 @@ public byte getByte(int columnIndex) throws SQLException { case ENUM: return isNull ? (byte) 0 : checkedCastToByte(spanner.getLong(spannerIndex)); case NUMERIC: - return isNull ? (byte) 0 : checkedCastToByte(spanner.getBigDecimal(spannerIndex)); + return isNull + ? (byte) 0 + : checkedCastToByte(spanner.getBigDecimal(spannerIndex).toBigInteger()); case PG_NUMERIC: return isNull ? (byte) 0 @@ -354,7 +356,9 @@ public short getShort(int columnIndex) throws SQLException { } return isNull ? 0 : checkedCastToShort(spanner.getLong(spannerIndex)); case NUMERIC: - return isNull ? 0 : checkedCastToShort(spanner.getBigDecimal(spannerIndex)); + return isNull + ? (short) 0 + : checkedCastToShort(spanner.getBigDecimal(spannerIndex).toBigInteger()); case PG_NUMERIC: return isNull ? 0 @@ -395,7 +399,7 @@ public int getInt(int columnIndex) throws SQLException { case ENUM: return isNull ? 0 : checkedCastToInt(spanner.getLong(spannerIndex)); case NUMERIC: - return isNull ? 0 : checkedCastToInt(spanner.getBigDecimal(spannerIndex)); + return isNull ? 0 : checkedCastToInt(spanner.getBigDecimal(spannerIndex).toBigInteger()); case PG_NUMERIC: return isNull ? 0 @@ -432,7 +436,7 @@ public long getLong(int columnIndex) throws SQLException { case ENUM: return isNull ? 0L : spanner.getLong(spannerIndex); case NUMERIC: - return isNull ? 0 : checkedCastToLong(parseBigDecimal(spanner.getString(spannerIndex))); + return isNull ? 0L : checkedCastToLong(spanner.getBigDecimal(spannerIndex).toBigInteger()); case PG_NUMERIC: return isNull ? 0L diff --git a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java index 46a35c1a4f06..8aee7692d6a4 100644 --- a/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java +++ b/java-spanner-jdbc/src/main/java/com/google/cloud/spanner/jdbc/JdbcTypeConverter.java @@ -116,39 +116,55 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx } if (type.getCode() == Code.FLOAT64) return (Double) value != 0d; if (type.getCode() == Code.NUMERIC) return !value.equals(BigDecimal.ZERO); + if (type.getCode() == Code.PG_NUMERIC) + return !AbstractJdbcWrapper.parseBigDecimal((String) value).equals(BigDecimal.ZERO); } if (targetType.equals(BigDecimal.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigDecimal.ONE : BigDecimal.ZERO; if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return BigDecimal.valueOf((Long) value); if (type.getCode() == Code.NUMERIC) return value; + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.parseBigDecimal((String) value); } if (targetType.equals(Long.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1L : 0L; if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return value; if (type.getCode() == Code.NUMERIC) - return AbstractJdbcWrapper.checkedCastToLong((BigDecimal) value); + return AbstractJdbcWrapper.checkedCastToLong(((BigDecimal) value).toBigInteger()); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.checkedCastToLong( + AbstractJdbcWrapper.parseBigDecimal((String) value).toBigInteger()); } if (targetType.equals(Integer.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return AbstractJdbcWrapper.checkedCastToInt((Long) value); if (type.getCode() == Code.NUMERIC) - return AbstractJdbcWrapper.checkedCastToInt((BigDecimal) value); + return AbstractJdbcWrapper.checkedCastToInt(((BigDecimal) value).toBigInteger()); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.checkedCastToInt( + AbstractJdbcWrapper.parseBigDecimal((String) value).toBigInteger()); } if (targetType.equals(Short.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return AbstractJdbcWrapper.checkedCastToShort((Long) value); if (type.getCode() == Code.NUMERIC) - return AbstractJdbcWrapper.checkedCastToShort((BigDecimal) value); + return AbstractJdbcWrapper.checkedCastToShort(((BigDecimal) value).toBigInteger()); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.checkedCastToShort( + AbstractJdbcWrapper.parseBigDecimal((String) value).toBigInteger()); } if (targetType.equals(Byte.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? 1 : 0; if (type.getCode() == Code.INT64 || type.getCode() == Code.ENUM) return AbstractJdbcWrapper.checkedCastToByte((Long) value); if (type.getCode() == Code.NUMERIC) - return AbstractJdbcWrapper.checkedCastToByte((BigDecimal) value); + return AbstractJdbcWrapper.checkedCastToByte(((BigDecimal) value).toBigInteger()); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.checkedCastToByte( + AbstractJdbcWrapper.parseBigDecimal((String) value).toBigInteger()); } if (targetType.equals(BigInteger.class)) { if (type.getCode() == Code.BOOL) return (Boolean) value ? BigInteger.ONE : BigInteger.ZERO; @@ -156,6 +172,9 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx return BigInteger.valueOf((Long) value); if (type.getCode() == Code.NUMERIC) return AbstractJdbcWrapper.checkedCastToBigInteger((BigDecimal) value); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.checkedCastToBigInteger( + AbstractJdbcWrapper.parseBigDecimal((String) value)); } if (targetType.equals(Float.class)) { if (type.getCode() == Code.BOOL) @@ -166,6 +185,8 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx if (type.getCode() == Code.FLOAT64) return AbstractJdbcWrapper.checkedCastToFloat((Double) value); if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).floatValue(); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.parseFloat((String) value); } if (targetType.equals(Double.class)) { if (type.getCode() == Code.BOOL) @@ -174,6 +195,8 @@ static Object convert(Object value, Type type, Class targetType) throws SQLEx return value; } if (type.getCode() == Code.NUMERIC) return ((BigDecimal) value).doubleValue(); + if (type.getCode() == Code.PG_NUMERIC) + return AbstractJdbcWrapper.parseDouble((String) value); } if (targetType.equals(java.sql.Date.class)) { if (type.getCode() == Code.DATE) return value; diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java index 74a00503802c..eb38f9cc0e7d 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConcurrentTransactionOnEmulatorTest.java @@ -57,7 +57,7 @@ public static void startEmulator() { new GenericContainer<>( DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:latest")) .withExposedPorts(9010) - .waitingFor(Wait.forListeningPorts(9010)); + .waitingFor(Wait.forLogMessage(".*gRPC server listening at.*\\n", 1)); emulator.start(); properties = new Properties(); properties.setProperty("autoConfigEmulator", "true"); diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java index 67b0cfd2305d..4aac4e9ea79b 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcResultSetTest.java @@ -141,6 +141,12 @@ public class JdbcResultSetTest { private static final BigDecimal NUMERIC_VALUE = new BigDecimal("3.14"); private static final int NUMERIC_COLINDEX_NULL = 25; private static final int NUMERIC_COLINDEX_NOTNULL = 26; + private static final String PG_NUMERIC_COL_NULL = "PG_NUMERIC_COL_NULL"; + private static final String PG_NUMERIC_COL_NOT_NULL = "PG_NUMERIC_COL_NOT_NULL"; + private static final String PG_NUMERIC_COL_NAN = "PG_NUMERIC_COL_NAN"; + private static final int PG_NUMERIC_COLINDEX_NULL = 44; + private static final int PG_NUMERIC_COLINDEX_NOTNULL = 45; + private static final int PG_NUMERIC_COLINDEX_NAN = 46; private static final String JSON_COL_NULL = "JSON_COL_NULL"; private static final String JSON_COL_NOT_NULL = "JSON_COL_NOT_NULL"; private static final int JSON_COLINDEX_NULL = 27; @@ -237,7 +243,10 @@ static ResultSet getMockResultSet() { Type.array(Type.proto(SingerInfo.getDescriptor().getFullName()))), StructField.of( PROTO_ENUM_ARRAY_COL, - Type.array(Type.protoEnum(Genre.getDescriptor().getFullName())))), + Type.array(Type.protoEnum(Genre.getDescriptor().getFullName()))), + StructField.of(PG_NUMERIC_COL_NULL, Type.pgNumeric()), + StructField.of(PG_NUMERIC_COL_NOT_NULL, Type.pgNumeric()), + StructField.of(PG_NUMERIC_COL_NAN, Type.pgNumeric())), Collections.singletonList( Struct.newBuilder() .set(STRING_COL_NULL) @@ -327,6 +336,12 @@ static ResultSet getMockResultSet() { PROTO_MSG_ARRAY_VALUE, SingerInfo.getDescriptor().getFullName()) .set(PROTO_ENUM_ARRAY_COL) .toProtoEnumArray(PROTO_ENUM_ARRAY_VALUE, Genre.getDescriptor().getFullName()) + .set(PG_NUMERIC_COL_NULL) + .to(Value.pgNumeric((String) null)) + .set(PG_NUMERIC_COL_NOT_NULL) + .to(Value.pgNumeric("3.14")) + .set(PG_NUMERIC_COL_NAN) + .to(Value.pgNumeric("NaN")) .build())); } @@ -541,20 +556,14 @@ public void testGetBooleanIndexForString() throws SQLException { @Test public void testGetBooleanIndexForDate() { - try { - subject.getBoolean(DATE_COLINDEX_NOTNULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } - try { - subject.getBoolean(DATE_COLINDEX_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = + assertThrows(SQLException.class, () -> subject.getBoolean(DATE_COLINDEX_NOTNULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + + e = assertThrows(SQLException.class, () -> subject.getBoolean(DATE_COLINDEX_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -594,15 +603,85 @@ public void testGetLongIndexForFloat64() throws SQLException { assertTrue(subject.wasNull()); } + @Test + public void testGetIntegerTypesOnNumeric() throws SQLException { + assertEquals((byte) 0, subject.getByte(NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals((byte) 3, subject.getByte(NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals((short) 0, subject.getShort(NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals((short) 3, subject.getShort(NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals(0, subject.getInt(NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(3, subject.getInt(NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals(0L, subject.getLong(NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(3L, subject.getLong(NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntegerTypesOnPgNumeric() throws SQLException { + assertEquals((byte) 0, subject.getByte(PG_NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals((byte) 3, subject.getByte(PG_NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals((short) 0, subject.getShort(PG_NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals((short) 3, subject.getShort(PG_NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals(0, subject.getInt(PG_NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(3, subject.getInt(PG_NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + + assertEquals(0L, subject.getLong(PG_NUMERIC_COLINDEX_NULL)); + assertTrue(subject.wasNull()); + assertEquals(3L, subject.getLong(PG_NUMERIC_COLINDEX_NOTNULL)); + assertFalse(subject.wasNull()); + } + + @Test + public void testGetIntegerTypesOnPgNumericNaN() throws SQLException { + assertTrue(Double.isNaN(subject.getDouble(PG_NUMERIC_COLINDEX_NAN))); + assertTrue(Float.isNaN(subject.getFloat(PG_NUMERIC_COLINDEX_NAN))); + assertEquals("NaN", subject.getString(PG_NUMERIC_COLINDEX_NAN)); + SQLException e = + assertThrows(SQLException.class, () -> subject.getByte(PG_NUMERIC_COLINDEX_NAN)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + + e = assertThrows(SQLException.class, () -> subject.getShort(PG_NUMERIC_COLINDEX_NAN)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + + e = assertThrows(SQLException.class, () -> subject.getInt(PG_NUMERIC_COLINDEX_NAN)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + + e = assertThrows(SQLException.class, () -> subject.getLong(PG_NUMERIC_COLINDEX_NAN)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + + e = assertThrows(SQLException.class, () -> subject.getBigDecimal(PG_NUMERIC_COLINDEX_NAN)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); + } + @Test public void testGetLongIndexForString() { - try { - subject.getLong(STRING_COLINDEX_NOTNULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); - } + SQLException e = + assertThrows(SQLException.class, () -> subject.getLong(STRING_COLINDEX_NOTNULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -620,13 +699,10 @@ public void testGetLongIndexForNullString() throws SQLException { @Test public void testGetLongIndexForTimestamp() { - try { - subject.getLong(TIMESTAMP_COLINDEX_NOTNULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); - } + SQLException e = + assertThrows(SQLException.class, () -> subject.getLong(TIMESTAMP_COLINDEX_NOTNULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -664,13 +740,10 @@ public void testGetDoubleIndexFromInt64() throws SQLException { @Test public void testGetDoubleIndexFromTimestamp() { - try { - subject.getDouble(TIMESTAMP_COLINDEX_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); - } + SQLException e = + assertThrows(SQLException.class, () -> subject.getDouble(TIMESTAMP_COLINDEX_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @SuppressWarnings("deprecation") @@ -800,13 +873,9 @@ public void testGetDateIndexFromTimestamp() throws SQLException { @Test public void testGetDateIndexFromInt64() { - try { - subject.getDate(LONG_COLINDEX_NOTNULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getDate(LONG_COLINDEX_NOTNULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1227,13 +1296,9 @@ public void testGetNullByteIndex() throws SQLException { assertTrue(subject.wasNull()); assertEquals(0, subject.getByte(STRING_COLINDEX_NULL)); assertTrue(subject.wasNull()); - try { - subject.getByte(TIMESTAMP_COL_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getByte(TIMESTAMP_COL_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1265,13 +1330,9 @@ public void testGetShortIndexFromBoolean() throws SQLException { @Test public void testGetShortIndexFromBytes() { - try { - subject.getShort(BYTES_COL_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getShort(BYTES_COL_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1284,13 +1345,9 @@ public void testGetNullShortIndex() throws SQLException { assertTrue(subject.wasNull()); assertEquals(0, subject.getShort(STRING_COLINDEX_NULL)); assertTrue(subject.wasNull()); - try { - subject.getShort(TIMESTAMP_COL_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getShort(TIMESTAMP_COL_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1323,13 +1380,9 @@ public void testGetIntIndexFromBoolean() throws SQLException { @Test public void testGetIntIndexFromTimestamp() { - try { - subject.getInt(TIMESTAMP_COL_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getInt(TIMESTAMP_COL_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1342,13 +1395,9 @@ public void testGetNullIntIndex() throws SQLException { assertTrue(subject.wasNull()); assertEquals(0, subject.getInt(STRING_COLINDEX_NULL)); assertTrue(subject.wasNull()); - try { - subject.getInt(TIMESTAMP_COL_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); - } + SQLException e = assertThrows(SQLException.class, () -> subject.getInt(TIMESTAMP_COL_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test @@ -1387,13 +1436,10 @@ public void testGetFloatIndexFromInt64() throws SQLException { @Test public void testGetFloatIndexFromTimestamp() { - try { - subject.getFloat(TIMESTAMP_COLINDEX_NULL); - fail("missing expected SQLException"); - } catch (SQLException e) { - assertTrue(e instanceof JdbcSqlException); - assertEquals(((JdbcSqlException) e).getCode(), Code.INVALID_ARGUMENT); - } + SQLException e = + assertThrows(SQLException.class, () -> subject.getFloat(TIMESTAMP_COLINDEX_NULL)); + assertTrue(e instanceof JdbcSqlException); + assertEquals(Code.INVALID_ARGUMENT, ((JdbcSqlException) e).getCode()); } @Test diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java index db36b47fa86a..2d3727970561 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/JdbcTypeConverterTest.java @@ -452,15 +452,13 @@ public void testConvertNumeric() throws SQLException { assertThat(convert(d, Type.numeric(), String.class)).isEqualTo(String.valueOf(d)); assertThat(convert(d, Type.numeric(), Boolean.class)).isEqualTo(!d.equals(BigDecimal.ZERO)); if (d.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0 - || d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0 - || d.scale() > 0) { + || d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0) { assertConvertThrows(d, Type.numeric(), Long.class, Code.OUT_OF_RANGE); } else { assertThat(convert(d, Type.numeric(), Long.class)).isEqualTo(d.longValue()); } if (d.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) > 0 - || d.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) < 0 - || d.scale() > 0) { + || d.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) < 0) { assertConvertThrows(d, Type.numeric(), Integer.class, Code.OUT_OF_RANGE); } else { assertThat(convert(d, Type.numeric(), Integer.class)).isEqualTo(d.intValue()); @@ -468,6 +466,49 @@ public void testConvertNumeric() throws SQLException { } } + @Test + public void testConvertPgNumeric() throws SQLException { + BigDecimal[] testValues = + new BigDecimal[] { + BigDecimal.ZERO, + BigDecimal.ONE.negate(), + BigDecimal.ONE, + BigDecimal.valueOf(Double.MIN_VALUE), + BigDecimal.valueOf(Double.MAX_VALUE), + BigDecimal.valueOf(Float.MIN_VALUE), + BigDecimal.valueOf(Float.MAX_VALUE), + BigDecimal.valueOf(Float.MAX_VALUE + 1D) + }; + for (BigDecimal d : testValues) { + String strVal = String.valueOf(d); + assertThat(convert(strVal, Type.pgNumeric(), BigDecimal.class)).isEqualTo(d); + assertThat(convert(strVal, Type.pgNumeric(), Double.class)).isEqualTo(d.doubleValue()); + assertThat(convert(strVal, Type.pgNumeric(), Float.class)).isEqualTo(d.floatValue()); + assertThat(convert(strVal, Type.pgNumeric(), String.class)).isEqualTo(strVal); + assertThat(convert(strVal, Type.pgNumeric(), Boolean.class)) + .isEqualTo(!d.equals(BigDecimal.ZERO)); + if (d.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0 + || d.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0) { + assertConvertThrows(strVal, Type.pgNumeric(), Long.class, Code.OUT_OF_RANGE); + } else { + assertThat(convert(strVal, Type.pgNumeric(), Long.class)).isEqualTo(d.longValue()); + } + if (d.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) > 0 + || d.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) < 0) { + assertConvertThrows(strVal, Type.pgNumeric(), Integer.class, Code.OUT_OF_RANGE); + } else { + assertThat(convert(strVal, Type.pgNumeric(), Integer.class)).isEqualTo(d.intValue()); + } + } + + assertThat(convert("NaN", Type.pgNumeric(), Float.class)).isEqualTo(Float.NaN); + assertThat(convert("NaN", Type.pgNumeric(), Double.class)).isEqualTo(Double.NaN); + assertThat(convert("NaN", Type.pgNumeric(), String.class)).isEqualTo("NaN"); + assertConvertThrows("NaN", Type.pgNumeric(), Long.class, Code.INVALID_ARGUMENT); + assertConvertThrows("NaN", Type.pgNumeric(), Integer.class, Code.INVALID_ARGUMENT); + assertConvertThrows("NaN", Type.pgNumeric(), BigDecimal.class, Code.INVALID_ARGUMENT); + } + private void assertConvertThrows(Object t, Type type, Class destinationType, Code code) throws SQLException { try { diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcNumericTest.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcNumericTest.java new file mode 100644 index 000000000000..9706348ffc3b --- /dev/null +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/it/ITJdbcNumericTest.java @@ -0,0 +1,242 @@ +/* + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spanner.jdbc.it; + +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl; +import com.google.cloud.spanner.testing.RemoteSpannerHelper; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITJdbcNumericTest { + + @ClassRule public static JdbcIntegrationTestEnv env = new JdbcIntegrationTestEnv(); + + private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(10); + private static RemoteSpannerHelper testHelper; + private static Database database; + private static String url; + + @BeforeClass + public static void setup() throws Exception { + testHelper = env.getTestHelper(); + final String projectId = testHelper.getInstanceId().getProject(); + final String instanceId = testHelper.getInstanceId().getInstance(); + final String databaseId = testHelper.getUniqueDatabaseId(); + final DatabaseAdminClient databaseAdminClient = testHelper.getClient().getDatabaseAdminClient(); + final Database databaseToCreate = + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) + .build(); + final String host = SpannerTestHost.getHost(); + + database = + databaseAdminClient + .createDatabase(databaseToCreate, Collections.emptyList()) + .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + url = "jdbc:cloudspanner://" + host + "/" + database.getId(); + if (isUsingEmulator()) { + url += "?usePlainText=true"; + } + } + + @AfterClass + public static void teardown() { + if (database != null) { + database.drop(); + } + ConnectionOptions.closeSpanner(); + } + + @Test + public void testResultSet() throws SQLException { + final String table = testHelper.getUniqueDatabaseId(); + final String positiveBigNumeric = "99999999999999999999999999999.999999999"; + final String negativeBigNumeric = "-99999999999999999999999999999.999999999"; + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement()) { + statement.executeUpdate( + "CREATE TABLE " + table + " (id INT64, col1 NUMERIC) PRIMARY KEY (id)"); + statement.executeUpdate( + "INSERT INTO " + + table + + " (id, col1) VALUES" + + " (1, NUMERIC '1.23')," + + " (2, null)," + + " (3, NUMERIC '" + + positiveBigNumeric + + "')," + + " (4, NUMERIC '" + + negativeBigNumeric + + "')"); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals((byte) 1, resultSet.getByte("col1")); + assertEquals((short) 1, resultSet.getShort("col1")); + assertEquals(1, resultSet.getInt("col1")); + assertEquals(1L, resultSet.getLong("col1")); + assertEquals(1.23F, resultSet.getFloat("col1"), 0.001F); + assertEquals(1.23D, resultSet.getDouble("col1"), 0.001D); + assertEquals(new BigDecimal("1.23"), resultSet.getBigDecimal("col1")); + assertEquals(new BigDecimal("1.23"), resultSet.getObject("col1")); + assertEquals(Value.numeric(new BigDecimal("1.23")), resultSet.getObject("col1", Value.class)); + + resultSet.next(); + assertNull(resultSet.getString("col1")); + assertEquals((byte) 0, resultSet.getByte("col1")); + assertEquals((short) 0, resultSet.getShort("col1")); + assertEquals(0, resultSet.getInt("col1")); + assertEquals(0L, resultSet.getLong("col1")); + assertEquals(0F, resultSet.getFloat("col1"), 0F); + assertEquals(0D, resultSet.getDouble("col1"), 0D); + assertNull(resultSet.getBigDecimal("col1")); + assertNull(resultSet.getObject("col1")); + assertNull(resultSet.getObject("col1", Value.class)); + + resultSet.next(); + assertEquals(positiveBigNumeric, resultSet.getString("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getByte("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getShort("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getInt("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getLong("col1")); + assertEquals(Float.parseFloat(positiveBigNumeric), resultSet.getFloat("col1"), 0F); + assertEquals(Double.parseDouble(positiveBigNumeric), resultSet.getDouble("col1"), 0D); + assertEquals(new BigDecimal(positiveBigNumeric), resultSet.getBigDecimal("col1")); + assertEquals(new BigDecimal(positiveBigNumeric), resultSet.getObject("col1")); + assertEquals( + Value.numeric(new BigDecimal(positiveBigNumeric)), + resultSet.getObject("col1", Value.class)); + + resultSet.next(); + assertEquals(negativeBigNumeric, resultSet.getString("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getByte("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getShort("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getInt("col1")); + assertThrows(JdbcSqlExceptionImpl.class, () -> resultSet.getLong("col1")); + assertEquals(Float.parseFloat(negativeBigNumeric), resultSet.getFloat("col1"), 0F); + assertEquals(Double.parseDouble(negativeBigNumeric), resultSet.getDouble("col1"), 0D); + assertEquals(new BigDecimal(negativeBigNumeric), resultSet.getBigDecimal("col1")); + assertEquals(new BigDecimal(negativeBigNumeric), resultSet.getObject("col1")); + assertEquals( + Value.numeric(new BigDecimal(negativeBigNumeric)), + resultSet.getObject("col1", Value.class)); + + // Just verify that the getColumns method works + try (ResultSet columns = connection.getMetaData().getColumns(null, null, null, null)) { + //noinspection StatementWithEmptyBody + while (columns.next()) { + // ignore + } + } + } + } + + @Test + public void testPreparedStatement() throws Exception { + final String table = testHelper.getUniqueDatabaseId(); + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); ) { + statement.executeUpdate( + "CREATE TABLE " + table + " (id INT64, col1 NUMERIC) PRIMARY KEY (id)"); + } + + try (Connection connection = DriverManager.getConnection(url); + PreparedStatement preparedStatement = + connection.prepareStatement( + "INSERT INTO " + + table + + " (id, col1) VALUES" + + " (1, ?)," + + " (2, ?)," + + " (3, ?)," + + " (4, ?)," + + " (5, ?)," + + " (8, ?)," + + " (9, ?)," + + " (10, ?)," + + " (11, ?)," + + " (12, ?)," + + " (15, ?)," + + " (16, ?)")) { + + preparedStatement.setNull(1, Types.NUMERIC); + + preparedStatement.setByte(2, (byte) 1); + preparedStatement.setShort(3, (short) 1); + preparedStatement.setInt(4, 1); + preparedStatement.setLong(5, 1L); + preparedStatement.setBigDecimal(6, new BigDecimal("1")); + preparedStatement.setObject(7, (byte) 1); + preparedStatement.setObject(8, (short) 1); + preparedStatement.setObject(9, 1); + preparedStatement.setObject(10, 1L); + preparedStatement.setObject(11, new BigDecimal("1")); + preparedStatement.setObject(12, Value.numeric(new BigDecimal("1"))); + + final int updateCount = preparedStatement.executeUpdate(); + assertEquals(12, updateCount); + } + + try (Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " ORDER BY id")) { + resultSet.next(); + assertNull(resultSet.getObject("col1")); + + for (int i = 2; i <= 12; i++) { + resultSet.next(); + assertEquals(Value.numeric(new BigDecimal("1")), resultSet.getObject("col1", Value.class)); + } + } + } +} From cfa412890e6eacfd245f4fa1a36d1b6b208c2f4c Mon Sep 17 00:00:00 2001 From: Tomo Suzuki Date: Mon, 23 Mar 2026 15:39:56 +0000 Subject: [PATCH 1979/1979] chore: manual fixes for java-spanner-jdbc --- .github/workflows/java-spanner-jdbc-ci.yaml | 4 ++++ ...bc-integration-tests-against-emulator.yaml | 11 ++++++---- .../java-spanner-jdbc-quickperf.yaml | 2 +- .../java-spanner-jdbc-sample-tests.yml | 2 +- ...-spanner-jdbc-spring-data-jdbc-sample.yaml | 4 ++-- ...anner-jdbc-spring-data-mybatis-sample.yaml | 4 ++-- .../spanner-jdbc-graalvm-native-presubmit.cfg | 7 ++++++- .../presubmit/spanner-jdbc-integration.cfg | 2 +- java-spanner-jdbc/pom.xml | 20 +++++++++---------- .../ConnectionPropertiesFileGenerator.java | 4 ++-- 10 files changed, 35 insertions(+), 25 deletions(-) diff --git a/.github/workflows/java-spanner-jdbc-ci.yaml b/.github/workflows/java-spanner-jdbc-ci.yaml index d55e400537fb..03e2c8a8f4a1 100644 --- a/.github/workflows/java-spanner-jdbc-ci.yaml +++ b/.github/workflows/java-spanner-jdbc-ci.yaml @@ -129,6 +129,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: actions/setup-java@v4 with: distribution: temurin @@ -137,3 +139,5 @@ jobs: - run: .kokoro/build.sh env: JOB_TYPE: lint + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} diff --git a/.github/workflows/java-spanner-jdbc-integration-tests-against-emulator.yaml b/.github/workflows/java-spanner-jdbc-integration-tests-against-emulator.yaml index 6c8032676b52..cddffc081038 100644 --- a/.github/workflows/java-spanner-jdbc-integration-tests-against-emulator.yaml +++ b/.github/workflows/java-spanner-jdbc-integration-tests-against-emulator.yaml @@ -19,7 +19,7 @@ jobs: filters: | library: - 'java-spanner-jdbc/**' - units: + tests-against-emulator: needs: filter if: ${{ needs.filter.outputs.library == 'true' }} runs-on: ubuntu-latest @@ -36,11 +36,14 @@ jobs: - uses: actions/setup-java@v5 with: distribution: temurin - java-version: 8 + java-version: 17 - run: java -version - - run: .kokoro/build.sh - - run: mvn -B -Dspanner.testenv.instance="" -Penable-integration-tests -DtrimStackTrace=false -Dclirr.skip=true -Denforcer.skip=true -fae verify + - name: Install dependencies for the integration test + run: .kokoro/build.sh env: JOB_TYPE: test + - run: mvn -B -Dspanner.testenv.instance="" -Penable-integration-tests -DtrimStackTrace=false -Dclirr.skip=true -Denforcer.skip=true -fae verify + working-directory: java-spanner-jdbc + env: SPANNER_EMULATOR_HOST: localhost:9010 GOOGLE_CLOUD_PROJECT: emulator-test-project diff --git a/.github/workflows/java-spanner-jdbc-quickperf.yaml b/.github/workflows/java-spanner-jdbc-quickperf.yaml index 2fe97a6507d8..df72be92aa90 100644 --- a/.github/workflows/java-spanner-jdbc-quickperf.yaml +++ b/.github/workflows/java-spanner-jdbc-quickperf.yaml @@ -43,4 +43,4 @@ jobs: java-version: 17 - name: Run tests run: mvn test - working-directory: samples/quickperf + working-directory: java-spanner-jdbc/samples/quickperf diff --git a/.github/workflows/java-spanner-jdbc-sample-tests.yml b/.github/workflows/java-spanner-jdbc-sample-tests.yml index bed6bf92164a..b3f74ed088b8 100644 --- a/.github/workflows/java-spanner-jdbc-sample-tests.yml +++ b/.github/workflows/java-spanner-jdbc-sample-tests.yml @@ -43,4 +43,4 @@ jobs: java-version: 8 - name: Run sample tests run: mvn --quiet --batch-mode test - working-directory: samples/snippets + working-directory: java-spanner-jdbc/samples/snippets diff --git a/.github/workflows/java-spanner-jdbc-spring-data-jdbc-sample.yaml b/.github/workflows/java-spanner-jdbc-spring-data-jdbc-sample.yaml index 4a5a721c4162..78e014263f6c 100644 --- a/.github/workflows/java-spanner-jdbc-spring-data-jdbc-sample.yaml +++ b/.github/workflows/java-spanner-jdbc-spring-data-jdbc-sample.yaml @@ -43,7 +43,7 @@ jobs: java-version: 17 - name: Run tests on GoogleSQL run: mvn test - working-directory: samples/spring-data-jdbc/googlesql + working-directory: java-spanner-jdbc/samples/spring-data-jdbc/googlesql - name: Run tests on PostgreSQL run: mvn test - working-directory: samples/spring-data-jdbc/postgresql + working-directory: java-spanner-jdbc/samples/spring-data-jdbc/postgresql diff --git a/.github/workflows/java-spanner-jdbc-spring-data-mybatis-sample.yaml b/.github/workflows/java-spanner-jdbc-spring-data-mybatis-sample.yaml index ab12db64a450..3673de7259cc 100644 --- a/.github/workflows/java-spanner-jdbc-spring-data-mybatis-sample.yaml +++ b/.github/workflows/java-spanner-jdbc-spring-data-mybatis-sample.yaml @@ -43,7 +43,7 @@ jobs: java-version: 17 - name: Run GoogleSQL sample tests run: mvn test - working-directory: samples/spring-data-mybatis/googlesql + working-directory: java-spanner-jdbc/samples/spring-data-mybatis/googlesql - name: Run PostgreSQL sample tests run: mvn test - working-directory: samples/spring-data-mybatis/postgresql + working-directory: java-spanner-jdbc/samples/spring-data-mybatis/postgresql diff --git a/.kokoro/presubmit/spanner-jdbc-graalvm-native-presubmit.cfg b/.kokoro/presubmit/spanner-jdbc-graalvm-native-presubmit.cfg index 42fc899f0ea2..0884a6087c90 100644 --- a/.kokoro/presubmit/spanner-jdbc-graalvm-native-presubmit.cfg +++ b/.kokoro/presubmit/spanner-jdbc-graalvm-native-presubmit.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.57.0" + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.57.0" # {x-version-update:google-cloud-shared-dependencies:current} } env_vars: { @@ -36,3 +36,8 @@ env_vars: { key: "BUILD_SUBDIR" value: "java-spanner-jdbc" } + +env_vars: { + key: "INTEGRATION_TEST_ARGS" + value: "-Dtest=com.google.cloud.spanner.jdbc.it.**" +} \ No newline at end of file diff --git a/.kokoro/presubmit/spanner-jdbc-integration.cfg b/.kokoro/presubmit/spanner-jdbc-integration.cfg index 81e1f13064b3..cd2d91941676 100644 --- a/.kokoro/presubmit/spanner-jdbc-integration.cfg +++ b/.kokoro/presubmit/spanner-jdbc-integration.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/java8" + value: "gcr.io/cloud-devrel-kokoro-resources/java11" } env_vars: { diff --git a/java-spanner-jdbc/pom.xml b/java-spanner-jdbc/pom.xml index c1fd2c4ffbff..7469a5e16faa 100644 --- a/java-spanner-jdbc/pom.xml +++ b/java-spanner-jdbc/pom.xml @@ -59,13 +59,6 @@ - - com.google.cloud - google-cloud-spanner-bom - 6.111.1 - pom - import - io.opencensus opencensus-api @@ -103,6 +96,7 @@ com.google.cloud google-cloud-spanner + 6.112.1-SNAPSHOT io.grpc @@ -143,6 +137,7 @@ com.google.api.grpc proto-google-cloud-spanner-v1 + 6.112.1-SNAPSHOT io.opentelemetry @@ -152,6 +147,7 @@ com.google.cloud google-cloud-spanner + 6.112.1-SNAPSHOT test-jar test @@ -207,13 +203,13 @@ com.google.cloud google-cloud-trace - 2.87.0 + 2.89.0-SNAPSHOT test com.google.api.grpc proto-google-cloud-trace-v1 - 2.87.0 + 2.89.0-SNAPSHOT test @@ -345,10 +341,12 @@
    com.google.cloud.spanner.jdbc.ConnectionPropertiesFileGenerator + + ${project.basedir}/documentation/connection_properties.md + test false - -
    +
    diff --git a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java index 052e4dce4c46..8d7b7e432b40 100644 --- a/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java +++ b/java-spanner-jdbc/src/test/java/com/google/cloud/spanner/jdbc/ConnectionPropertiesFileGenerator.java @@ -28,6 +28,7 @@ public class ConnectionPropertiesFileGenerator { public static void main(String[] args) throws IOException { + String filename = args.length > 0 ? args[0] : "documentation/connection_properties.md"; StringBuilder builder = new StringBuilder("# Supported Connection Properties\n\n") .append( @@ -57,8 +58,7 @@ public static void main(String[] args) throws IOException { .append(connectionProperty.getContext()) .append(" |\n"); } - try (BufferedWriter writer = - new BufferedWriter(new FileWriter("documentation/connection_properties.md"))) { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) { writer.write(builder.toString()); } }
    Commits